suggestions icon indicating copy to clipboard operation
suggestions copied to clipboard

Function capture with more, or less, than one argument.

Open CrowdHailer opened this issue 5 years ago • 3 comments

A stupid example

import gleam/list

pub fn add(a, b, _message) {
    a + b
}

pub fn demo(){
    list.fold([], 0, add(_, _, "counting"))
}

Probably needs a way to switch argument order.

list.fold([], 0, add(_1, _2, "counting"))
list.fold([], 0, add(_2, _1, "counting"))

The above doesn't handle the case of 0 arguments. sometimes you need a zero arity funcation that returns a value you already have.

let func = fn() { add(1,2,"counting") }
let func = &add(1,2,"counting")

Borrowed "&" from elixir syntax don't massivly like it.

A suggestion that a havent though through is. could the compiler make the following work. if it sees a 0 arg function that returns an Int and the caller gives it an Int it knows to treat that Int as a result.

fn outer(fn() -> Int) {
}

outer(5)

This would be really useful in result unwrap where you don't always want to eagerly calculate the failure value

let my_result = do_some_maths()
let value = result.unwrap(my_result, 0)
let value = result.unwrap(my_result, fn_that_calcs_the_fallback)

CrowdHailer avatar May 13 '20 06:05 CrowdHailer

What problem does this solve that fn(a, b) { run(b, a) } does not? I would like to keep the core language small and would like to avoid having multiple ways of writing the same thing.

A suggestion that a havent though through is. could the compiler make the following work. if it sees a 0 arg function that returns an Int and the caller gives it an Int it knows to treat that Int as a result.

How would this be typed?

This would be really useful in result unwrap where you don't always want to eagerly calculate the failure value

An result.unwrap_with: fn(Result(a, e), fn() -> a) function seems like a more straightforward solution that doesn't introduce any more complexity to the language to me. We can revisit the names unwrap and unwrap_with as I'm not sure they're the best here.

lpil avatar May 13 '20 08:05 lpil

What problem does this solve that fn(a, b) { run(b, a) } does not?

It's no different to the one arity case. Apart from the fact that the one arity case is a bit more common because of pipes. This is more just experience from me using gleam, I have twice typed foo(_, _) and then remembered it doesn't work.

An result.unwrap_with: fn(Result(a, e), fn() -> a) function seems like a more straightforward solution

It is simpler and I would understand if I saw that. If you assume referential transparency the type fn() -> a is equivalent to a.

Note this issue was more speculative and I decided to put it down as a place to hold my thoughts. My gut feeling is I really like making fn() -> a == a. But I need to mull it over a bit further.

CrowdHailer avatar May 13 '20 09:05 CrowdHailer

Note this issue was more speculative and I decided to put it down as a place to hold my thoughts.

Of course, thank you.

My gut feeling is I really like making fn() -> a == a. But I need to mull it over a bit further.

This is how lazy languages work! It works well for Haskell, but there are many implications in terms of typing, implementation, and the style of programming. It would be quite different from Erlang.

lpil avatar May 13 '20 09:05 lpil