gleam
gleam copied to clipboard
Using curried functions with const
Hi! So happy to have a new functional programming language! I'm not sure where I'm supposed to ask, so I'm opening an issue here 🙂 Sorry for inconvenience if it's the wrong place, feel free to close the issue or anything and point me to the right place!
I'm trying to play with curried functions in Gleam, and I don't understand some design decisions. I can assign a function to a constant, but I can't assign a function return value to a constant.
fn example(a) {
fn(b) {
a + b
}
}
const c = example(1) // This is not allowed
const d = example // This is allowed
Here in both case, the code seems valid, but the first case is forbidden by the compiler. Is there any specific reason to not allow it? It seems to me like a logical case, and avoid something like :
fn example(a) {
fn(b) {
a + b
}
}
fn c(b) {
example(1, b)
}
I believe the issue you are running into is with what the const keyword is doing. const values need to be known (and I believe are inlined?) at compile time so calling a function is not allowed. The error message is definitely confusing/misleading in this case (it looks like Gleam treats this as an invalid syntax error). Gleam doesn't have any special behavior about currying/curried functions (i.e. Gleam does not automatically curry functions in any way). So to run the example you have you would want to use let bindings within a function declaration like this:
import gleam/io
fn example(a) {
fn(b) { a + b }
}
pub fn main() {
let c = example(1)
let d = example
io.debug(c(2)) // 3
io.debug(d(3)(4)) // 7
}
Oh, I get your point. So as I was expecting, const is a special thing in the compiler, and I was wondering if it could come from some Erlang interop or anything else.
Actually, the pattern with curried function is something I use oftentimes (I'm coming from a Haskell/Elm/PureScript background for context) when I want to hide some configurations in child functions.
For example, when dealing with flex items in frontend, I could have a function named flex not exposed, and two functions row and column defining some configuration and reusing flex (because in the end, it's the same thing in the browser).
fn flex(direction: String) {
fn (children: List(Element(a))) {
// Render the correct HTML here.
}
}
pub const row = flex("row")
pub const column = flex("column")
And in such case, the idea is to expose only the last functions, and hide everything else. But I suppose I have to use the first version I wrote earlier, with fn row(children) { flex("row", children) } instead of using curried functions.
Gleam isn't a scripting language, a language with compile time code execution, or a language with call-by-need evaluation, so there's no way to evaluate code in constants. Only literals are possible.