ExpandCollapsePrev Next Index

+ 9.1 Application syntax

So far we've applied a function like in C.

  fun sum : int * int -> int = '$1+$2';
  fun neg : int -> int = '-$1';
  println ( sum (1,neg (2)) );

-1

However, parens in Felix simply provide grouping: functional style application does not require them:

  println ( sum (1,neg 2) );

-1

The parens around the sum argument are required. Hey, that's a typo you say! sum has two arguments!

No it doesn't. sum has a single argument which is of the type of a cartesian product {int * int}. The parens are only required because operator whitespace, which is used for application, has a higher precedence than operator comma, which is used for tuple formation. Here's the proof:

  var x = 1, neg 2;
  println ( sum x );

-1

There's another syntax for application, using operator dot:

  println (1,2.neg).sum;

-1

As you can see, operator dot is reverse application and has a higher precedence than operator whitespace. This operator gives expressions and "OO" feel, and the left to right ordering of application is arguably more natural to programmers than mathematical notation.

Felix provides yet another application operator:

  println$ sum$ 1, neg 2;

-1

Operator dollar is a forward infix operator like whitespace but it has very low precedence and is right associative. I commonly write the {$} hard up against the left hand function name if the LHS is an identifier, which gives the appearance of a command where the {$} is part of the name.

Operator dollar was stolen from Haskell.

In combination, these three operators make it possible to write many expressions without any parentheses. However there's one more which is useful for that:

  fun zero : 1 -> int = "0";
  println$ zero();
  println$ #zero;

0
0

If the argument is () you can use the very high precedence operator hash. Operator hash is higher precedence than operator dot. It gives the feel of a specially named value, which makes sense because pure functions of unit argument must always return the same value, that is, they're constant functions.

+ 9.2 Call syntax

Although we didn't tell you the proper syntax for a call is:

  call println 1;

1

However the operator call can be left out. Felix then sees application syntax. However Felix does not allow you to discard values the way C does. So if it sees a whitespace application which would discard a value if the LHS term of the application were a function, Felix assumes it is a procedure. This means you can do this:

  proc hello : 1 = '::std::cout<<"hello"<<::std::endl;'
    requires header '#include <iostream>'
  ;
  call hello ();
  hello ();
  hello;
  call hello;

hello
hello
hello
hello

All these four calls are equivalent. Eliding the trailing () is inspired by Pascal.

There are some things resembling calls we will meet later.