proc f[t] (x:t, y:int) { print y; h x; }
You will note this function is polymorphic with one type
argument t, it accepts a single argument of tuple type t * int.
This form supports an extension to curry form:
proc f[t] (x:t) (y:int)
{
print y; h x;
}
which is short hand for
fun f[t] (x:t): t -> (int -> void) =
{
proc g(y:int) =
{
print y; h x;
}
return g;
}
Procedures also support lambda abstraction:
(proc (x:int, y:int) { print y; h x; }) (1,2);
A special form can be used for procedures with unit argument:
{ print "Hello"; endl; }
is a procedure with unit argument, and is short hand for:
(proc(){print "Hello"; endl; })
You should note very carefully the following
are NOT equivalent:
proc f(){ print "Hello"; endl; }
val f = { print "Hello"; endl; }
The first line defines a procedure f, but does not
form a closure. The second line stores a closure of
an anonymous procedure into value f. Although any
application of either f is equivalent, the lookup
rules for variable and function names are distinct.
Procedure names can be overloaded, and lookup choses
the right procedure to use in an application based
on the procedure argument.
Variable names, even if used applicatively, are never overloaded and do not participate in overload resolution.
Felix also allows procedures to provide pre-conditions. Here is an example:
proc f(x: int, y:int when x+y>0)
{
print (x + y); endl;
}