Proposal: Optional Binding Shorthand Syntax


(Zef Houssney) #1

Hello. This is exciting!

I have an idea I’ve been mulling over for a while to reduce a common source of clutter in Swift code.

The idea is to introduce a new syntax for Optional Binding:

Instead of:

if let foo = foo { }

You could simply use:

if let foo { }

I’ve written up a draft of a proposal here with additional information and motivations:
https://github.com/zef/swift-evolution/blob/master/proposals/00xx-optional-binding-shorthand.md

What do you think?

Thank you!


(David Hart) #2

I understand the reasoning of this proposal but it seems to go against the objectives the Swift team has been striving towards lately of:

- simplifying the language
- making code more explicit by removed by shorthand syntax
- removing redundant syntax for achieving the same behavior

You can see examples of this in the latest changes to the language:

- removal of the # symbol in the first argument name as a shorthand to defining the argument name twice
- removal of the ++ and -- prefix and postfix operators in Swift 3
- removal of the var modifier in argument declaration and if/guard/while/for in blocks in Swift 3

I tend to agree with their philosophy to remove these shorthand syntaxes which make the language more difficult to learn (when all these features are taken as a whole) and potentially making the grammar more complicated only for the benefit of a shorthand syntax which also has the disadvantage of allowing two different syntaxes for the same semantics.

Just my 2 cents :slight_smile:

···

Sent from my iPhone

On 03 Dec 2015, at 20:52, Zef Houssney <zefmail@gmail.com> wrote:

Hello. This is exciting!

I have an idea I’ve been mulling over for a while to reduce a common source of clutter in Swift code.

The idea is to introduce a new syntax for Optional Binding:

Instead of:

if let foo = foo { }

You could simply use:

if let foo { }

I’ve written up a draft of a proposal here with additional information and motivations:
https://github.com/zef/swift-evolution/blob/master/proposals/00xx-optional-binding-shorthand.md

What do you think?

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


(Zef Houssney) #3

Thanks for your thoughts David!

I would argue that it does support stated objectives of Swift, like "the syntax is concise yet expressive.”

In the majority of cases having a lot of esoteric syntax is a problem. However, with this being such a fundamental part of every day programming in Swift, I find it to be a perfect place to reduce friction. I also find it to be quite understandable and intuitive, unlike the three examples of Swift 3 changes that you gave, which are more specialized and less frequently encountered.

Also, I just noticed that this isn’t unprecedented and that a similar idiom actually currently used in Swift to assign constants when pattern matching inside a Switch:

case let (x, y):

That is doing fundamentally the same thing that I’m suggesting. It assigns a constant without using `=`, because the value is already known.

Zef

···

On Dec 3, 2015, at 1:26 PM, David Hart <david@hartbit.com> wrote:

I understand the reasoning of this proposal but it seems to go against the objectives the Swift team has been striving towards lately of:

- simplifying the language
- making code more explicit by removed by shorthand syntax
- removing redundant syntax for achieving the same behavior

You can see examples of this in the latest changes to the language:

- removal of the # symbol in the first argument name as a shorthand to defining the argument name twice
- removal of the ++ and -- prefix and postfix operators in Swift 3
- removal of the var modifier in argument declaration and if/guard/while/for in blocks in Swift 3

I tend to agree with their philosophy to remove these shorthand syntaxes which make the language more difficult to learn (when all these features are taken as a whole) and potentially making the grammar more complicated only for the benefit of a shorthand syntax which also has the disadvantage of allowing two different syntaxes for the same semantics.

Just my 2 cents :slight_smile:

Sent from my iPhone

On 03 Dec 2015, at 20:52, Zef Houssney <zefmail@gmail.com> wrote:

Hello. This is exciting!

I have an idea I’ve been mulling over for a while to reduce a common source of clutter in Swift code.

The idea is to introduce a new syntax for Optional Binding:

Instead of:

if let foo = foo { }

You could simply use:

if let foo { }

I’ve written up a draft of a proposal here with additional information and motivations:
https://github.com/zef/swift-evolution/blob/master/proposals/00xx-optional-binding-shorthand.md

What do you think?

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


(Lily Ballard) #4

It's actually not doing the same thing, and what you're suggesting has
no precedent. `case let (x, y)` is completely unrelated; it does not
look up existing bindings for the identifiers `x` and `y`, but instead
is matching against a previously-specified value. But in your proposed
`if let foo {`, you do not specify the value anywhere, and instead rely
on the assumption that you're trying to match against an existing value
with the same identifier. But nowhere else in the language does it ever
assume that any identifier has any relation to another identifier that
it shadows. And nowhere else in the language does it make an assumption
about what data you want to operate over. Furthermore, to anyone not
already familiar with the proposed rule, `if let foo {` is meaningless;
it does not tell the reader what it's actually doing, and its behavior
cannot be inferred from any other language rule.

-Kevin Ballard

···

On Thu, Dec 3, 2015, at 01:17 PM, Zef Houssney wrote:

Thanks for your thoughts David!

I would argue that it does support stated objectives of Swift, like "the
syntax is concise yet expressive.”

In the majority of cases having a lot of esoteric syntax is a problem.
However, with this being such a fundamental part of every day programming
in Swift, I find it to be a perfect place to reduce friction. I also find
it to be quite understandable and intuitive, unlike the three examples of
Swift 3 changes that you gave, which are more specialized and less
frequently encountered.

Also, I just noticed that this isn’t unprecedented and that a similar
idiom actually currently used in Swift to assign constants when pattern
matching inside a Switch:

case let (x, y):

That is doing fundamentally the same thing that I’m suggesting. It
assigns a constant without using `=`, because the value is already known.

Zef

> On Dec 3, 2015, at 1:26 PM, David Hart <david@hartbit.com> wrote:
>
> I understand the reasoning of this proposal but it seems to go against the objectives the Swift team has been striving towards lately of:
>
> - simplifying the language
> - making code more explicit by removed by shorthand syntax
> - removing redundant syntax for achieving the same behavior
>
> You can see examples of this in the latest changes to the language:
>
> - removal of the # symbol in the first argument name as a shorthand to defining the argument name twice
> - removal of the ++ and -- prefix and postfix operators in Swift 3
> - removal of the var modifier in argument declaration and if/guard/while/for in blocks in Swift 3
>
> I tend to agree with their philosophy to remove these shorthand syntaxes which make the language more difficult to learn (when all these features are taken as a whole) and potentially making the grammar more complicated only for the benefit of a shorthand syntax which also has the disadvantage of allowing two different syntaxes for the same semantics.
>
> Just my 2 cents :slight_smile:
>
>
>
> Sent from my iPhone
>> On 03 Dec 2015, at 20:52, Zef Houssney <zefmail@gmail.com> wrote:
>>
>> Hello. This is exciting!
>>
>> I have an idea I’ve been mulling over for a while to reduce a common source of clutter in Swift code.
>>
>> The idea is to introduce a new syntax for Optional Binding:
>>
>> Instead of:
>>
>> if let foo = foo { }
>>
>> You could simply use:
>>
>> if let foo { }
>>
>>
>> I’ve written up a draft of a proposal here with additional information and motivations:
>> https://github.com/zef/swift-evolution/blob/master/proposals/00xx-optional-binding-shorthand.md
>>
>>
>> What do you think?
>>
>> Thank you!
>> _______________________________________________
>> 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


(Chris Lattner) #5

It's actually not doing the same thing, and what you're suggesting has
no precedent.

...

Furthermore, to anyone not
already familiar with the proposed rule, `if let foo {` is meaningless;
it does not tell the reader what it's actually doing, and its behavior
cannot be inferred from any other language rule.

Right.

“if let foo {“ is a frequently proposed extension to the syntax, but it is not one that we’re likely to ever add.

I agree that this is a common pattern, and it would allow you to “write less code”, but that isn’t the goal of Swift. Since code is read more often than it is written, the real goal behind Swift is to let you write “more readable code” by eliminating boilerplate and other noise.

Reducing syntax isn’t itself a goal, particularly if the result could/would be confusing for someone who has to read and maintain your code later.

-Chris

···

On Dec 3, 2015, at 2:18 PM, Kevin Ballard <kevin@sb.org> wrote:

-Kevin Ballard

On Thu, Dec 3, 2015, at 01:17 PM, Zef Houssney wrote:

Thanks for your thoughts David!

I would argue that it does support stated objectives of Swift, like "the
syntax is concise yet expressive.”

In the majority of cases having a lot of esoteric syntax is a problem.
However, with this being such a fundamental part of every day programming
in Swift, I find it to be a perfect place to reduce friction. I also find
it to be quite understandable and intuitive, unlike the three examples of
Swift 3 changes that you gave, which are more specialized and less
frequently encountered.

Also, I just noticed that this isn’t unprecedented and that a similar
idiom actually currently used in Swift to assign constants when pattern
matching inside a Switch:

case let (x, y):

That is doing fundamentally the same thing that I’m suggesting. It
assigns a constant without using `=`, because the value is already known.

Zef

On Dec 3, 2015, at 1:26 PM, David Hart <david@hartbit.com> wrote:

I understand the reasoning of this proposal but it seems to go against the objectives the Swift team has been striving towards lately of:

- simplifying the language
- making code more explicit by removed by shorthand syntax
- removing redundant syntax for achieving the same behavior

You can see examples of this in the latest changes to the language:

- removal of the # symbol in the first argument name as a shorthand to defining the argument name twice
- removal of the ++ and -- prefix and postfix operators in Swift 3
- removal of the var modifier in argument declaration and if/guard/while/for in blocks in Swift 3

I tend to agree with their philosophy to remove these shorthand syntaxes which make the language more difficult to learn (when all these features are taken as a whole) and potentially making the grammar more complicated only for the benefit of a shorthand syntax which also has the disadvantage of allowing two different syntaxes for the same semantics.

Just my 2 cents :)

Sent from my iPhone

On 03 Dec 2015, at 20:52, Zef Houssney <zefmail@gmail.com> wrote:

Hello. This is exciting!

I have an idea I’ve been mulling over for a while to reduce a common source of clutter in Swift code.

The idea is to introduce a new syntax for Optional Binding:

Instead of:

if let foo = foo { }

You could simply use:

if let foo { }

I’ve written up a draft of a proposal here with additional information and motivations:
https://github.com/zef/swift-evolution/blob/master/proposals/00xx-optional-binding-shorthand.md

What do you think?

Thank you!
_______________________________________________
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

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


(David Waite) #6

I might argue that if let is already an odd case; people often read it equivalent to "if (let x=x)”, but “let x=x” has completely different behavior outside the context of an if let statement (I in fact had to try it before I realized it does, in fact, work). Obviously, 'let x=x’ on its own could not have the same behavior.

In that spirit, I propose an alternative feature:

if foo? { … }

where the variable is not shadowed by a copy - instead, inside the block it behaves as an implicit unwrapped optional, including keeping any mutability.

so for example:

func foo(x:Int?) {
     if var x = x { // var so it can be assigned
         x++
     }
     print(x)
}

foo(1) // => 1, updating the aliased x does not do anything

# working code in Swift 1.2
func bar(x:Int?) {
     var y=x
     if let x=x {
         y=x+1
     }
     print(y)
}
bar(1) # => Optional(2)

# proposed
func proposed(x:Int?) {
     var y = x // since swift 3 won't have var function arguments
     if y? { // var so it can be assigned
         y++
     }
     print(y)
}

proposed(1) // => Optional(2)

-DW

···

On Dec 3, 2015, at 3:42 PM, Chris Lattner <clattner@apple.com> wrote:

“if let foo {“ is a frequently proposed extension to the syntax, but it is not one that we’re likely to ever add.

I agree that this is a common pattern, and it would allow you to “write less code”, but that isn’t the goal of Swift. Since code is read more often than it is written, the real goal behind Swift is to let you write “more readable code” by eliminating boilerplate and other noise.

Reducing syntax isn’t itself a goal, particularly if the result could/would be confusing for someone who has to read and maintain your code later.

-Chris


(Sean Heber) #7

What about lifting the whole concept out of "if" or "guard" and making a new construct that directly communicates the intent?

For example:

when foo { ... }

Which could be combined with "where" to generate an if-like construct:

when foo where foo.isSomething { ... }

Inside the code block, you can access foo directly and it isn't shadowed - so if it was a var, it is mutable, etc.

l8r
Sean

···

On Dec 3, 2015, at 8:25 PM, David Waite <david@alkaline-solutions.com> wrote:

I might argue that if let is already an odd case; people often read it equivalent to "if (let x=x)”, but “let x=x” has completely different behavior outside the context of an if let statement (I in fact had to try it before I realized it does, in fact, work). Obviously, 'let x=x’ on its own could not have the same behavior.

In that spirit, I propose an alternative feature:

if foo? { … }

where the variable is not shadowed by a copy - instead, inside the block it behaves as an implicit unwrapped optional, including keeping any mutability.

so for example:

func foo(x:Int?) {
     if var x = x { // var so it can be assigned
         x++
     }
     print(x)
}

foo(1) // => 1, updating the aliased x does not do anything

# working code in Swift 1.2
func bar(x:Int?) {
     var y=x
     if let x=x {
         y=x+1
     }
     print(y)
}
bar(1) # => Optional(2)

# proposed
func proposed(x:Int?) {
     var y = x // since swift 3 won't have var function arguments
     if y? { // var so it can be assigned
         y++
     }
     print(y)
}

proposed(1) // => Optional(2)

-DW

On Dec 3, 2015, at 3:42 PM, Chris Lattner <clattner@apple.com> wrote:

“if let foo {“ is a frequently proposed extension to the syntax, but it is not one that we’re likely to ever add.

I agree that this is a common pattern, and it would allow you to “write less code”, but that isn’t the goal of Swift. Since code is read more often than it is written, the real goal behind Swift is to let you write “more readable code” by eliminating boilerplate and other noise.

Reducing syntax isn’t itself a goal, particularly if the result could/would be confusing for someone who has to read and maintain your code later.

-Chris

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


(Zef Houssney) #8

Interesting thoughts! And thanks for the consideration Chris. Just a couple more thoughts and I’ll drop this :slight_smile:

Chris, I love the way you put this:

Since code is read more often than it is written, the real goal behind Swift is to let you write “more readable code” by eliminating boilerplate and other noise.

In my view, this proposal is aligned with that goal and it’s as much about readability as anything. I find this first example so much more readable at a glance, and I consider the duplicate names and equals sign to be in the boilerplate/noise category:

if let thing, otherThing, moreThings where thing > 0 { }
if let thing = thing, otherThing = otherThing, moreThings = moreThings where thing > 0 { }

Kevin, in regard to this:

Furthermore, to anyone not already familiar with the proposed rule, `if let foo {` is meaningless

I agree with David in that the existing syntax is already at the point where your statement is also true. There is nothing in the current syntax that indicates that you are unwrapping the optional. It’s only through learning or familiarity with other languages that one understands it. The = indicates assignment, but the unwrapping is learned and specific to that context. The jump to this seems super easy to grok.

Also my point isn’t that it’s doing the same thing technically, but that it’s a similar concept — assigning to a constant with the value derived implicitly by the context instead of directly through ‘=‘.

The idea of another keyword like “when” also seems plausible to me, though it’s a much more drastic change.

···

On Dec 3, 2015, at 8:13 PM, Sean Heber <sean@fifthace.com> wrote:

What about lifting the whole concept out of "if" or "guard" and making a new construct that directly communicates the intent?

For example:

when foo { ... }

Which could be combined with "where" to generate an if-like construct:

when foo where foo.isSomething { ... }

Inside the code block, you can access foo directly and it isn't shadowed - so if it was a var, it is mutable, etc.

l8r
Sean

On Dec 3, 2015, at 8:25 PM, David Waite <david@alkaline-solutions.com <mailto:david@alkaline-solutions.com>> wrote:

I might argue that if let is already an odd case; people often read it equivalent to "if (let x=x)”, but “let x=x” has completely different behavior outside the context of an if let statement (I in fact had to try it before I realized it does, in fact, work). Obviously, 'let x=x’ on its own could not have the same behavior.

In that spirit, I propose an alternative feature:

if foo? { … }

where the variable is not shadowed by a copy - instead, inside the block it behaves as an implicit unwrapped optional, including keeping any mutability.

so for example:

func foo(x:Int?) {
     if var x = x { // var so it can be assigned
         x++
     }
     print(x)
}

foo(1) // => 1, updating the aliased x does not do anything

# working code in Swift 1.2
func bar(x:Int?) {
     var y=x
     if let x=x {
         y=x+1
     }
     print(y)
}
bar(1) # => Optional(2)

# proposed
func proposed(x:Int?) {
     var y = x // since swift 3 won't have var function arguments
     if y? { // var so it can be assigned
         y++
     }
     print(y)
}

proposed(1) // => Optional(2)

-DW

On Dec 3, 2015, at 3:42 PM, Chris Lattner <clattner@apple.com <mailto:clattner@apple.com>> wrote:

“if let foo {“ is a frequently proposed extension to the syntax, but it is not one that we’re likely to ever add.

I agree that this is a common pattern, and it would allow you to “write less code”, but that isn’t the goal of Swift. Since code is read more often than it is written, the real goal behind Swift is to let you write “more readable code” by eliminating boilerplate and other noise.

Reducing syntax isn’t itself a goal, particularly if the result could/would be confusing for someone who has to read and maintain your code later.

-Chris

_______________________________________________
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 <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Sean Heber) #9

I am obviously biased in favor of a new keyword/construct for this. :slight_smile: The more I think about it, the more convinced I am that the intent of these scenarios should be conveyed in the code clearly so it is easily seen by future maintainers of that code. It may also help to guide the design of code in the same way that guard seems to alter how I now think about writing a function.

In any event, it is clear that there is a strong desire to solve a pain point, assuming we have correctly identified what pain, exactly, we are trying to solve. :slight_smile:

l8r
Sean

···

On Dec 3, 2015, at 10:57 PM, Zef Houssney <zefmail@gmail.com> wrote:

Interesting thoughts! And thanks for the consideration Chris. Just a couple more thoughts and I’ll drop this :slight_smile:

Chris, I love the way you put this:

Since code is read more often than it is written, the real goal behind Swift is to let you write “more readable code” by eliminating boilerplate and other noise.

In my view, this proposal is aligned with that goal and it’s as much about readability as anything. I find this first example so much more readable at a glance, and I consider the duplicate names and equals sign to be in the boilerplate/noise category:

if let thing, otherThing, moreThings where thing > 0 { }
if let thing = thing, otherThing = otherThing, moreThings = moreThings where thing > 0 { }

Kevin, in regard to this:

Furthermore, to anyone not already familiar with the proposed rule, `if let foo {` is meaningless

I agree with David in that the existing syntax is already at the point where your statement is also true. There is nothing in the current syntax that indicates that you are unwrapping the optional. It’s only through learning or familiarity with other languages that one understands it. The = indicates assignment, but the unwrapping is learned and specific to that context. The jump to this seems super easy to grok.

Also my point isn’t that it’s doing the same thing technically, but that it’s a similar concept — assigning to a constant with the value derived implicitly by the context instead of directly through ‘=‘.

The idea of another keyword like “when” also seems plausible to me, though it’s a much more drastic change.

On Dec 3, 2015, at 8:13 PM, Sean Heber <sean@fifthace.com> wrote:

What about lifting the whole concept out of "if" or "guard" and making a new construct that directly communicates the intent?

For example:

when foo { ... }

Which could be combined with "where" to generate an if-like construct:

when foo where foo.isSomething { ... }

Inside the code block, you can access foo directly and it isn't shadowed - so if it was a var, it is mutable, etc.

l8r
Sean

On Dec 3, 2015, at 8:25 PM, David Waite <david@alkaline-solutions.com> wrote:

I might argue that if let is already an odd case; people often read it equivalent to "if (let x=x)”, but “let x=x” has completely different behavior outside the context of an if let statement (I in fact had to try it before I realized it does, in fact, work). Obviously, 'let x=x’ on its own could not have the same behavior.

In that spirit, I propose an alternative feature:

if foo? { … }

where the variable is not shadowed by a copy - instead, inside the block it behaves as an implicit unwrapped optional, including keeping any mutability.

so for example:

func foo(x:Int?) {
     if var x = x { // var so it can be assigned
         x++
     }
     print(x)
}

foo(1) // => 1, updating the aliased x does not do anything

# working code in Swift 1.2
func bar(x:Int?) {
     var y=x
     if let x=x {
         y=x+1
     }
     print(y)
}
bar(1) # => Optional(2)

# proposed
func proposed(x:Int?) {
     var y = x // since swift 3 won't have var function arguments
     if y? { // var so it can be assigned
         y++
     }
     print(y)
}

proposed(1) // => Optional(2)

-DW

On Dec 3, 2015, at 3:42 PM, Chris Lattner <clattner@apple.com> wrote:

“if let foo {“ is a frequently proposed extension to the syntax, but it is not one that we’re likely to ever add.

I agree that this is a common pattern, and it would allow you to “write less code”, but that isn’t the goal of Swift. Since code is read more often than it is written, the real goal behind Swift is to let you write “more readable code” by eliminating boilerplate and other noise.

Reducing syntax isn’t itself a goal, particularly if the result could/would be confusing for someone who has to read and maintain your code later.

-Chris

_______________________________________________
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


(Dan Appel) #10

I would like to add on to your idea and propose mixing in David's
suggestion:

if let thing?, otherThing?, moreThings? where thing > 0 { }

I think this makes it clearer that the variables are optionals, which could
lead newcomers to infer that they are being unwrapped. Just my two cents.

Also,

I agree with David in that the existing syntax is already at the point
where your statement is also true.

is fair, but it is made significantly clearer that there is some sort of
assignment going on in the existing implementation (because of the equal
sign).

···


Dan Appel

On Thu, Dec 3, 2015 at 8:57 PM Zef Houssney <zefmail@gmail.com> wrote:

Interesting thoughts! And thanks for the consideration Chris. Just a
couple more thoughts and I’ll drop this :slight_smile:

Chris, I love the way you put this:

Since code is read more often than it is written, the real goal behind
Swift is to let you write “more readable code” by eliminating boilerplate
and other noise.

In my view, this proposal is aligned with that goal and it’s as much about
readability as anything. I find this first example so much more readable at
a glance, and I consider the duplicate names and equals sign to be in the
boilerplate/noise category:

if let thing, otherThing, moreThings where thing > 0 { }

if let thing = thing, otherThing = otherThing, moreThings = moreThings where thing > 0 { }

Kevin, in regard to this:

Furthermore, to anyone not already familiar with the proposed rule, `if
let foo {` is meaningless

I agree with David in that the existing syntax is already at the point
where your statement is also true. There is nothing in the current syntax
that indicates that you are unwrapping the optional. It’s only through
learning or familiarity with other languages that one understands it. The =
indicates assignment, but the unwrapping is learned and specific to that
context. The jump to this seems super easy to grok.

Also my point isn’t that it’s doing the same thing technically, but that
it’s a similar concept — assigning to a constant with the value derived
implicitly by the context instead of directly through ‘=‘.

The idea of another keyword like “when” also seems plausible to me, though
it’s a much more drastic change.

On Dec 3, 2015, at 8:13 PM, Sean Heber <sean@fifthace.com> wrote:

What about lifting the whole concept out of "if" or "guard" and making a
new construct that directly communicates the intent?

For example:

when foo { ... }

Which could be combined with "where" to generate an if-like construct:

when foo where foo.isSomething { ... }

Inside the code block, you can access foo directly and it isn't shadowed -
so if it was a var, it is mutable, etc.

l8r
Sean

On Dec 3, 2015, at 8:25 PM, David Waite <david@alkaline-solutions.com> > wrote:

I might argue that if let is already an odd case; people often read it
equivalent to "if (let x=x)”, but “let x=x” has completely different
behavior outside the context of an if let statement (I in fact had to try
it before I realized it does, in fact, work). Obviously, 'let x=x’ on its
own could not have the same behavior.

In that spirit, I propose an alternative feature:

if foo? { … }

where the variable is not shadowed by a copy - instead, inside the block
it behaves as an implicit unwrapped optional, including keeping any
mutability.

so for example:

func foo(x:Int?) {
     if var x = x { // var so it can be assigned
         x++
     }
     print(x)
}

foo(1) // => 1, updating the aliased x does not do anything

# working code in Swift 1.2
func bar(x:Int?) {
     var y=x
     if let x=x {
         y=x+1
     }
     print(y)
}
bar(1) # => Optional(2)

# proposed
func proposed(x:Int?) {
     var y = x // since swift 3 won't have var function arguments
     if y? { // var so it can be assigned
         y++
     }
     print(y)
}

proposed(1) // => Optional(2)

-DW

On Dec 3, 2015, at 3:42 PM, Chris Lattner <clattner@apple.com> wrote:

“if let foo {“ is a frequently proposed extension to the syntax, but it is
not one that we’re likely to ever add.

I agree that this is a common pattern, and it would allow you to “write
less code”, but that isn’t the goal of Swift. Since code is read more
often than it is written, the real goal behind Swift is to let you write
“more readable code” by eliminating boilerplate and other noise.

Reducing syntax isn’t itself a goal, particularly if the result
could/would be confusing for someone who has to read and maintain your code
later.

-Chris

_______________________________________________
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

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


(Lily Ballard) #11

If we change anything based on this, I’d suggest the simpler change of removing `if let`/`while let` and renaming `if case`/`while case` to `if let`/`while let`. Since Swift now has the ? pattern type to mean optional binding, it means that all existing instances of

    if let foo = bar {

become the almost-identical

    if let foo? = bar {

That said, I’m not convinced we actually have to change anything, but if we do change anything, this seems like the change to make. Of course, it doesn’t actually solve the original poster’s problem of wanting to type less when shadowing an optional value, but I agree completely with Chris Lattner that the goal of Swift is not to be terse but to be readable.

-Kevin Ballard

···

On Dec 3, 2015, at 9:15 PM, Sean Heber <sean@fifthace.com> wrote:

I am obviously biased in favor of a new keyword/construct for this. :slight_smile: The more I think about it, the more convinced I am that the intent of these scenarios should be conveyed in the code clearly so it is easily seen by future maintainers of that code. It may also help to guide the design of code in the same way that guard seems to alter how I now think about writing a function.

In any event, it is clear that there is a strong desire to solve a pain point, assuming we have correctly identified what pain, exactly, we are trying to solve. :slight_smile:

l8r
Sean

On Dec 3, 2015, at 10:57 PM, Zef Houssney <zefmail@gmail.com <mailto:zefmail@gmail.com>> wrote:

Interesting thoughts! And thanks for the consideration Chris. Just a couple more thoughts and I’ll drop this :slight_smile:

Chris, I love the way you put this:

Since code is read more often than it is written, the real goal behind Swift is to let you write “more readable code” by eliminating boilerplate and other noise.

In my view, this proposal is aligned with that goal and it’s as much about readability as anything. I find this first example so much more readable at a glance, and I consider the duplicate names and equals sign to be in the boilerplate/noise category:

if let thing, otherThing, moreThings where thing > 0 { }
if let thing = thing, otherThing = otherThing, moreThings = moreThings where thing > 0 { }

Kevin, in regard to this:

Furthermore, to anyone not already familiar with the proposed rule, `if let foo {` is meaningless

I agree with David in that the existing syntax is already at the point where your statement is also true. There is nothing in the current syntax that indicates that you are unwrapping the optional. It’s only through learning or familiarity with other languages that one understands it. The = indicates assignment, but the unwrapping is learned and specific to that context. The jump to this seems super easy to grok.

Also my point isn’t that it’s doing the same thing technically, but that it’s a similar concept — assigning to a constant with the value derived implicitly by the context instead of directly through ‘=‘.

The idea of another keyword like “when” also seems plausible to me, though it’s a much more drastic change.

On Dec 3, 2015, at 8:13 PM, Sean Heber <sean@fifthace.com <mailto:sean@fifthace.com>> wrote:

What about lifting the whole concept out of "if" or "guard" and making a new construct that directly communicates the intent?

For example:

when foo { ... }

Which could be combined with "where" to generate an if-like construct:

when foo where foo.isSomething { ... }

Inside the code block, you can access foo directly and it isn't shadowed - so if it was a var, it is mutable, etc.

l8r
Sean

On Dec 3, 2015, at 8:25 PM, David Waite <david@alkaline-solutions.com <mailto:david@alkaline-solutions.com>> wrote:

I might argue that if let is already an odd case; people often read it equivalent to "if (let x=x)”, but “let x=x” has completely different behavior outside the context of an if let statement (I in fact had to try it before I realized it does, in fact, work). Obviously, 'let x=x’ on its own could not have the same behavior.

In that spirit, I propose an alternative feature:

if foo? { … }

where the variable is not shadowed by a copy - instead, inside the block it behaves as an implicit unwrapped optional, including keeping any mutability.

so for example:

func foo(x:Int?) {
     if var x = x { // var so it can be assigned
         x++
     }
     print(x)
}

foo(1) // => 1, updating the aliased x does not do anything

# working code in Swift 1.2
func bar(x:Int?) {
     var y=x
     if let x=x {
         y=x+1
     }
     print(y)
}
bar(1) # => Optional(2)

# proposed
func proposed(x:Int?) {
     var y = x // since swift 3 won't have var function arguments
     if y? { // var so it can be assigned
         y++
     }
     print(y)
}

proposed(1) // => Optional(2)

-DW

On Dec 3, 2015, at 3:42 PM, Chris Lattner <clattner@apple.com <mailto:clattner@apple.com>> wrote:

“if let foo {“ is a frequently proposed extension to the syntax, but it is not one that we’re likely to ever add.

I agree that this is a common pattern, and it would allow you to “write less code”, but that isn’t the goal of Swift. Since code is read more often than it is written, the real goal behind Swift is to let you write “more readable code” by eliminating boilerplate and other noise.

Reducing syntax isn’t itself a goal, particularly if the result could/would be confusing for someone who has to read and maintain your code later.

-Chris

_______________________________________________
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 <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


(John McCall) #12

This is something we carefully considered after introducing the ? pattern, and in fact it was even implemented for a time. The lesson we took from that experience was that optional-binding is really, really important, and it really is worthwhile to recognize that importance by giving it special syntactic support.

John.

···

On Dec 3, 2015, at 11:07 PM, Kevin Ballard <kevin@sb.org> wrote:

If we change anything based on this, I’d suggest the simpler change of removing `if let`/`while let` and renaming `if case`/`while case` to `if let`/`while let`. Since Swift now has the ? pattern type to mean optional binding, it means that all existing instances of

    if let foo = bar {

become the almost-identical

    if let foo? = bar {


(Chris Lattner) #13

+1 to what John said. You can see this in the history, start with 20f8f09ea8de5eb1c0cb559e59c8a8e8a0e115a9. Sorry, but I don’t know how to turn that hash into a github URL.

-Chris

···

On Dec 4, 2015, at 9:47 AM, John McCall <rjmccall@apple.com> wrote:

On Dec 3, 2015, at 11:07 PM, Kevin Ballard <kevin@sb.org> wrote:

If we change anything based on this, I’d suggest the simpler change of removing `if let`/`while let` and renaming `if case`/`while case` to `if let`/`while let`. Since Swift now has the ? pattern type to mean optional binding, it means that all existing instances of

   if let foo = bar {

become the almost-identical

   if let foo? = bar {

This is something we carefully considered after introducing the ? pattern, and in fact it was even implemented for a time. The lesson we took from that experience was that optional-binding is really, really important, and it really is worthwhile to recognize that importance by giving it special syntactic support.


(Chris Lattner) #14

Ah, here you go:

The behavior was later reverted to the Swift 1 behavior of privileging “if let” for optionals.

-Chris

···

On Dec 5, 2015, at 9:52 AM, Chris Lattner <clattner@apple.com> wrote:

On Dec 4, 2015, at 9:47 AM, John McCall <rjmccall@apple.com> wrote:

On Dec 3, 2015, at 11:07 PM, Kevin Ballard <kevin@sb.org> wrote:

If we change anything based on this, I’d suggest the simpler change of removing `if let`/`while let` and renaming `if case`/`while case` to `if let`/`while let`. Since Swift now has the ? pattern type to mean optional binding, it means that all existing instances of

  if let foo = bar {

become the almost-identical

  if let foo? = bar {

This is something we carefully considered after introducing the ? pattern, and in fact it was even implemented for a time. The lesson we took from that experience was that optional-binding is really, really important, and it really is worthwhile to recognize that importance by giving it special syntactic support.

+1 to what John said. You can see this in the history, start with 20f8f09ea8de5eb1c0cb559e59c8a8e8a0e115a9. Sorry, but I don’t know how to turn that hash into a github URL.