Specifiy allowed or forbidden behavior of Functions
I think we should make some statements around what Functions are allowed to do and not, as part of our resolver spec.
In particular, I think we should
- define functions to be deterministic
- forbid functions to have side effects
I had to do some work to account for nondeterministic/impure functions, so forbiding them will simplify things a bit. But aren’t there use cases which do require them? How would you write this, for example? (Different localizations may define different number of synonyms.)
greeting = { RANDOM(3) ->
[1] Greetings, {$userName}!
[2] Hello, {$userName}!
*[3] Hi, {$userName}, and have a nice day!
}
I'd prefer to see functions defined as being deterministic with no side effects - because of the principle of least power, and considerations for the different implementations I'm working on, several of which assume pure functions only :-)
I can see the use case for functions like RANDOM, but also lots of problems. For example, for some implementations you are going to have a very hard time implementing RANDOM at all - for example elm-fluent which works by compiling to Elm, which is a pure functional language. So if you have usages of RANDOM in your FTL messages, this just isn't going to work if you try to use these messages via elm-fluent or any similar implementation, and so it would probably be a bad idea to encourage use of that kind of function.
I can think of one work-around for implementing greeting above:
greeting = { $alternative ->
[1] Greetings, {$userName}!
[2] Hello, {$userName}!
*[3] Hi, {$userName}, and have a nice day!
}
.alternative-count = 3
The application would have to retrieve the greeting.alternative-count value, convert that to an integer, then generate an appropriate random number and pass that to the greeting message as the $alternative argument.
So
- you could only do random numbers with the cooperation of the application code. Given that random number generation really is a side effect, and we do not expect translation messages to be able to do any other side effects like writing to DB etc., this seems reasonable.
- it's not very pretty, but if you don't need it that often it's perhaps not too bad.
Thank you, your solution looks nice (well, nicer than those I thought about). And if a message needs several random numbers (don’t know why), it can request a bigger number and call DIV/MOD to split it up.
And… aside from RANDOM, I can’t think of another impure function that would be useful to a translator.