[swift-evolution] It's the little things..

Xiaodi Wu xiaodi.wu at gmail.com
Mon Dec 12 20:13:21 CST 2016


On Mon, Dec 12, 2016 at 6:15 PM, John Holdsworth via swift-evolution <
swift-evolution at 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 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.

Plus, that's what `flatMap` is for: `let a = key.flatMap { dict[$0] }`.

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 :)


> John
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20161212/96aaf0bf/attachment.html>


More information about the swift-evolution mailing list