Note: information on this page refers to Ceylon 1.0, not to the
current release.

Named arguments

This is the twelfth leg in the Tour of Ceylon. In the
previous leg we learnt about functions. This part builds
on that by covering Ceylon's support for calling functions using named
arguments.

Named arguments

Consider the following function:

void printf(Writer to, String format, {Object*} values) {
// ...
}

We've seen lots of examples of invoking a function or instantiating a class
using a familiar C-style syntax where arguments are delimited by parentheses
and separated by commas. Arguments are matched to parameters by their
position in the list. Let's see one more example, just in case:

This invocation protocol is called a named argument list. We can recognize a
named argument list by the use of braces as delimiters instead of parentheses.
Notice that arguments are separated by semicolons. We explicitly specify the
name of each parameter.

We usually format named argument invocations across multiple lines.

Iterable arguments

Since the parameter values is of type Iterable, we're allowed to abbreviate
this, leaving out the parameter name and the braces surrounding the iterable
construction expression:

However, it's far more common to use named arguments to build a complex
graph of objects. In this section we're going to meet some new features of
named argument lists, that make it especially convenient to build object
graphs.

First, note that the syntax we've already seen for specifying a named argument
value looks exactly like the syntax for refining a formal attribute. If you
think about it, taking into account that a function parameter may accept
references to other functions, the whole problem of specifying values for named
parameters starts to look a lot like the problem of refining abstract members.
Therefore, Ceylon will let us reuse much of the member declaration syntax
inside a named argument list.

It's legal to include the following constructs in a named argument list:

function declarations—specify the argument of a parameter that accepts a
function,

object (anonymous class) declarations—are most useful for specifying
the value of a parameter whose type is an interface or abstract class, and

getter declarations—lets us compute the value of an argument inline.

This helps explain why named argument lists are delimited by braces: the
fully general syntax for a named argument list is very, very close to the
syntax for a class, function, or attribute body. Notice, again, how flexibility
derives from language regularity.

Notice how we've transformed our code from a form which emphasized invocation
into a form that emphasizes declaration of a hierarchical structure.
Semantically, the two forms are equivalent. But in terms of readability,
they are quite different.

We could put the above totally declarative code in a file by itself and it
would look like some kind of "mini-language" for defining tables. In fact,
it's executable Ceylon code that may be validated for syntactic correctness by
the Ceylon compiler and then compiled to Java bytecode or JavaScript. Even
better, the Ceylon IDE will provide authoring support for our mini-language.
In complete contrast to the DSL support in some dynamic languages, any Ceylon
DSL is completely typesafe! You can think of the definition of the Table,
Column and Border classes as defining the "schema" or "grammar" of the
mini-language. (In fact, they are really defining a syntax tree for the
mini-language.)

Now let's see an example of a named argument list with an inline getter
declaration:

(Note that Observer<T> is assignable to Observer<Nothing> for any type
T, since Observer<T> is contravariant in its type parameter T. If this
doesn't make sense, please read the section on generics again.)

Of course, as we saw in the leg on functions, a better way to
solve this problem might be to eliminate the Observer interface and pass a
function directly:

Even though this looks like some kind of templating language, it's just an
ordinary expression.

There's more...

There's plenty of potential applications of this syntax aside from user
interface definition. For example, Ceylon lets us use a named argument list to
specify the arguments of a program element annotation. But we'll have to come
back to the subject of annotations in a future installment.

The next section introduces yet another way to specify an
argument to a function: comprehensions.