    Author: Richard A. O'Keefe <ok(at)cs(dot)otago(dot)ac(dot)nz>
    Status: Final/R12B-4  Implemented in OTP release R12B-4
    Type: Standards Track
    Erlang-Version: OTP_R12B-4
    Created: 08-Aug-2008
    Post-History:
****
EEP 23: Allow variables in `fun M:F/A`
----

Abstract
========

`fun M:F/A` should allow `M`, `F`, and/or `A` to be a variable.

Specification
=============

The form `fun M:F/A` currently requires `M` to be an atom,
`F` to be an atom, and `A` to be a non-negative integer.
This is generalised to allow any or all of them to be
variables.

Motivation
==========

Representing functions by tuples `{M,F,A}` is now deprecated.
Yet there are times when some of this information is not
available until run time.  For example, a behaviour's author
might wish to refer to the `start/0` function in the Callback
module, but there might be any number of Callback modules at
run time.

It is absurd that the module name and function name in a call
of the form `M:F(E1, ..., En)` may be either atoms or variables,
but that they may not be variables in `fun M:F/A`.

It turns out that `fun M:F/A` is currently implemented as a call
to `erlang:make_fun(M, F, A)`, so the ability to create such
funs given run-time data already exists.  All that is missing
is to wrap some syntax around it.

Rationale
=========

The gap that's being filled here is one that has been felt in
practice.  See a September 2008 thread in the Erlang mailing list.
The proposal generalises an existing form, but not more than the
existing function call syntax has already been generalised.

It is perhaps the limits of this proposal that need explaining.

First, the extension is from constants to constants or variables,
not to arbitrary expressions.  This is mainly to avoid confusing
parsers and people.  The effect of `fun (E1):(E2)/(E3)` can be had
by writing `M = E1, F = E2, A = E3, fun M:F/A`, so there is no loss
of expressiveness.  Since Erlang's equivalent of a lambda form
begins with "`fun (`", `fun (E1):...` would be tricky to parse and
very confusing to people.

Second, the extension is for `fun M:F/A` only, and not for `fun F/A`.
That's because there is no `erlang:make_fun/2` to call; the
implementation of `fun F/A` is surprisingly tricky and involves
creating a special-purpose glue function.  For many purposes,
`fun ?MODULE:F/A` will serve instead.

Backwards Compatibility
=======================

All existing Erlang code remains acceptable with unchanged
semantics.  No new functions or instructions are added, so
BEAM files produced with the new parser will work in older
releases.

Reference Implementation
========================

The auxiliary file [eep-0023-1.diff][]
is a patch file to be applied to erl_parse.yrl.
The patched file has been checked by yecc, which is happy
with it, and the resulting .erl file compiles cleanly.
However, that's all the testing that has been done.

All that the implementation does is to

1. accept `fun M:F/A` where `M`, `F`, and `A` are constants or
   variables,
2. generate the same abstract syntax term that was
   generated in the past when they are all constants,
3. pretend that `erlang:make_fun(M, F, A)` had been written
   when at least one is a variable.
Only the parser is involved.

[eep-0023-1.diff]: eep-0023-1.diff
    "Diff to apply to erl_parse.yrl"

Copyright
=========

This document has been placed in the public domain.

[EmacsVar]: <> "Local Variables:"
[EmacsVar]: <> "mode: indented-text"
[EmacsVar]: <> "indent-tabs-mode: nil"
[EmacsVar]: <> "sentence-end-double-space: t"
[EmacsVar]: <> "fill-column: 70"
[EmacsVar]: <> "coding: utf-8"
[EmacsVar]: <> "End:"
