Lambdas and Delegates
Prerequisites: Generics
A delegate is a type for "a reference to a procedure". A lambda expression creates one inline.
Lambda expressions
Module Program
Sub Main()
Dim square As Func(Of Integer, Integer) = Function(x) x * x
Dim add = Function(a As Integer, b As Integer) a + b
Dim greet As Action(Of String) = Sub(name) Console.WriteLine($"Hi, {name}")
Console.WriteLine(square(7))
Console.WriteLine(add(2, 3))
greet("Ada")
Dim describe = Function(n As Integer) As String
If n Mod 2 = 0 Then Return "even"
Return "odd"
End Function
Console.WriteLine(describe(7))
End Sub
End Module
49
5
Hi, Ada
odd
Function(x) expressionreturns a value;Sub(x) statementdoesn't.- Multi-line lambdas end with
End FunctionorEnd Sub. Func(Of T1, ..., TResult)andAction(Of T1, ...)are the built-in delegate types for functions and subs.
Passing functions to functions
Module Program
Function ApplyToAll(values As Integer(), f As Func(Of Integer, Integer)) As Integer()
Dim result(values.Length - 1) As Integer
For i = 0 To values.Length - 1
result(i) = f(values(i))
Next
Return result
End Function
Function Triple(x As Integer) As Integer
Return x * 3
End Function
Sub Main()
Dim nums = {1, 2, 3}
Console.WriteLine(String.Join(" ", ApplyToAll(nums, Function(x) x + 10)))
Console.WriteLine(String.Join(" ", ApplyToAll(nums, AddressOf Triple)))
Dim words As New List(Of String) From {"ccc", "a", "bb"}
words.Sort(Function(x, y) x.Length.CompareTo(y.Length))
Console.WriteLine(String.Join(" ", words))
Console.WriteLine(words.Find(Function(w) w.StartsWith("b")))
End Sub
End Module
11 12 13
3 6 9
a bb ccc
bb
AddressOf Triple turns a named procedure into a delegate.
Closures
A lambda can capture local variables around it:
Module Program
Function MakeCounter() As Func(Of Integer)
Dim count = 0
Return Function()
count += 1
Return count
End Function
End Function
Sub Main()
Dim c1 = MakeCounter()
Dim c2 = MakeCounter()
Console.WriteLine($"{c1()} {c1()} {c1()} {c2()}")
End Sub
End Module
1 2 3 1
Each counter keeps its own count alive after MakeCounter returns.
Custom delegate types
Public Delegate Function Discount(price As Decimal) As Decimal
Module Program
Sub Main()
Dim rules As Discount() = {
Function(p) p * 0.9D,
Function(p) Math.Max(0D, p - 5D)
}
For Each rule In rules
Console.WriteLine(rule(30D))
Next
End Sub
End Module
27.0
25
Named delegate types document intent, but Func and Action cover most
needs. Delegates are also the foundation of events (later in this
level).