dotnet / dotnet/vblang

Express lambdas simply as "incomplete expressions" with _ (or $1) and no argument list declaration

Open
#256 36 comments 7 reactions 0 assignees View on GitHub
LDM Reviewed: No plans
Dominant language
No language data
Stars
328
Forks
71
PR merge metrics
No merged PRs in 30d

Description

Express lambdas as "incomplete expressions," using a "placeholder character" (here, `_` as in Scala).
- Greatly improves readability, reducing the noise of `Function(parameter)`
- Reduces the need for for LINQ query comprehensions
- Well-received in Scala/Swift
- A perfect match for VB -- as it was decided that C# arrow syntax did not fit well into BASIC, whereas this one fits in very well

```vb
'Old way (goes off the page...):
Dim activeCustomers = customers.Where(Function(c) c.LastActive > lastMonth).OrderBy(Function(c) c.LastName)
Dim lastNameList = activeCustomers.Select(Function(c) $"{c.LastName}, {c.FirstName}")
'New way:
Dim activeCustomers = customers.Where(_.LastActive > lastMonth).OrderBy(_.LastName)
Dim lastNameList = activeCustomers.Select($"{_.LastName}, {_.FirstName}")

'Here's how it works:
'An expression that contains a reference to '_' is wrapped into a function.

```

### Technical details
- If you pass an expression where a function is expected, AND the `_` pseudo-identifier is used somewhere in the expression, convert it into something like `Function(arg1) exprGoesHere` with the `_`s converted to `arg1`.
```vb
Dim isActiveLately As Func(Of Customer, DateTime) = _.LastActive > Now.AddMonths(-1)
Dim isActiveLately As Func(Of Customer, DateTime) = Function(c) c.LastActive > Now.AddMonths(-1)
```
- Argument and return types can easily be inferred, just as we do for the regular `Function(args)` syntax. As a matter of fact, we can do even better this way; see below.
- Nesting two "incomplete expressions" should probably not be allowed. There wouldn't a clear argument for `_` to reference.

### Use in 'partial application'

This also shines for highly expressive and concise partial application:
```vb
'Old way:
Dim GetFirstChar = Function(str As String) Strings.Left(str, 1)
'New way:
Dim GetFirstChar = Strings.Left(_, 1)
'Notice how it also makes better type inference possible.
```

### Multi-argument functions

Swift actually goes further and lets you use `$1`, `$2`, and so on, for lambdas where a multi-argument function is expected -- for instance, comparer/aggregator functions:
```vb
'Old way:
Dim totalOrders = activeCustomers.Aggregate(0, Function(r, c) r + c.Orders.Count)
'New way:
Dim totalOrders = activeCustomers.Aggregate(0, $1 + $2.Orders.Count)
```

VB could implement either `_` or `$1` or both -- input would be appreciated.

### Use in pattern matching

If we ever get pattern matching done _(note: we should!)_ 😃, and we allow providing a function as a pattern, then again `_` makes this very concise and expressive -- it would be a game-changer for Select Case:

```vb
Select Case lastIssueId
Case 0: 'no issues -- throw an exception
Case 1: 'first issue in the repo -- award the "First Issue" badge
Case _ Mod 256 = 0: 'issue has won the jackpot and should be implemented immediately! :-)
'WITHOUT OUR NEW FEATURE the above line would have to be:
Case Function(i) i Mod 256 = 0
'...so it really saves the day here.
End Select
```

### Another example: conditionally selected lambdas
Sometimes you want to use one or more lambdas based on a condition. `_` really shines here:
**NOTE:** There are caveats in this specific usage related to type inference and precedence. But I wanted to convey the idea.
```vb
Dim sortByTitle = (Request.Params("sort") = "title")
'Old way:
Dim sortFunc = If(sortByTitle, Function(i As Issue) i.Title, Function(i As Issue) i.PostDate)
Dim sortedIssues = allIssues.OrderBy(sortFunc)
'New way -- much simpler:
Dim sortedIssues = allIssues.OrderBy(If(sortByTitle, _.Title, _.PostDate))
```

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.