As the festive season approaches I thought I’d write a brain dump
of a few things I'd hope Santa could bring in his bag for Swift 3.1.
No big ideas, just things that bug me day to day and would be
backward source compatible.

I’m sure it’s been discussed before but I wish static and class vars and
functions were in scope for instance methods without having to prefix them
as they are in Java. I’d go further and say they should be available when
referring to an object outside the class as if they were instance methods
i.e. object.classMethod().

Occasionally I find myself wishing I could give a static variable function
or method scope i.e. declare it inside the function or method if there are
no other references to localise access.

I’d like to raise again the idea of optionality when referencing a key or
calling a function could be possible using a ? i.e instead of

let a = key != nil ? dict[key] : nil

you could just write:

let a = dict[key?]

or even

let a = func( arg: argumentThatMayBeNull? ) // not called if argument is nil

As subscripts are functions these are probably the same thing.

One thing I encountered the recently writing a (bad) regular expression
library was that I wish getters were not required for subscript overloads.
In the library I wanted to write multiple setters for different types being
assigned but you only want one declared getter or you get ambiguities.

And of course, multi-line string literals using either “””long string””” or <<“HEREDOC”.

As the festive season approaches I thought I’d write a brain dump
of a few things I'd hope Santa could bring in his bag for Swift 3.1.
No big ideas, just things that bug me day to day and would be
backward source compatible.

I’m sure it’s been discussed before but I wish static and class vars and
functions were in scope for instance methods without having to prefix them
as they are in Java.

I agree that it's annoying to have to prefix them with
`VeryLongTypeNames.everyTime()`. Fortunately, SE-0068 was already approved
a long time ago that makes this a lot better, though it's not the specific
solution you're advocating for. Namely, we'll be able to write
`Self.everyTime()` instead, and IMO it can't come fast enough. It's just
that no one has stepped up to implement it. Santa?

I’d go further and say they should be available when
referring to an object outside the class as if they were instance methods
i.e. object.classMethod().

Occasionally I find myself wishing I could give a static variable function
or method scope i.e. declare it inside the function or method if there are
no other references to localise access.

I’d like to raise again the idea of optionality when referencing a key or
calling a function could be possible using a ? i.e instead of

let a = key != nil ? dict[key] : nil

you could just write:

let a = dict[key?]

or even

let a = func( arg: argumentThatMayBeNull? ) // not called if
argument is nil

As subscripts are functions these are probably the same thing.

We've had several discussions about this particular proposal on the list,
as you've alluded to. Core team members have chimed in and said that this
was considered and rejected. One specific point has convinced me that it is
a superficially delightful idea with _very_ high footgun potential--

The expression `a()?.b()?.c()` clearly short-circuits. That is, if `a() ==
nil`, then `b()` is never called. It's not just a way of making code
terser; the short-circuiting behavior is critical.

Now, given `let result = foo(a(), b()?, c(), d()?)`, how does that line of
code short-circuit, or should all arguments be evaluated regardless?

There is no single obviously correct answer. Is a() called before b()
because it's the first argument--as it would be if we had written `foo(a(),
b(), c(), d())`--or is b() called before a() because it's the first
potentially short-circuiting argument, by analogy with `a()?.b()?.c()`? Is
c() always called, as it would be by analogy with `foo(a(), b(), c(),
d())`, or sometimes not called, by analogy with `a()?.b()?.c()`?

Now if we *do* short-circuit, suppose the signature of foo is changed in a
subsequent version of a library so that you must supply the arguments in a
different order, what then? Suppose we have now `let result = foo(d()?,
c(), b()?, a())` and that a(), b(), c(), d() have side effects. All of a
sudden, a seemingly innocuous change by a library vendor could totally
change the behavior of our code.

You might say: it's uncommon to nest functions like that. Maybe, but keep
in mind that computed properties and subscripts are just functions. It
cannot be known on inspection whether any particular property is computed
and might have side effects. This has convinced me that the potential for
this syntax to be silently tricky outweighs the benefits of shorter syntax,
and that the core team made the right choice in rejecting it initially.

One thing I encountered the recently writing a (bad) regular expression

library was that I wish getters were not required for subscript overloads.
In the library I wanted to write multiple setters for different types being
assigned but you only want one declared getter or you get ambiguities.

And of course, multi-line string literals using either “””long string”””
or <<“HEREDOC”.

I'm sure that will be a lively discussion in Swift 4 phase 2 in the new
year. Happy holidays everyone

You can do something like this, but I’d recommend labeling the subscript. The problem comes up when you have a dictionary that has an optional key: When you use “myDict[nil]”, you may get one or the other, but you probably mean one specifically.

Using a label on the subscript solves this, and makes the code more explicit that you’re not just getting the normal subscript that everyone would expect.

Allowing `?` at an arbitrary position like this has ambiguity problems, since it isn't clear how much of the enclosing expression needs to be conditionalized on the unwrapped optional. This would be hard for humans to read, and it'd be an exponential search for the compiler to find a solution that works. You can use Optional's `map` and `flatMap` to chain an arbitrary closure, though. `dict[key?]` would be `key.flatMap { dict[$0] }`, and `func(arg: optional?)` would be `optional.flatMap { func(arg: $0) }`.

As the festive season approaches I thought I’d write a brain dump
of a few things I'd hope Santa could bring in his bag for Swift 3.1.
No big ideas, just things that bug me day to day and would be
backward source compatible.

I’m sure it’s been discussed before but I wish static and class vars and
functions were in scope for instance methods without having to prefix them
as they are in Java. I’d go further and say they should be available when
referring to an object outside the class as if they were instance methods
i.e. object.classMethod().

Occasionally I find myself wishing I could give a static variable function
or method scope i.e. declare it inside the function or method if there are
no other references to localise access.

I’d like to raise again the idea of optionality when referencing a key or
calling a function could be possible using a ? i.e instead of

let a = key != nil ? dict[key] : nil

you could just write:

let a = dict[key?]

or even

let a = func( arg: argumentThatMayBeNull? ) // not called if argument is nil

On Mon, Dec 12, 2016 at 6:15 PM, John Holdsworth via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
I’m sure it’s been discussed before but I wish static and class vars and
functions were in scope for instance methods without having to prefix them
as they are in Java.

I agree that it's annoying to have to prefix them with `VeryLongTypeNames.everyTime()`. Fortunately, SE-0068 was already approved a long time ago that makes this a lot better, though it's not the specific solution you're advocating for. Namely, we'll be able to write `Self.everyTime()` instead, and IMO it can't come fast enough. It's just that no one has stepped up to implement it. Santa?

If not using '?' at arbitrary positions, but instead applying '?' to the
function call, it looks like it's possible to enable OK syntax by defining
a custom operator (at least for unnamed args):
let result = fn<-?(a, b)
Here:
- fn is a function that has two non-optional parameters
- a and b are optionals of the same type as the parameters
- fn is called if both a and b are non-nil
- result is nil if either a or b are nil, otherwise it's the value
returned by calling fn

> On Dec 12, 2016, at 4:15 PM, John Holdsworth via swift-evolution < > swift-evolution@swift.org> wrote:
>
> As the festive season approaches I thought I’d write a brain dump
> of a few things I'd hope Santa could bring in his bag for Swift 3.1.
> No big ideas, just things that bug me day to day and would be
> backward source compatible.
>
> I’m sure it’s been discussed before but I wish static and class vars and
> functions were in scope for instance methods without having to prefix
them
> as they are in Java. I’d go further and say they should be available when
> referring to an object outside the class as if they were instance methods
> i.e. object.classMethod().
>
> Occasionally I find myself wishing I could give a static variable
function
> or method scope i.e. declare it inside the function or method if there
are
> no other references to localise access.
>
> I’d like to raise again the idea of optionality when referencing a key or
> calling a function could be possible using a ? i.e instead of
>
> let a = key != nil ? dict[key] : nil
>
> you could just write:
>
> let a = dict[key?]
>
> or even
>
> let a = func( arg: argumentThatMayBeNull? ) // not called if
argument is nil
>
> As subscripts are functions these are probably the same thing.

Allowing `?` at an arbitrary position like this has ambiguity problems,
since it isn't clear how much of the enclosing expression needs to be
conditionalized on the unwrapped optional. This would be hard for humans to
read, and it'd be an exponential search for the compiler to find a solution
that works. You can use Optional's `map` and `flatMap` to chain an
arbitrary closure, though. `dict[key?]` would be `key.flatMap { dict[$0]
}`, and `func(arg: optional?)` would be `optional.flatMap { func(arg: $0)
}`.

You can do something like this, but I’d recommend labeling the subscript. The problem comes up when you have a dictionary that has an optional key: When you use “myDict[nil]”, you may get one or the other, but you probably mean one specifically.

I don’t think that’s an issue in the stdlib, because `Optional` doesn’t conform to `Hashable` and, AFAIK, no other stdlib types conform to `ExpressibleByNilLiteral`. Custom types could conform to both, though, and according to a playground, that does indeed lead to some confusing code:
struct Foo : ExpressibleByNilLiteral, Hashable {...}
extension Dictionary { subscript(_ key:Key?) -> Value? { return key != nil ? self[key!] : nil } }
var bar = [Foo:Int]()
bar[nil] //calls `Foo.init(nilLiteral:())`, and tries to look up the new `Foo` in `bar` using the stdlib's subscript
bar[nil as Foo?] //passes `Optional<Foo>.none, which uses the extension's subscript

Using a label on the subscript solves this, and makes the code more explicit that you’re not just getting the normal subscript that everyone would expect.

Yeah, that would certainly solve it. Kind of a shame, though, since it’d be one less function to think about, and 99.998% of the time it’d give the right answer. Too bad we can’t extend stuff where some condition isn’t met, like "extension Dictionary where !(Key: ExpressibleByNilLiteral) {…}” or something.

We haven't had time to invest in implementing this yet. Since it's a purely additive feature, the acceptance of the proposal still stand, and we would accept a good implementation of it at any time. It does however require some relatively deep refactoring of the modeling of Self types across the AST and SIL layers, which is currently very superficial, in order to successfully implement, which is part of why we haven't gotten around to it yet.

You can do something like this, but I’d recommend labeling the subscript. The problem comes up when you have a dictionary that has an optional key: When you use “myDict[nil]”, you may get one or the other, but you probably mean one specifically.

I don’t think that’s an issue in the stdlib, because `Optional` doesn’t conform to `Hashable` and, AFAIK, no other stdlib types conform to `ExpressibleByNilLiteral`. Custom types could conform to both, though, and according to a playground, that does indeed lead to some confusing code:
struct Foo : ExpressibleByNilLiteral, Hashable {...}
extension Dictionary { subscript(_ key:Key?) -> Value? { return key != nil ? self[key!] : nil } }
var bar = [Foo:Int]()
bar[nil] //calls `Foo.init(nilLiteral:())`, and tries to look up the new `Foo` in `bar` using the stdlib's subscript
bar[nil as Foo?] //passes `Optional<Foo>.none, which uses the extension's subscript

You can do something like this, but I’d recommend labeling the subscript. The problem comes up when you have a dictionary that has an optional key: When you use “myDict[nil]”, you may get one or the other, but you probably mean one specifically.

I don’t think that’s an issue in the stdlib, because `Optional` doesn’t conform to `Hashable` and, AFAIK, no other stdlib types conform to `ExpressibleByNilLiteral`. Custom types could conform to both, though, and according to a playground, that does indeed lead to some confusing code:
struct Foo : ExpressibleByNilLiteral, Hashable {...}
extension Dictionary { subscript(_ key:Key?) -> Value? { return key != nil ? self[key!] : nil } }
var bar = [Foo:Int]()
bar[nil] //calls `Foo.init(nilLiteral:())`, and tries to look up the new `Foo` in `bar` using the stdlib's subscript
bar[nil as Foo?] //passes `Optional<Foo>.none, which uses the extension's subscript

I wouldn't be surprised if there's a proposal to make Optional conditionally conform to Hashable if/when we get conditional conformances.

It is a hash, collision is fine. It is just a single value. I guess a hashValue of zero works well for `nil`.

···

On Dec 14, 2016, at 11:08 AM, David Sweeris via swift-evolution <swift-evolution@swift.org> wrote:
I'll be curious as to how they propose we prevent collisions between Optional<T>.none.hashValue and any given T's hash value.