Open paulyoung opened 5 years ago
Currently there is no way, although you can at least use an anonymous function and write
> func f(g : (Text, Text) -> Text) : Text = g ("foo","bar");
let f : ((Text, Text) -> Text) -> Text = func
> f(func (x,y) = x # y);
"foobar" : Text
Note that type inference actually allows you to write the lambda without extra type annotations.
Whether we want a shorthand like (#)
or op #
is up for @rossberg to decide, but don't hold your breath – the anonymous function form isn’t too bad if you compare it to the right other languages…
I'd be fine with adding (<op>)
as sugar for lambdas. The main problem, though, is that they are syntactically ambiguous when the same operator can be either unary or binary -- e.g., what's (-)
? Both Haskell and Ocaml use some really ugly hack for that distinction, which only applies to -
, but Mtk has more ops like that. I suppose we could make the short form core syntax and perform some form of overloading for it, but that's a bit less pretty.
~deleted, misread something~
I guess saying (★)
is, by construction always the binary form is one option.
Do we then also want sections? (★ 5)
?
It would be a bit odd if there was a shorthand for binary but not unary. One way to support both are mixfix forms like (- _)
and (_ - _)
-- I think Scala does this. That would also more naturally extend to sections, though sections are a bit questionable in a language that does not even have currying (and rare anyway).
Sections might also be tricky with regard to evaluation order: does (_ + foo())
call foo()
now and once, or does it call foo()
only when (_ + foo())
is applied?
Scala allows the _
in all kinds of places which can have confusing/surprising consequences so it's generally considered a mistake in their community.
In PureScript we added the section syntax for specific syntactic constructs with a straight-forward desugaring.
For example (_ + f x) = \$1 -> $1 + f x
and { foo: _, bar: _ } = \$1 $2 -> { foo: $1, bar: $2 }
and we've generally been happy with those. (Another commonly used one replaces Haskell's LambdaCase)
case _ of ... = \$1 -> case $1 of ...
So in PureScript (_ + f x) = \$1 ->( $1 + f x)
and not (_ + f x) = let y = f x in \$1 ->($1 + y)
?
In partiuclar, (f x + _) ≠ (+) (f x)
?
I guess the conclusion is: Let’s not do sections for now.
So back to the question of how to deal with (-)
being either binary or unary?
Yes to all of those.
If you had sections (- _)
could be the unary one and (-)
or (I don't like this one) (_ - _)
the binary one.
EDIT: I just saw Andreas already mentioned all of those... don't mind me
I created the following functions to work around not being able to pass the operators as arguments.
https://github.com/dfinity-lab/motoko/blob/8977c86eedbe96131106d742e53663aaa1c0ca3f/stdlib/int.mo#L4-L6
https://github.com/dfinity-lab/motoko/blob/8977c86eedbe96131106d742e53663aaa1c0ca3f/stdlib/nat.mo#L5-L7
https://github.com/dfinity-lab/motoko/blob/8977c86eedbe96131106d742e53663aaa1c0ca3f/stdlib/text.mo#L2-L4
This way they can be used with
Array.foldr<Text, Text>(Text.append, "", xs)
andArray.foldr<Nat, Nat>(Nat.add, 0, xs)
Is there currently a way to, or do we expect to be able to do, something like
Array.foldr<Text, Text>((#), "", xs)
andArray.foldr<Nat, Nat>((+), 0, xs)
at some point?