dart-lang / dart-lang/language

Method-to-function conversion

Open
#4,150 12 comments 13 reactions 0 assignees View on GitHub
brevity feature
Dominant language
TeX
Stars
2.9k
Forks
239
Avg merge
2d 18h
Merged PRs (30d)
14

Description

Discussions in #357 strongly suggest that we will support a primary expression of the form `'.' ` (e.g., `.foo`). The semantics of such terms will most likely be determined by the context type.

This issue is a proposal that we should generalize the semantics of this syntax to cover an additional case: If `.foo` is used in a context where an expression of type `R Function(T)` is expected then it is implicitly transformed into `(T x) => x.foo`. Similar conversions are applied when a chain of selectors are present, e.g., `.foo(1)?.whereType()[4]` would become `(T x) => x.foo(1)?.whereType()[4]`. For example:

```dart
void main() {
// Proposed form.
var xs1 = [1, 2, 3].map(.toString());

// Same thing, written without this feature.
var xs2 = [1, 2, 3].map((int x) => x.toString());
}
```

This feature will only enable a small amount of abbreviation, but it is likely to be convenient to have in a large number of invocations of `map` and `forEach` on collections, as well as many other situations involving callback arguments, and this would justify having the feature even though it doesn't do a lot each time it is used.

# Proposal

## Syntax

The grammar is adjusted as follows:

```ebnf
::= // Add one alternative at the end.
: ...
| '.'
```

*Several other proposals are expected to introduce this new kind of expression. If and when we get any of those proposed features then this grammar change is not needed.*

## Static analysis

Assume that `e` is an expression of the form `.id s1 .. sk` where `id` is an identifier and `sj` is derived from ``, for `j` in `1 .. k`, and `e` is not a subexpression of an expression of the form `.id s1 .. sk .. sn` where `sj` is derived from `` for `j` in `1 .. n` *(that is, `e` already contains all the selectors)*.

If the context type of `e` is of the form `R Function(T)` for some types `R` and `T` then `e` is implicitly transformed into `((T x) => x.e s1 .. sk)`, where `x` is a fresh name.

*If the resulting function literal is or contains a compile-time error then it should be reported in terms of a failure to perform the method-to-function conversion, plus information about the error that arises after the conversion. For example, `.foo` may be an error in the context of `R Function(T)` because `T` isn't an interface type that declares a member named `foo`, and there is no extension method named `foo` which is applicable to a receiver of type `T`; or `x.foo` is an expression that has no errors when `x` has type `T`, but that type is not a subtype of `R`, and hence the function literal as a whole isn't assignable to `R Function(T)`.*

Contributor guide

Open the contributing guide

Research direction

Start with this proposal and the discussions in issue #357, then review the proposed grammar and static-analysis rules for `.identifier` expressions. Done means the method-to-function conversion proposal has a decided specification and its behavior, including selector chains and conversion errors, is covered by the language implementation and validation work.

Written by the indexing model from the issue text.

Assessment

Tech stack
dart
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.