ExpandCollapsePrev Next Index

+ 11.1 Application and call operators

+ 11.1.1 Operator whitespace

You may have noticed that you can write:

  fflush stdout;

which is equivalent to

  fflush (stdout);

Parentheses are not required for function application or procedure calls, just for grouping. It's fun to call juxtaposition "operator whitspace".

+ 11.1.2 Operator dot

Those with an OO background may find this more pleasing:

  val name = stdin.readln.strip;

It means exactly the same as before, the operator . is nothing more than reverse application. Postfix application binds more tightly than prefix application so

  f x.g

means to apply g to x first, then f to the result.

+ 11.1.3 Operator dollar

And those with a Haskell background will readily understand that in

  val name = strip $ readln $ stdin;

the {$} is just a low precedence forward application, so it is also the same as before. It is typically used for procedural commands to save writing brackets around arguments:

  println$ "Hello "+name; // println ("Hello"+name)

because whitespace application has a higher precedence than infix +.

+ 11.1.4 Operator pipe

A low precedence left associative reverse application operator:

  val name = stdin |> s readkb |> strip;

+ 11.1.5 Operator hash

Finally if a function takes only the unit argument {()}: you can use the very high precedence prefix # operator to call it:

  fun pi() => 22.0/7.0;
  println$ "Pi=" + str #pi;

[See next chapter for explanation of unit type]

+ 11.1.6 Implied procedure call

And there's a special case for procedures with no arguments:

  proc doit() { println "Done"; }
  doit;

allowing you to omit the unit argument. This is an example of type based syntactic sugar which is used a quite a bit in Felix to provide shortcuts. A statement which is an expression of a type other than void is not normally allowed. In this special case, however, if the type is {unit->void} then the compiler translates it into an application of the expression to {()}.