[swift-evolution] [Idea] Use optionals for non-optional parameters

Tim Vermeulen tvermeulen at me.com
Mon Aug 15 07:44:06 CDT 2016


> > On 15 Aug 2016, at 08:02, Justin Jia via swift-evolution<swift-evolution at swift.org(mailto:swift-evolution at swift.org)>wrote:
> > Hi!
> > 
> > I don’t know if this has came up before. I tried to search though the mailing list but didn’t find any related threads.
> > 
> > This is purely a syntactic thing (which I know it’s the lowest priority for Swift 4), but I think it’s an important one.
> > 
> > Let’s say we have a struct with a function:
> > 
> > ```
> > struct Foo {
> > func bar(x: Int)
> > }
> > ```
> > 
> > We can use optionals:
> > 
> > ```
> > let foo: Foo? = nil
> > let x = 1
> > foo!.bar(x: x) // Able to compile, but will cause runtime error
> > foo?.bar(x: x) // Able to compile, and won't cause runtime error
> > ```
> > 
> > However:
> > 
> > ```
> > let foo = Foo()
> > let x: Int? = nil
> > foo.bar(x: x!) // Able to compile, but will cause runtime error
> > foo.bar(x: x?) // Won't compile
> > ```
> > 
> > I propose that we should allow `foo.bar(x: x?)`, which should be equivalent to:
> > 
> > ```
> > if let x = x {
> > foo.bar(x: x)
> > }
> > ```
> > 
> > What do you think?
> I like the intent behind this, but personally I think it's not clear enough. For me, putting the statement in a conditional as you've shown is the better solution, as it's a lot clearer exactly what's going on. Putting a question mark on a variable makes it look like something specific to that variable, rather than preventing the entire statement from executing.

I get where you’re coming from, but how would people react if optional chaining wasn’t in the language yet and someone proposed it now? I know it’s not strictly the same thing, but it’s still a single question mark that prevents the whole statement from being executed. I think it would be met with a lot of resistance from people saying that being more explicit with `if let` is the way to go.

> There may be some alternatives though, for example, what about a shorthand for the conditional like so:
> 
> if let x? { foo.bar(x: x) }
> if x? { foo.bar(x: x) } // even shorter?

The alternatives you’ve come up with would only work if foo.bar doesn’t return anything. If it does return something, and you want to assign it to a variable, you have to declare the variable beforehand and it just becomes ugly. It’s then probably a better idea to use map/flatmap:

x.flatMap { foo.bar(x: $0) }

But IMO that's not as clean as `foo.bar(x: x?)`. flatMap is so hidden to most people that they resort to things like

myDictionary[myOptionalString ?? “”]

assuming that no key is the empty string. People might also make function overloads that accept and return optionals, just to avoid nesting. I’m sure you’ve seen something like this before:

if limit == nil || number < limit! { /* … */ }

There’s no great way to “fix” this. We can do

if limit.map({ number < $0 }) { /* … */ }

or we can overload the < operator for optionals to return Bool?, which we can use with

if (number < limit) ?? true { /* … */ }

With the new sugar, we’d be able to do

if (number < limit?) ?? true { /* … */ }

out of the box.

> But in general, I think it's best to be explicit about the entire statement being optional, which the conditional does but a postfix on a variable doesn't to the same degree._______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> 
> 


More information about the swift-evolution mailing list