Emojicode Documentation 1.0 beta 2

Callables

Emojicode supports a type called callables. Callables are like methods (or more generally functions) that can be passed like any other object.

Type

The type of a callable is denoted using this syntax:

callable-type ⟢ πŸ‡ [type-list] [return-type] [error-type] πŸ‰
type-list ⟢ type | type type-list

Each of the types provided before the return type stands for one argument of that type. The return type is optional. If no return type is specified the callable does not return a value. An error-type can be specified.

Examples:

πŸ‡πŸ”’βž‘οΈπŸ”‘πŸ‰  πŸ’­ Takes an integer argument and returns a string
πŸ‡βž‘οΈπŸ”£πŸ‰  πŸ’­ Takes no arguments and returns a symbol
πŸ‡πŸ‰  πŸ’­ Takes no arguments and does not return a value.
πŸ‡πŸ”’βž‘οΈπŸ”‘πŸš§πŸš§πŸ‰  πŸ’­ May raise a 🚧

Calling a Callable

Callables are called using this syntax.

callable-call ⟢ ⁉️ expression [arguments] mood

The first expression must be a callable.

Example of calling a callable:

πŸ’­ greet is of type πŸ‡πŸ”‘πŸ‰
⁉️ greet πŸ”€BobπŸ”€β—οΈ

An error-prone callable must be handled like any error-prone call by using πŸ”Ί, 🍺 or πŸ†—.

Closure

Closures are blocks of code that are not immediately executed but remember the context in which they were created, i.e. the variables and the context of the method, and can be passed around. The type of a closure is, of course, a callable.

A closure is created by a block of code that appears when an expression is expected. This means that every code block that is not part of an β†ͺ️, πŸ™…, or πŸ™…β†ͺ️ πŸ”‚ or πŸ” statement or a method or initializer declaration, is a closure.

In contrast to a normal code block, a closure can define arguments and a return type similar to a method.

Formally, its syntax is:

closure ⟢ πŸ‡ [🎍πŸ₯‘] [closure-parameters] [return-type] statements πŸ‰
closure-parameters ⟢ variable type [closure-parameters]

We can define a very simple closure that does not capture any context like this:

πŸ‡ name πŸ”‘
  πŸ˜€ πŸ”€It is a pleasure to welcome the honorable 🧲nameπŸ§²πŸ”€ ❗️
πŸ‰ ➑️ greet

⁉️ greet πŸ”€LindaπŸ”€β—οΈ

Running this code would print:

It is a pleasure to welcome the honorable Linda

Capturing Variables and Context

Hint

You should be familiar with Borrowing and Escaping Use before reading this section.

Let’s take a look at this example:

πŸ‡ 🍀 πŸ‡
  πŸ‡β—οΈπŸ’š g πŸ‡πŸ”‘βž‘οΈπŸ”‘πŸ‰ πŸ‡
    πŸ˜€ ⁉️g πŸ”€DARTH VADERπŸ”€β—οΈβ—οΈ
  πŸ‰
πŸ‰

🏁 πŸ‡
  πŸ”€LUKEπŸ”€ ➑️ πŸ–πŸ†•var

  πŸ’šπŸ‡πŸ€ πŸ‡ gπŸ”‘ βž‘οΈπŸ”‘
    ↩️ var
  πŸ‰β—οΈ
πŸ‰

Running the above code will print LUKE. In the above example the value var was declared and assigned outside the closure. This is called a captured variable. Much the same, you can capture the πŸ‘‡ context in a closure.

Actually, however, we need to distinguish between escaping and non-escaping closures. By default, every closure is non-escaping and cannot be used as an escaping value. To define an escaping closure the πŸ‡ must be immediately followed by 🎍πŸ₯‘. When creating a thread, for instance, an escaping closure is required:

πŸ†•πŸ§΅ πŸ‡πŸŽπŸ₯‘

πŸ‰β—οΈ

Escaping closures can capture variables, just like non-escaping closures. However, in escaping closures, the captured variables are constant. In non-escaping closures, the captured variables can be modified, as seen in this example:

🏁 πŸ‡
  πŸ”€LUKEπŸ”€ ➑️ πŸ–πŸ†•var

  πŸ˜€ var❗️

  πŸ’šπŸ‡πŸ€ πŸ‡ gπŸ”‘ βž‘οΈπŸ”‘
    g ➑️ πŸ–var
    ↩️ πŸ”€DEATH STARπŸ”€
  πŸ‰β—οΈ

  πŸ˜€ var❗️
πŸ‰

The output of the above code (πŸ’šπŸ‡πŸ€ is defined in a previous example) will be:

LUKE
DEATH STAR
DARTH VADER

var was modified inside the closure and is set to the value g passed into the closure, which in our case was β€œDARTH VADER”. This does not work with an escaping closure.

The following example demonstrates capturing the πŸ‘‡ context and modifying an instance variable:

πŸ‡ πŸ•΅ πŸ‡
  πŸ–πŸ†• name πŸ”‘

  πŸ†• 🍼 name πŸ”‘ πŸ‡πŸ‰

  ❓ πŸ“› ➑️ πŸ”‘ πŸ‡
    ↩️ name
  πŸ‰

  ❗️ πŸ› title πŸ”‘ ➑️ πŸ‡πŸ”‘πŸ‰ πŸ‡
    ↩️ πŸ‡πŸŽπŸ₯‘ a πŸ”‘  πŸ’­ Returning lets the value escape
      πŸ”€πŸ§²title🧲 🧲aπŸ§²πŸ”€ ➑️ πŸ–name
    πŸ‰
  πŸ‰
πŸ‰

🏁 πŸ‡
  πŸ†•πŸ•΅ πŸ”€Arthur LemmingπŸ”€β—οΈ ➑️ pi
  πŸ›pi πŸ”€DrπŸ”€β—οΈ ➑️ nameSetterDr
  ⁉️nameSetterDr πŸ”€Jessica JonesπŸ”€ ❗️
  πŸ˜€ πŸ“›pi❓ ❗
πŸ‰

Note that you can capture the object context of a class type in both non-escaping and escaping closures and also modify its instance variables. The context of value types and enums, though, can only be captured in non-escaping closures. Thus the above sample would not compile if πŸ•΅ was a value type.

The example below shows how the instance variable of a value type can be captured in a non-escaping closure:

πŸ•Š 🌼 πŸ‡
  πŸ–πŸ†• string πŸ”‘ ⬅️ πŸ”€YODAπŸ”€

  πŸ†• πŸ‡πŸ‰

  πŸ–β—οΈ β˜„οΈ πŸ‡
    πŸ’šπŸ‡πŸ€ πŸ‡ gπŸ”‘ βž‘οΈπŸ”‘
      g ➑️ πŸ–string
      ↩️ πŸ”€STORMTROOPERπŸ”€
    πŸ‰β—οΈ
  πŸ‰
πŸ‰
← Previous Next Up: β€œPackages” β†’
Something not quite right? Improve this page