Reputation: 3128
So I read that every function in SML
has one argument and one
result. But I saw examples like:
fun foo x y = x + y;
fun goo x y z = 5;
Those examples make me think that they get more than one argument. The signatures:
val foo = fn : int -> int -> int
val goo = fn : 'a -> 'b -> 'c -> int
The only possible explanation that I can think of, is "syntactic sugar", although I'm not sure. What could be the explanation to this?
Upvotes: 1
Views: 196
Reputation: 317
There is indeed some syntactic sugar involved. If I remember correctly,
fun foo x y = x + y
is just syntactic sugar for
val rec foo = fn x => (fn y => x + y)
So this definition does in fact define a function foo
that takes a single argument x
of type int
and returns a function of type int -> int
. So the function application foo 5
returns a function:
fn y => 5 + y
This returned function can of course also take an argument. This is what looks like a second argument. But notice that this argument is not an argument of foo
but an argument of the result we get when applying foo
to its single argument.
Upvotes: 1
Reputation: 45740
Although your examples seem to take multiple arguments, they actually take one argument at a time.
foo 1
returns a function that takes y
as an argument, then when you apply y
, the function evaluates.
goo 1
returns a function that takes y
, which when given returns a function that takes z
, which when given allows the function to evaluate.
This allows you to easily partially apply a function by giving it less arguments than it asks for:
val f = foo 1 (* Returns a function *)
val returnVal = f 2 (* Both arguments were given, so the function is fully applied and evaluates *)
When combined with functions like map
or List.filter
, you can make nice readable code:
val keepNegatives = List.filter isNeg
keepNegatives [~1, ~2, 1, ~3]
> [~1, ~2, ~3]
Where isNeg
is a predicate that checks if a number is negative, and List.filter
is a function that keeps elements from a collection that satisfy the given predicate.
Upvotes: 3