Skip to content
Andrey Kurosh edited this page Jun 20, 2017 · 4 revisions

Lambda expressions are anonymous functions that can be passed to other functions, invoked and partially applied. They are defined with the arrow notation:

let sum = (x:int y:int) -> x + y

If the lambda expression needs no arguments, the block can be omitted entirely:

let getFive = -> 5

Type inference

Lambda's argument types can be omitted if they could be inferred from usage:

Enumerable::Range 1 10
    |> Select x -> x + 0.5  // it is implied that x is int
    |> Where y -> y < 50    // y is double because (x + 0.5) is double
    |> Count ()

More specifically, argument types can be inferred when the lambda is...

  • ...passed as an argument to a method, function, or constructor
  • ...assigned to an existing variable, field, property or index of array / collection
  • ...being explicitly cast to a delegate type
  • ...used as a right operand of a function composition operator

By default, lambda expressions evaluate to Func<...> if they return a value or Action<...> if they don't. However, depending on usage they may be evaluated to any kind of delegate.

Closures

A particularly useful feature of lambda expressions is that they closure the scope around them. This means that a lambda can use or modify values from the scope where it was declared:

var count = 0
let arr = new [5; 4; 3; 2; 1]
Array::ForEach (x -> count = count + 1)
println "There are {0} items in an array" count

You can, for example, closure function arguments to create generators:

fun createMultiplier:Func<int, int> (x:int) -> (y:int) -> x * y
let byFive = createMultiplier 5
let twenty = byFive 4

You cannot, however, closure ref arguments. This is a limitation of the .NET framework itself.

Read more

Clone this wiki locally