How to conditionally update list items with random generator

Scenario 1

  • If an item in a collection was clicked, we would like to randomly change its properties. Color, scale etc.
  • Following code shows a failed attempt:
randomUpdate: Item -> Generator Item
-- implementation omitted for brevity.


updateItem: Id -> Seed -> List Item -> (List Item, Seed)
updateItem id seed = 
   List.map (\ item -> 
     if item.id==id then 
       Random.step (randomUpdate item) seed -- ERROR
     else 
       item
   )

Question

  • What would be a simple way to implement updateItem?

Scenario 2

  • I write quite a bit of code that deals with random numbers. Mostly for animations, games and generative art.
  • I start out by hard-coding values. And later, passing model & seed along the update chain
  • So functions requiring randomness can use them while updating both the model & seed.

Question

How to handle these scenarios when iteratively coding a project?

  1. Pass seed & model
  2. Wrap update methods in generators
  3. Or …?

FYI: For non-update scenario, I always prefer to write and combine Generators. The problem starts when I have to update existing values with them. Most of the time the update depth is 2 or 3 levels. Model → Collection → Record

Regards,
Jigar Gosar

About Scenario 1: if I understand correctly your issue, when you need to “carry over” something while looping you need to do a List.foldl, which in the end will produce a new list with updated (or not) items and a seed to save somewhere for the next round.

2 Likes

I would split the process into two steps:
click → save the cell coordinates we are modifying to the model and call generator
generator → produces message for cell update

type Msg
    = GotRandomColor Colors
    | Randomize


type alias Colors =
    { red : Int
    , green : Int
    , blue : Int
    }


colorsGenerator : Random.Generator Colors
colorsGenerator =
    Random.map3 Colors colorGenerator colorGenerator colorGenerator


colorGenerator : Random.Generator Int
colorGenerator =
    Random.int 0 255


generateRandomColors : Cmd Msg
generateRandomColors =
    Random.generate GotRandomColor colorsGenerator

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Randomize ->
            -- save position here
            ( model, generateRandomColors )

        GotRandomColor color ->
            ( { model | color = color }, Cmd.none )

Here is the Ellie link for a generator example

I made something similar for a snake game (using random to spawn an apple): Snake

P.S. an updated Ellie with a grid pattern - click on any square to change the color … not the most elegant code - but the point is splitting the process into 2 steps.

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.