.. _readme-firstClassFns:

===============================
First-class Functions in Chapel
===============================

This README describes some initial support that we have added to the
compiler for first-class functions in Chapel.  This mechanism should
be considered a stopgap technology until we have developed and
implemented a more robust story, which is why it's being described in
this README rather than the language specification.


Manipulating first-class functions
----------------------------------

Functions defined with parentheses may be captured as values by
referring to them by name without parentheses.  Once captured, these
values may be passed around as other value types.

For example:

.. code-block:: chapel

  proc myfunc(x:int) { return x + 1; }
  var f = myfunc;
  writeln(f(3));  // outputs: 4

To be captured, a function must not be any of the following:

- A generic function (all captured functions must be fully-qualified
  with no generic arguments)

- A function with special return types (type, param)

- An iterator

- The method of an object

- An operator

- An overloaded function

Rationale. Generic functions would require manipulating generic,
uninstantiated types, which is currently not available in Chapel.
Functions with compile-time return types like type and param would
require the ability to have param classes, to fit with the current
implementation. Param classes are not currently part of Chapel.
Iterators would require a new type of capture, one that works
similarly to the current implementation but respects the yielding that
occurs inside an iterator. Method capture requires the currying of
the object as the first argument to the first-class function.
Operators and overloaded functions require a type-based multiple
dispatch mechanism.


Lambda functions
----------------

Lambda functions are anonymous first-class function objects. In other
words, they are expressions rather than formally-defined named
functions. They are available with the following syntax:

.. code-block:: none

  lambda-declaration-expression:
    lambda argument-list return-type_opt function-body

where ``lambda`` is a Chapel keyword and ``return-type_opt`` is an optional
return-type.

For example:

.. code-block:: chapel

  var f = lambda(x:int, y:int) { return x + y; };
  writeln(f(1,2));  // outputs: 3

Lambdas can also "capture" variables that are defined outside of the
lambda by referring to them in the body of the lambda. These form a
"closure", a combination of a function and an associated execution
environment.  This closure captures the variables in such a way that
modifying them modifies the original variables (this is sometimes
called "capturing the variables by reference").  Currently a lambda
that captures variables can be used only while the activation records
of the functions that define these variables, if any, still exist
on the stack, i.e. while these functions are still executing.

Example. For example the following is acceptable:

.. code-block:: chapel

  proc myfunc() {
    var x = 3;
    var f = lambda() { x = 4; };
    f();
    return x;
  }

  writeln(myfunc());  // outputs: 4

whereas having ``myfunc()`` return its ``f`` variable is not supported.


Function type signatures
------------------------

The types of first-class functions can be obtained by using
the 'func' type functions that are provided as follows:

.. code-block:: chapel

  // no arguments, void return type (returns no value)
  proc func() type

  // no arguments, the return type is 'rettype' 
  proc func(type rettype) type

  // argument types are 'argtypes'
  proc func(type argtypes...?n, type rettype) type

For example:

.. code-block:: chapel

  var f : func(void);  // A function with no arguments, no return value
  var f1: func();      // A shortcut for the above
  var g : func(int);   // A function with no arguments, returning int
  var h : func(bool, int); // A function with one bool argument, returning int


Future Directions
-----------------

Over time, we will be improving the support for first-class functions
and their syntax.  If you have specific feature requests or
suggestions, please let us know at: chapel_info@cray.com.
