Generating random numbers without Cmd

I was bored so I made a hacky way to generate random numbers without using Cmd:

https://ellie-app.com/9yQqJKWS2Tta1

It works by defining this Elm function:

generate : D.Value -> Float
generate =
    D.decodeValue (D.field "n" D.float) >> Result.withDefault 0

and this object which is sent via flags and stored in the model:

{
    get n() {
        return Math.random();
    }
}

Don’t do this in production code; it’s extremely hacky

That’s a clever solution. However it will break the referential transparency of Elm (ie. the promise you get from the lack of side effects that all expressions will, given the same inputs, evaluate to the same output). You’ve broken that which is why your expression generate model.obj returns different results even though you’re giving it the same input.

However you don’t need that to avoid Cmd, you can just pass a ‘seed’ in as a flag and then use Random.step. The issue with that is that Random.step will return the random value you have generated and the new seed, so you have to remember to update the ‘seed’ that is somehow stored in your model.

5 Likes

I expected to break this program after compiling it with --optimize and minifiying it using uglify.js and the usual options, but it still works. It seems, according to the documentation of uglify.js, that calls to pure functions are removed, when the result is not used. I miss an optimization, which replaces the call to pure functions with the result, at least for simple types. This seems not to be supported by uglify.js. Are there any options I miss, or other tools, which support this?

Breaking referential transparency seems pretty problematic - I can imagine some ugly uses of this non-feature.

I have no idea how uglify determines whether a function is pure or not. In any case, the result is used. The result of generate is used to set the num field on the model.

However, it wouldn’t surprise me if at some point, some optimisation would indeed break this scheme, just not in this simple case. For example, if you called it twice to generate two random numbers the optimiser in the Elm compiler might recognise the two calls as a common sub-expression.

Prepack sounds like what you want!

It’s given in the command-line by --compress 'pure_funcs="F2,F3,F4,F5,F6,F7,F8,F9,A2,A3,A4,A5,A6,A7,A8,A9",pure_getters,…, there is no automatic detection.

Thanks for the suggestion. Unfortunately Prepack is unable to parse the Javascript generated by Elm and the development is stopped at the moment.