That seems like a straight-forward way of plugging that particular hole in the
”less-than-normal” feature set of Swift.
I do, however, think that ??? Is not a great choice, because it doesn’t
indicate the error handling at all.
Considering that the traditional ?? means “unwrap optional or use the other
value’, I’d go for something along the lines of ?throw that means “unwrap
optional or throw error”.
func foo() throws -> String {
return bar ?throw EmbarrassingError.oops
}
But there are other holes in completeness of Swift’s features that are closely
related to this.
I opened a discussion a while back regarding something similar, but that
discussion got abandoned without a conclusion.
In a nutshell, I proposed making `throws` and `inout` less magical by promoting
them to proper declaration specifiers.
Currently, something like
var foo: inout String = &bar
can be exactly replicated in the following way:
var foo: String {
get {
return bar
}
set {
bar = newValue
}
}
So the would be just some minor syntax sugar for logical completeness and
convenience.
Further helping the logical completeness of `inout` would be allowing functions
to have a `get` and `set` accessors just like subscripts. This would allow
implementing a `set` accessor of the function, essentially making it an `inout`
function with all the usual perks like the prefix ampersand operator.
The `throws` could get the same treatment by first allowing property accessors
to be marked as `throws`:
var foo: String throws {
return try throwingFunction()
}
print(try foo)
Then getting a syntax sugar just like `inout`:
var foo: String throws = throwingFunction() // notice the lack of `try`, due to
the fact that the error from `throwingFunction()` is not thrown into the
current scope.
In cases where the getter and setter of the variable can have different thowing
capabilities, the trick used by access level indicators could be used:
var foo: String throws(set)
or
var foo: String throws(get)
What do you think?
> On Jul 30, 2017, at 9:37 PM, Erica Sadun <[email protected]> wrote:
>
> From 2016:
>
> See:
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160404/014272.html
>
> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160404/014272.html>
> and https://gist.github.com/erica/5a26d523f3d6ffb74e34d179740596f7
> <https://gist.github.com/erica/5a26d523f3d6ffb74e34d179740596f7>
>
> -- E
>
>> On Jul 30, 2017, at 12:30 PM, Gor Gyolchanyan via swift-evolution
>> <[email protected] <mailto:[email protected]>> wrote:
>>
>> I like the general direction where this is going, but I haven’t settled on
>> an opinion regarding its appearance yet.
>> I’ve argued before that the gap between optionals and errors should be
>> closed by making it easy to swift from optionals to non-optionals with
>> throwing.
>> The “unwrap-or-die” idea discussed earlier is very similar to this.
>>
>> In the end, I think all optional, throwing and fatalError-related proposals
>> have to be united and carefully considered as an overarching proposal to
>> extend and complete Swift’s representation of “less-than-normal” situations.
>>
>>> On Jul 30, 2017, at 9:25 PM, Robert Bennett via swift-evolution
>>> <[email protected] <mailto:[email protected]>> wrote:
>>>
>>> This idea was sparked by conversation in another thread about a more
>>> concise way to write the following:
>>>
>>> guard let x1 = f1(), let x2 = f2(), ... else { ... }
>>> doSomething(with: x1)
>>> doSomething(with: x2)
>>> ...
>>>
>>> It was suggested to write a function that throws when an optional is nil,
>>> and then wrapping the calls to f1, f2, ... in that function, and then
>>> wrapping *those* in a do-catch block. This would both exit early in case
>>> one value was nil, and also use the values as soon as they’re available
>>> instead of needing to assign them to a temp variable first and using the
>>> temp variable.
>>>
>>> Instead of a throwing unwrap function, I am proposing a throwing unwrap
>>> operator. This operator would work like !, but instead of a fatal error
>>> when the value is nil, it would throw.
>>>
>>> struct UnwrapError: Error {}
>>> postfix operator ^?
>>> extension Optional {
>>> static postfix func ^?(optional: Optional) throws -> Wrapped {
>>> guard let wrapped = optional else {
>>> throw UnwrapError()
>>> }
>>> return wrapped
>>> }
>>> }
>>>
>>> In addition, to round this out, I think it would be helpful to be able to
>>> throw arbitrary errors, as a nil value may carry meaning that should be
>>> propagated to the rest of the program. Thus there could be a throwing nil
>>> coalescing operator, which returns the unwrapped value if non-nil, or
>>> throws the specified error if nil.
>>>
>>> infix operator ^??
>>> extension Optional {
>>> static func ^??(lhs: Optional, rhs: Error) throws -> Wrapped {
>>> guard let wrapped = lhs else {
>>> throw rhs
>>> }
>>> return wrapped
>>> }
>>> }
>>>
>>> Thoughts? I think these would be helpful additions to allow doing something
>>> with Optionals while simultaneously exiting early in the case of a nil
>>> value — putting the unwrapping, the use, and the exiting early all on one
>>> line.
>>>
>>> Hopefully this doesn’t distract from the other important conversations
>>> happening on the mailing list!
>>> _______________________________________________
>>> swift-evolution mailing list
>>> [email protected] <mailto:[email protected]>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution