[Proposal] Invert the order of pattern match operator


(David Rodrigues) #1

Hi all,

Swift has a pattern match operator, ~=, which is unknown to many (like me
until a few weeks ago), that performs a match between a value and a certain
pattern, e.g. checking if an integer value is contained in a range of
integers.

This operator may be little known, but it plays a key role in the language
since it's used behind the scenes to support expression patterns in
`switch` statement case labels, which we all know are extremely popular.

let point = (2, 4)
switch point {
case (0, 0):
    print("The point is at the origin")
case (0...4, 0...4):
    print("The point is in the subregion")
default:
    break
}

Most of the time we don't use the operator directly but it is available and
can be handy in certain conditions.

let point = (2, 4)
switch point {
case (let x, let y) where 0...4 ~= x && 0...4 ~= y:
    print("The point is in the subregion")
default:
    break
}

However the current syntax is not ideal (in my opinion). We're not really
declaring the operation that we want to do, and that has an impact in the
expressivity and readability of the code. Currently we're doing matches
like "if blue is the ocean" instead of "if the ocean is blue" or "if the
ocean contains the whale" instead of "if the whale is in the ocean".

For that reason, I would like to suggest inverting the order of the
operator to match more closely our logical thought.

case (let x, let y) where x =~ 0...4 && y =~ 0...4: // Proposed
// vs
case (let x, let y) where 0...4 ~= x && 0...4 ~= y: // Current

I have an ongoing proposal to suggest this change and it contains a little
more context. It is available here:

https://github.com/dmcrodrigues/swift-evolution/blob/proposal/invert-order-of-pattern-match-operator/proposals/NNNN-invert-order-of-pattern-match-operator.md
.

Any feedback is very welcome.

Thank you.

David Rodrigues


(David Owens II) #2

It would be nice to know the rationale behind the choice of the current syntax. I agree that these seem more natural:

@warn_unused_result
public func ~=<I : ForwardIndexType where I : Comparable>(value: I, pattern: Range<I>) -> Bool

@warn_unused_result
public func ~=<I : IntervalType>(value: I.Bound, pattern: I) -> Bool

I would not change from `~=` to `=~` though.

So you have this:

let x = 4

switch x {
case let v where x ~= 0...5: print("matched: \(v)")
default: print("nothing!!")
}

-David

···

On Apr 7, 2016, at 4:57 AM, David Rodrigues via swift-evolution <swift-evolution@swift.org> wrote:

Hi all,

Swift has a pattern match operator, ~=, which is unknown to many (like me until a few weeks ago), that performs a match between a value and a certain pattern, e.g. checking if an integer value is contained in a range of integers.

This operator may be little known, but it plays a key role in the language since it's used behind the scenes to support expression patterns in `switch` statement case labels, which we all know are extremely popular.

let point = (2, 4)
switch point {
case (0, 0):
    print("The point is at the origin")
case (0...4, 0...4):
    print("The point is in the subregion")
default:
    break
}

Most of the time we don't use the operator directly but it is available and can be handy in certain conditions.

let point = (2, 4)
switch point {
case (let x, let y) where 0...4 ~= x && 0...4 ~= y:
    print("The point is in the subregion")
default:
    break
}

However the current syntax is not ideal (in my opinion). We're not really declaring the operation that we want to do, and that has an impact in the expressivity and readability of the code. Currently we're doing matches like "if blue is the ocean" instead of "if the ocean is blue" or "if the ocean contains the whale" instead of "if the whale is in the ocean".

For that reason, I would like to suggest inverting the order of the operator to match more closely our logical thought.

case (let x, let y) where x =~ 0...4 && y =~ 0...4: // Proposed
// vs
case (let x, let y) where 0...4 ~= x && 0...4 ~= y: // Current

I have an ongoing proposal to suggest this change and it contains a little more context. It is available here:

https://github.com/dmcrodrigues/swift-evolution/blob/proposal/invert-order-of-pattern-match-operator/proposals/NNNN-invert-order-of-pattern-match-operator.md.

Any feedback is very welcome.

Thank you.

David Rodrigues
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Dave Abrahams) #3

It would be nice to know the rationale behind the choice of the current syntax.
I agree that these seem more natural:

    @warn_unused_result
    public func ~=<I : ForwardIndexType where I : Comparable>(value: I, pattern:
    Range<I>) -> Bool

    @warn_unused_result
    public func ~=<I : IntervalType>(value: I.Bound, pattern: I) -> Bool

+1

I would not change from `~=` to `=~` though.

One downside with `~=` is that it reads like `+=`, which mutates the
LHS. Of course, `=~` has its own issues, e.g. `x=~y` might read as `x =
~y`.

···

on Thu Apr 07 2016, David Owens II <swift-evolution@swift.org> wrote:

So you have this:

    let x = 4

    switch x {
    case let v where x ~= 0...5: print("matched: \(v)")
    default: print("nothing!!")
    }

-David

    On Apr 7, 2016, at 4:57 AM, David Rodrigues via swift-evolution > <swift-evolution@swift.org> wrote:

    Hi all,

    Swift has a pattern match operator, ~=, which is unknown to many (like me
    until a few weeks ago), that performs a match between a value and a certain
    pattern, e.g. checking if an integer value is contained in a range of
    integers.

    This operator may be little known, but it plays a key role in the language
    since it's used behind the scenes to support expression patterns in `switch
    ` statement case labels, which we all know are extremely popular.

    let point = (2, 4)
    switch point {
    case (0, 0):
    print("The point is at the origin")
    case (0...4, 0...4):
    print("The point is in the subregion")
    default:
    break
    }

    Most of the time we don't use the operator directly but it is available and
    can be handy in certain conditions.

    let point = (2, 4)
    switch point {
    case (let x, let y) where 0...4 ~= x && 0...4 ~= y:
    print("The point is in the subregion")
    default:
    break
    }

    However the current syntax is not ideal (in my opinion). We're not really
    declaring the operation that we want to do, and that has an impact in the
    expressivity and readability of the code. Currently we're doing matches like
    "if blue is the ocean" instead of "if the ocean is blue" or "if the ocean
    contains the whale" instead of "if the whale is in the ocean".

    For that reason, I would like to suggest inverting the order of the operator
    to match more closely our logical thought.

    case (let x, let y) where x =~ 0...4 && y =~ 0...4: // Proposed
    // vs
    case (let x, let y) where 0...4 ~= x && 0...4 ~= y: // Current

    I have an ongoing proposal to suggest this change and it contains a little
    more context. It is available here:

    https://github.com/dmcrodrigues/swift-evolution/blob/proposal/invert-order-of-pattern-match-operator/proposals/NNNN-invert-order-of-pattern-match-operator.md
   .

    Any feedback is very welcome.

    Thank you.

    David Rodrigues
    _______________________________________________
    swift-evolution mailing list
    swift-evolution@swift.org
    https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--
Dave


(Erica Sadun) #4

I'd prefer to offer both ~= and =~, allowing the consumer to choose which side the pattern sits on.

-- E

···

On Apr 7, 2016, at 11:09 AM, David Owens II via swift-evolution <swift-evolution@swift.org> wrote:

It would be nice to know the rationale behind the choice of the current syntax. I agree that these seem more natural:

@warn_unused_result
public func ~=<I : ForwardIndexType where I : Comparable>(value: I, pattern: Range<I>) -> Bool

@warn_unused_result
public func ~=<I : IntervalType>(value: I.Bound, pattern: I) -> Bool

I would not change from `~=` to `=~` though.

So you have this:

let x = 4

switch x {
case let v where x ~= 0...5: print("matched: \(v)")
default: print("nothing!!")
}

-David

On Apr 7, 2016, at 4:57 AM, David Rodrigues via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hi all,

Swift has a pattern match operator, ~=, which is unknown to many (like me until a few weeks ago), that performs a match between a value and a certain pattern, e.g. checking if an integer value is contained in a range of integers.

This operator may be little known, but it plays a key role in the language since it's used behind the scenes to support expression patterns in `switch` statement case labels, which we all know are extremely popular.

let point = (2, 4)
switch point {
case (0, 0):
    print("The point is at the origin")
case (0...4, 0...4):
    print("The point is in the subregion")
default:
    break
}

Most of the time we don't use the operator directly but it is available and can be handy in certain conditions.

let point = (2, 4)
switch point {
case (let x, let y) where 0...4 ~= x && 0...4 ~= y:
    print("The point is in the subregion")
default:
    break
}

However the current syntax is not ideal (in my opinion). We're not really declaring the operation that we want to do, and that has an impact in the expressivity and readability of the code. Currently we're doing matches like "if blue is the ocean" instead of "if the ocean is blue" or "if the ocean contains the whale" instead of "if the whale is in the ocean".

For that reason, I would like to suggest inverting the order of the operator to match more closely our logical thought.

case (let x, let y) where x =~ 0...4 && y =~ 0...4: // Proposed
// vs
case (let x, let y) where 0...4 ~= x && 0...4 ~= y: // Current

I have an ongoing proposal to suggest this change and it contains a little more context. It is available here:

https://github.com/dmcrodrigues/swift-evolution/blob/proposal/invert-order-of-pattern-match-operator/proposals/NNNN-invert-order-of-pattern-match-operator.md.

Any feedback is very welcome.

Thank you.

David Rodrigues
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(David Rodrigues) #5

It would be nice to know the rationale behind the choice of the current syntax.
I agree that these seem more natural:

   @warn_unused_result
   public func ~=<I : ForwardIndexType where I : Comparable>(value: I, pattern:
   Range<I>) -> Bool

   @warn_unused_result
   public func ~=<I : IntervalType>(value: I.Bound, pattern: I) -> Bool

+1

This operator was firstly introduced in Swift in the form =~ but then it was reversed to the current form (~3y ago). There’s a little context about this change on Twitter: https://twitter.com/dmcrodrigues/status/717063623957471232.

I would not change from `~=` to `=~` though.

One downside with `~=` is that it reads like `+=`, which mutates the
LHS. Of course, `=~` has its own issues, e.g. `x=~y` might read as `x =
~y`.

I agree but this operator already exists in other languages like Ruby and Perl, so align the syntax may be a good option.

···

On 07 Apr 2016, at 19:16, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

On 07 Apr 2016, at 18:56, Erica Sadun <erica@ericasadun.com> wrote:

I'd prefer to offer both ~= and =~, allowing the consumer to choose which side the pattern sits on.

On the other hand, I like in particular the option of having both `~=` and `=~` to provide more flexibility like Erica has suggested. The main question is if that’s ok introduce another operator in the language.


David


(Haravikk) #6

Can someone fill me in as to how this differs from (0…4).contains(x)?

Personally I don’t like the choice for the operator, and think it’s not very clear, if we can do the same thing with a method then I’d prefer removing the operator to be honest.

···

On 7 Apr 2016, at 12:57, David Rodrigues via swift-evolution <swift-evolution@swift.org> wrote:

Hi all,

Swift has a pattern match operator, ~=, which is unknown to many (like me until a few weeks ago), that performs a match between a value and a certain pattern, e.g. checking if an integer value is contained in a range of integers.

This operator may be little known, but it plays a key role in the language since it's used behind the scenes to support expression patterns in `switch` statement case labels, which we all know are extremely popular.

let point = (2, 4)
switch point {
case (0, 0):
    print("The point is at the origin")
case (0...4, 0...4):
    print("The point is in the subregion")
default:
    break
}

Most of the time we don't use the operator directly but it is available and can be handy in certain conditions.

let point = (2, 4)
switch point {
case (let x, let y) where 0...4 ~= x && 0...4 ~= y:
    print("The point is in the subregion")
default:
    break
}

However the current syntax is not ideal (in my opinion). We're not really declaring the operation that we want to do, and that has an impact in the expressivity and readability of the code. Currently we're doing matches like "if blue is the ocean" instead of "if the ocean is blue" or "if the ocean contains the whale" instead of "if the whale is in the ocean".

For that reason, I would like to suggest inverting the order of the operator to match more closely our logical thought.

case (let x, let y) where x =~ 0...4 && y =~ 0...4: // Proposed
// vs
case (let x, let y) where 0...4 ~= x && 0...4 ~= y: // Current

I have an ongoing proposal to suggest this change and it contains a little more context. It is available here:

https://github.com/dmcrodrigues/swift-evolution/blob/proposal/invert-order-of-pattern-match-operator/proposals/NNNN-invert-order-of-pattern-match-operator.md.

Any feedback is very welcome.

Thank you.

David Rodrigues
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Brent Royal-Gordon) #7

Can someone fill me in as to how this differs from (0…4).contains(x)?

Personally I don’t like the choice for the operator, and think it’s not very clear, if we can do the same thing with a method then I’d prefer removing the operator to be honest.

~= is the way you customize how a type behaves when it's a pattern in a switch statement. So ~= (_: Range<T>, _: T) is responsible for making `case 1..<10` work properly. Removing it would be...unwise.

···

--
Brent Royal-Gordon
Architechies


(Haravikk) #8

But why not just (1..<10).contains(x) behind the scenes instead? This could be redefined as a protocol or whatever. It’s just kind of strange as an operator, and as the OP said not especially well known.

···

On 8 Apr 2016, at 11:32, Brent Royal-Gordon <brent@architechies.com> wrote:

Can someone fill me in as to how this differs from (0…4).contains(x)?

Personally I don’t like the choice for the operator, and think it’s not very clear, if we can do the same thing with a method then I’d prefer removing the operator to be honest.

~= is the way you customize how a type behaves when it's a pattern in a switch statement. So ~= (_: Range<T>, _: T) is responsible for making `case 1..<10` work properly. Removing it would be…unwise.