Skip to content

Allow inferring the name on object patterns  #2563

Open
@munificent

Description

@munificent

An earlier version of the patterns proposal used record pattern syntax like (foo: var f, bar: 3) to match any object, and it would simply call the corresponding getters on whatever static type the matched value had. Alas, this left users with no way to actually test if an object is a record (#2218). We fixed that by saying that record pattern only ever matches record objects. If you want to call getters on other objects, you have to use a named object pattern.

This works, but it's verbose in cases where you want to use an object but the type you're destructuring is the same as the matched value type, like:

var map = {1: 'a', 2: 'b'};
for (var MapEntry(:key, :value) in map.entries) {
  ...
}

Here, we already know the static type of the matched value is MapEntry. And we know that the value can never be an actual record since MapEntry isn't a record type. So the object name doesn't add much value here. It would be nice if you could write:

var map = {1: 'a', 2: 'b'};
for (var (:key, :value) in map.entries) {
  ...
}

Of course, that's ambiguous with record patterns. To disambiguate, I would say:

You can omit the type name in an object pattern only when the matched value type is not a record type, Record, or a supertype of Record. When the matched value is any of those types, then the pattern is instead treated as a record pattern that only matches records.

When the matched value is any other type, a record pattern could never successfully match since the value will never be a record, so we instead treat it as an extractor pattern whose inferred type is the matched value type.

We do have to decide this now because the proposal currently doesn't make it an error to have a record pattern in a context where the matched value type means no record will ever appear. You can still write the record pattern, but it just will never match. When we full specify exhaustiveness checking, we might be able to flag this as an unreachable case. If we do that, then we can allow inferred object names in a later release without it being a breaking change.

Metadata

Metadata

Assignees

No one assigned

    Labels

    patternsIssues related to pattern matching.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions