【问题标题】:Generate random UUIDv4 with Elm使用 Elm 生成随机 UUIDv4
【发布时间】:2021-12-29 11:36:16
【问题描述】:

我正在尝试在循环中生成随机 UUID 的 v4:

    randomUuid =
         -- TODO: find a way to generate random uuid for variableId

    updatedVariables =              
         group.variables |> List.map (\variable -> { variable | id = randomUuid })

我阅读了elm/randomelm/uuid 的文档,但找不到如何在不使用种子的情况下生成 UUID。

我唯一能做的就是:

newUuid : Random.Seed -> ( String, Random.Seed )
newUuid seed =
    seed
        |> Random.step UUID.generator
        |> Tuple.mapFirst UUID.toString

我将 elm/random 视为 independentSeed 函数,但我无法让它生成种子。

我试图用randomUuid 实现的节点等效是:

const { uuid } = require('uuidv4');

const randomUuid = uuid();

我觉得我可能在这里遗漏了 Elm 中的一些重要概念,但我自己无法弄清楚。任何帮助或指针将不胜感激。

【问题讨论】:

    标签: random uuid elm


    【解决方案1】:

    生成随机值是一种效果,因此纯语言不能仅仅执行它。

    但是,有一个纯粹的随机性版本,它使用随机种子。它们的特性是,每次使用相同的种子生成值时,都会得到相同的值 - 因此这只是一个纯计算,在纯上下文中完全可以。

    Elm 允许您以Cmd 的形式执行效果,这是您从initupdate 函数返回的东西。所以你有一个选择是总是在你需要它之​​前返回Random.generate GotANewUUID UUID.generator,然后在你处理GotANewUUID msg 时执行你的计算。

    另一个选项是跟踪随机种子。你要么从一个确定性的Random.initialSeed 开始(可能不是你想要的UUID,因为它们在你的程序的每次运行中都是完全相同的),或者在你的init 函数中返回Random.generate GotNewSeed Random.independentSeed。然后将种子存储在模型中。 每次需要生成新的 UUID 时,请使用上面的 newUuid 函数,确保存储新的种子。

    这是一个例子:

    import Random
    import UUID
    
    type alias Thing = 
        { id : String
        -- , some other stuff
        }
    
    type alias Model =
        { seed : Random.Seed
        , stuff : List Thing
        }
    
    type Msg
        = GotNewSeed Random.Seed 
        | AddAThing Thing
        | AddABunchOfThings (List Thing)
    
    init : () -> (Model, Cmd Msg)
    init flags =
        ({ seed = Random.initialSeed 567876567 
        -- Let's start with a deterministic seed
        -- so you don't need to deal with Maybe Seed later
         , stuff = []
        }, Random.generate GotNewSeed Random.independentSeed
        )
    
    update : Msg -> Model -> (Model, Cmd Msg)
    update msg model =
        case msg of
            GotNewSeed seed ->
                ({model | seed = seed}, Cmd.none)
        
            AddAThing thing ->
                let
                    (newId, newSeed) = 
                         newUuid model.seed
                in
                ({ model | stuff = { thing | id = newId } :: model.stuff
                 , seed = newSeed }
                , Cmd.none
                )
    
             AddABunchOfThings things ->
                 let
                     (newStuff, newSeed) =
                          List.foldl (\thing (stuff, seed) ->
                              newUuid seed
                                  |> Tuple.mapFirst (\id -> 
                                      { thing | id = id } :: stuff
                                  )
                          ) (model.stuff, model.seed) things
                  in
                  ({model | stuff = newStuff, seed = newSeed}, Cmd.none)
    
              
     
    
    

    【讨论】:

    • 非常感谢您的帮助!由于您的解释,我对函数式编程有了更好的理解。并且使用 newUuid List.foldr 是循环的关键,同时从同一个种子生成新的 id。谢谢!
    猜你喜欢
    • 2016-05-16
    • 1970-01-01
    • 2014-05-21
    • 2016-01-03
    • 2021-06-19
    • 2015-03-14
    • 2013-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多