.. _readme-forwarding:

========================
Forwarding Methods Calls
========================

Chapel 1.15 includes a preview version of a method forwarding feature.
This feature allows a ``record`` or ``class`` to specify that certain
method calls will be forwarded to a particular expression. The most
typical use case is to forward methods to a particular field.

Why Forwarding?
---------------

While Chapel supports inheritance between classes as a way to reuse
method implementations, inheritance is not always appropriate. In
particular, inheritance has the drawback that it affects the types
of the classes and therefore changes what users can do with those
classes. Due to some of these drawbacks, there is a well-known design
pattern *composition over inheritance*.

The basic strategy for using composition instead of inheritance is to
declare a member field that stores the type that would be inherited from.
Then, declare methods that forward to the member field. This can allow
the implementation to be more flexible and re-usable. In particular,
changing how many classes participate in the implementation of a
particular type need not change its public interface or impact the users
of that type.

Besides these issues, composition is a more general strategy in Chapel
due to the following language design decisions:

 * records don't support inheritance.
 * multiple inheritance for classes is not supported.
 * inheriting a record from a class or a class from a record is not
   supported.

Composition can help in each of these cases where inheritance cannot
apply.

Example of Forwarding
---------------------

Suppose, for example, ``MyCircleImpl`` is a Chapel class, but the author
of that type wishes to present it as a record (say, ``MyCircle``).  Such
a division allows the type author to control what happens when the type
is copied and to manage the deletion of the class instances.

Consider the following example:

.. (comment) Note, these examples are tested here:
   test/classes/ferguson/forwarding/readme-forwarding-examples.chpl

.. code-block:: chapel

  class MyCircleImpl {
    var radius:real;
    proc area() {
      return pi*radius*radius;
    }
    proc circumference() {
      return 2.0*pi*radius;
    }
  }

  record MyCircle {
    var impl: MyCircleImpl;

    // forwarding methods
    proc area() {
      return impl.area();
    }
    proc circumference() {
      return impl.circumference();
    }
  }

Since writing these forwarding methods is repetitive and boring, it's a
good candidate for automation. The Chapel language allows automating the
creation of these forwarding methods by using the `forwarding` keyword.
For example, the following is equivalent to the previous ``MyCircle``
record.

.. code-block:: chapel

  record MyCircle {
    forwarding var impl: MyCircleImpl;
  }

The ``forwarding`` keyword instructs the compiler to forward method
invocations on a ``MyCircle`` that would otherwise not resolve to
the field ``impl``.

Using ``forwarding``
--------------------

Besides the ``forwarding var`` style, the ``forwarding`` syntax
can be applied to forward to a particular expression. For example,
one might wish to generate a different error in the event that ``impl``
is ``nil``:

.. code-block:: chapel

  record MyCircle {
    var impl: MyCircleImpl;

    proc getImplOrFail() {
      if impl == nil then
        halt("impl is nil");
      else
        return impl;
    }

    forwarding getImplOrFail();
  }

  var empty = new MyCircle(nil);
  empty.area(); // halts with "impl is nil"

Another direction that a user of ``forwarding`` might go is that they
might decide to only forward certain methods. For example, the following
are equivalent ways to forward only the ``area()`` method, assuming that
the only methods of ``MyCircleImpl`` are ``area()`` and
``circumference()``.

.. code-block:: chapel

  record MyCircle {
    var impl: MyCircleImpl;

    forwarding impl only area;
  }

.. code-block:: chapel

  record MyCircle {
    var impl: MyCircleImpl;

    forwarding impl except circumference;
  }

As with ``use``, ``forwarding`` supports comma-separated ``only`` and
``except`` lists.

Additionally, note that multiple ``forwarding`` declarations can be
specified.

Resolving Forwarded Methods
---------------------------

Forwarded methods resolve only when regular methods on a particular type
do not resolve. For example, in the above cases, if ``MyCircle`` declared
a ``area()`` method that could be called with no arguments, that method
would be called in preference to the forwarded method on ``MyCircleImpl``
that is available. Other than that, the forwarded methods participate
normally in the function resolution process. As with other ambiguous
function declarations, ambiguity errors will be reported at the call
site.

Note that special IO methods such as ``writeThis`` and ``readThis`` are not
forwarded since the compiler generates these for the type by default.
Similarly, a field accessor will not get forwarded if the class defines a
conflicting field or method name. Consider the example below:

.. code-block:: chapel

  record ArrayWrapper {
    var array: [1..0] int;

    proc shape {
      return 1;
    }

    forwarding array;
  }

The ``shape`` method above will resolve, meaning ``array.shape`` will not be
forwarded.

