Subscribe to get more articles about programming languages
Donate

Lambdas everywhere

colourful arrows

Almost all popular programming languages have a “lambda functions” feature. There are several closely related concepts:

  • anonymous functions (lambdas which might have a more verbose syntax)
  • closures (lambdas that capture parameters from outside scopes)
  • blocks (mostly similar to closures)
  • lambda expressions (same idea as lambda functions)

When anonymous functions are much like normal functions, but without a name, for example:

function (x) { return 2*x + 1; } // JavaScript 5 anonymous function

analogous lambda functions have a very concise syntax like:

x => 2*x + 1 // JavaScript 6 lambda function

Math notation

In math unnamed functions are often aliased to intermediate variables, for example:

x ↦ y
y = 2x + 1

which can be shortcut with:

x ↦ 2x + 1

This defines a function that multiplies x by 2 and then adds one to the result. Note the arrow sign which means “maps to”. Lambda syntax in many programming languages was inspired by that arrow.

In the lambda calculus a different notation is used for the same thing:

𝛌x.(2x + 1)

So a Greek letter lambda is used in front of arguments declaration, and a dot is used instead of an arrow to separate arguments from the function expression.

Lambda function syntax in programming languages

Language Lambda syntax Ver Year
Haskell \x -> 2*x+1 1 1990
Python lambda x: 2*x+1 1 1994
OCaml/F# fun x -> 2*x+1 1 1996
Scala x => 2*x+1 1 2004(2)
C# x => 2*x+1 3 2007(6)
Ruby -> (x) { 2*x+1 } 1.9 2007(1)
Groovy { x -> 2*x+1 } 1 2007(2)
Visual Basic Function (x) 2*x+1 9 2007
PHP function ($x) { return 2*$x+1; } 5.3 2009
Objective-C ^(int x) { return 2*x+1; } 3.2 2009(3)
Clojure (fn [x] (+ (* 2 x) 1)) 1 2009(2)
C++ [](int x) { return 2*x+1; } 11 2011
Go func (x int) int { return 2*x+1 } 1 2012(2)
Java x -> 2*x+1 8 2014
Swift { x in 2*x+1 } 1 2014
JavaScript x => 2*x+1 6 2015(4)
Perl -> $x { 2*$x+1 } 6 2015(5)

Notes:

  1. Ruby has an alternative syntax { |x| 2*x+1 } which existed before in version 1.8 (2003).
  2. Lambda function syntax might have existed in early versions before 1.0.
  3. “3.2” is a version of Xcode which shipped at the time of Mac OS X 10.6.
  4. Earlier JavaScript versions had a more verbose syntax similar to PHP 5.3.
  5. Earlier Perl versions had an alternative syntax:
    { my $x = shift; 2*$x+1 }
  6. C# 2.0 (2006) had a more verbose syntax:
    delegate(int x) { return 2*x+1; }

Most of the time the lambda function declaration starts with a keyword (“function” or similar) or a symbol (like “^”), then there’s a parameter list, a delimiter (like an arrow), and finally an expression defining the function. In several languages (Perl, Ruby, Groovy, Swift) a “block”-like syntax is used where there’s no special keyword, and a lambda function looks like a normal block of code, but the beginning of such block starts with a parameter list separated from the block body. In addition those Perl-influenced languages also support magic implicit parameters. That gives a very concise lambda function syntax:

// Perl
{ 2 * $_ + 1 }    
// Groovy
{ 2 * it + 1 }
// Swift
{ 2 * $0 + 1 }

-> vs =>

As you can see from the table many languages borrow an arrow “maps to” notation from math. 5 languages are using “->” to signify an arrow, but 3 other languages are using “=>”. In fact in C++ and Swift the thin arrow (->) is actually used to specify a return type, for example:

// C++ lambda with return type
[](int x) -> int { return 2*x+1; }
// Swift lambda with return type
{ x -> Int in return 2*x+1 }

That puts languages with “=>” as outliers: Scala, C# and JavaScript.

It’s possible to understand C# choice, because it uses “->” as an operator that accesses a member of a structure via a pointer, which is familiar to C/C++ coders and can be used in “unsafe” mode in C# (see here).

JavaScript’s decision to use a “fat” arrow is most likely an influence of CoffeeScript. CoffeeScript had introduced both arrows to the JavaScript developers community. The semantics of the fat arrow from CoffeeScript, which captures “this” from an outer scope into the closure, was later adopted by JavaScript 6.

Notable usages

Lambda functions enable an inline function declaration. Usually it resides at the place of another function call. This language feature can be used whenever you would otherwise pass a function, a function pointer or another sort of a callback. It’s very relieving, because you don’t need to invent a good function name, nor think about a class/module to put that function in. On the downside this can be abused, degrade code readability and diminish reuse. Therefore one should try to keep lambda expression or a block body short and readable.

Asynchronous programming

Sometimes you need to start a task, which runs independently, and want to get a notification when it’s finished in order to do something with the result. You might use a lambda function to declare code which runs at the end of the task:

// JavaScript (Node.js): download a URL and print out when ready
require('http').get("http://dobegin.com", response => console.log(response));

Event handlers

Subscribing to an event usually requires a callback function that will be called upon arrival of an event. A lambda function (or a “block”) might be used to have a code responding to an event inline at the place of subscription:

// Swift: creating an "OK" button for a message dialog
UIAlertAction(title: "OK", style: UIAlertActionStyle.Default) {
    action:UIAlertAction in
        print("OK was pressed")
}

Collections

Collection manipulation APIs (like .NET LINQ or Underscore.js) let you do things like sorting, filtering, mapping and grouping of the data items. A collection’s operation behaviour is usually easily customizable with user-provided lambda functions:

// C#: sort users by the last name field
users.Sort((u1, u2) => u1.LastName.CompareTo(u2.LastName));

Lazy evaluation

Lambda function fits nice to do lazy evaluation. It gives a special syntax to capture some lambda expression or a block to be evaluated later:

// Java: delay counting lines of an input text
Supplier<Integer> createLineCounter(String text) {
    return () -> countLines(text);
}

No lambda support

The C language lacks lambdas in the C11 specification, but it’s supported by some non-standard compiler extensions. In particular, compiling C code on Mac OS X with clang will give you the same syntax of lambda functions as Objective-C has.

The Android platform Java lacks lambdas in Android version M, but the next version Android N already announced support for Java 8 lambda functions.

See also

Subscribe to get more articles about programming languages
Donate