Justin 的个人资料Various Technical Topics照片日志 工具 帮助

日志


12月12日

Lambda Expressions In Visual Basic

Paul Vick had a post last week, where he solicited feedback on syntax for this feature that will likely be included in a future version of Visual Basic.

http://www.panopticoncentral.net/archive/2006/12/08/18587.aspx#FeedBack

I originally posted my opinion in a comment on his blog, but it apparently didn't make it past the censors. He proposed 3 possible syntax variations, but I'm not found of any of them. My proposal is a fourth style, and I think it has a lot of merit.

What's a Lambda Expression?

This is probably better explained elsewhere, but basically it as an anonymous function.

For example, given the following code, ...

Class Test
  Private myNames As List(Of Name)
  ...
  Public Sub PrintLegalNames()
    For Each n As Name In myNames
      Console.WriteLine(n.ToString())
    Next
  End Sub
End Class

we could replace the explicit loop using List.ForEach.

Public Sub PrintLegalNames()
  myNames.ForEach(AddressOf WriteName)
End Sub

However, for this to work, we have to provide a suitable WriteName function.

Public Sub WriteName(ByVal n As Name) 
  Console.WriteLine(n.ToString()) 
End Sub

My proposal is to support the following syntax.

Public Sub PrintLegalNames()
  myNames.ForEach(Console.WriteLine(ByVal(0).ToString()))
End Sub

The lambda expression is just a normal expression that uses parameters and return statements inline. Here are some more examples that show multiple parameters, functions, and ByRef parameters compared to roughly equivalent code.

Dim ary(0 to 9) As Integer

Array.Find(ary, Return ByVal(0) = 2) 
Function Find2(ByVal x As Integer) As Boolean
  Return x = 2
End Function
Array.Find(ary, AddressOf Find2)


Array.ForEach(ary, ByRef(0) += 1) 
Sub AddOne(ByRef x As Integer)
  x += 1
End Sub
Array.ForEach(ary, AddressOf AddOne)


Array.Sort(ary, ByVal(1) >= ByVal(0))
Function Less(ByVal lhs As Integer, ByVal rhs As Integer) As Boolean
  Return lhs < rhs
End Function
Array.Sort(ary, AddressOf Less)

What about closures?

It wasn't mentioned in Pauls post, but I think closures are also a necessary feature so that the following code will work.

Sub SendPartyInvitation(ByVal state As State)
  ...
  Dim legal As Integer = state.LegalDrinkingAge
  Dim names As List(Of Name) = CreateList()
  ...
  tmp = List.FindAll(names, Return ByVal(0).Age >= legal)
  ...
End Sub

The key feature, is that the "legal" local variable is available for use within the lambda expression, which would not be the case if each expression where simply an anonymous function.