[swift-evolution] ternary operator ?: suggestion
Matthew Johnson
matthew at anandabits.com
Tue Dec 29 07:38:04 CST 2015
Sent from my iPad
> On Dec 29, 2015, at 7:28 AM, Craig Cruden via swift-evolution <swift-evolution at swift.org> wrote:
>
> That looks pretty ugly.
>
> I think the best we can hope for at this point is maybe another keyword that mirrors switch but is expression based (aka match) — leaving the ternary ? : expression as is - which is not all that bad since any if else that becomes a compound expression or more than two resultant values (chaining) quickly becomes a mess.
I agree that this is probably the best path forward at the moment. There was a post early on showing a ternary-like switch expression. I don't remember whether there were any specific problems with that idea or not, but if there aren't that might best route forward.
>
> I am not sure that even a “match” expression would be accepted at this point because there seems to be general resistance to anything more than the existing paradigm with a few functional decorations — and the way of doing things is good enough.
>
> Concurrency is also currently off the table at this point -- the fact that immutable pure functional code can theoretically be parsed into a dependance graph which would allow for out of order [within scope] parallel execution on different threads [not sure if the overhead of doing so would outweigh the benefits]…. would also not be of sufficient benefit.
>
> The primary focus of Swift is a language for UI development, not server development….
>
>
>> On 2015-12-29, at 15:07:57, James Campbell via swift-evolution <swift-evolution at swift.org> wrote:
>>
>> What if you could wrap the existing switch statement in a closure and return a value from that closure like so
>>
>> Let value = { switch (other) {
>> Case .Some(let value):
>> Return value // because this is in a closure the closure will return the value not the function this is in
>> Case .None:
>> Return "hello"
>> }}
>>
>>
>> Sent from my iPhone
>>
>>> On 29 Dec 2015, at 07:53, Howard Lovatt via swift-evolution <swift-evolution at swift.org> wrote:
>>>
>>> You can replace the proposed statement `which` (another thread), the existing statement `?:` (this thread), and the global function `??` (which is an odd ball) with matching library methods.
>>>
>>> A library method is likely slower than a built in at this stage until the optimiser improves, but a library function:
>>>
>>> Is documented right in the IDE including code completion, statements aren’t (you don’t see quick help for `for`!)
>>> Having a library function allows the use case to be throughly investigated. Is worth while as a language statement? What exact features are useful? EG should `which` support pattern matching, general boolean expressions, or simply be `Equatable` as shown below?
>>> It is simpler to implement, maintain, and change a library function that a built-in.
>>> There is no need for a keyword.
>>>
>>> First `which`:
>>>
>>> // Alternative to introducing `which` statement
>>>
>>> final
>>> class Which<I: Equatable, R> {
>>> private
>>> var result: R?
>>>
>>> private
>>> let which: I
>>>
>>> init(_ which: I) {
>>> self.which = which
>>> }
>>>
>>> func match(value: I, @noescape matchResult: () throws -> R) rethrows -> Self {
>>> if self.result == nil && self.which == value {
>>> self.result = try matchResult()
>>> }
>>> return self
>>> }
>>>
>>> func matchDefault(@noescape defaultResult: () throws -> R) rethrows -> R {
>>> switch self.result {
>>> case .None:
>>> return try defaultResult()
>>> case .Some(let value):
>>> return value
>>> }
>>> }
>>> }
>>>
>>>
>>> // Demo
>>> enum Color {
>>> case Red, Blue, Green
>>> }
>>>
>>> // Which with a default value
>>> let i1 = Which(Color.Red) // i = 16711680
>>> .match(.Red) { 0xFF0000 }
>>> .match(.Green) { 0x00FF00 }
>>> .match(.Blue) { 0x00000FF }
>>> .matchDefault { 0 }
>>>
>>> // Which that throws an error if it defaults
>>> let i2: Int! = Which(Color.Green) // i = 16711680
>>> .match(.Red) { 0xFF0000 }
>>> .match(.Green) { 0x00FF00 }
>>> .match(.Blue) { 0x00000FF }
>>> .matchDefault { nil } // Cant type call to fatalError as no return, hence nil and type Int! (note !)
>>>
>>> Note runtime check for default rather than static check via compiler, not as good but not a big deal most of the time. The vast majority of languages don't do a compiler check on `switch`.
>>>
>>> Similarly the `?:` statement can be replaced:
>>>
>>> // Replacement for `?:` operator
>>>
>>> struct IfFalse<R> {
>>> private
>>> let result: R?
>>>
>>> func ifFalse(@noescape falseResult: () throws -> R) rethrows -> R {
>>> switch self.result {
>>> case .None:
>>> return try falseResult()
>>> case .Some(let value):
>>> return value
>>> }
>>> }
>>> }
>>>
>>> extension Bool {
>>> func ifTrue<R>(@noescape trueResult: () throws -> R) rethrows -> IfFalse<R> {
>>> switch self {
>>> case true:
>>> return IfFalse(result: try trueResult())
>>> case false:
>>> return IfFalse(result: nil)
>>> }
>>> }
>>> }
>>>
>>>
>>> // Demo
>>> let sB = true.ifTrue{"True"}.ifFalse{"False"} // "True" - for some reason needs {} and not () thinks () form throws
>>>
>>> Whilst the `??` operator is already a library function it is difficult to see in an expression, it gets buried, and is inconsistent in style because it is a non-mathematical operator and a symbol rather than a keyword or keyword followed by a symbol. The space either side of the `??` operator also makes it look like both arguments are of equal importance, whereas it is the left hand side that is important and the right hand side is just a catch.
>>>
>>> // Replacement for `??` operator
>>>
>>> extension Optional {
>>> func ifNil(@noescape nilResult: () throws -> Wrapped) rethrows -> Wrapped {
>>> switch self {
>>> case .None:
>>> return try nilResult()
>>> case .Some(let value):
>>> return value
>>> }
>>> }
>>> }
>>>
>>>
>>> // Demo
>>> let o: String? = nil
>>> let sO = o.ifNil{"Nil"} // "Nil" - for some reason needs {} and not () thinks () form throws
>>>
>>>
>>> Sent from my iPad
>>>
>>>> On 29 Dec 2015, at 4:00 AM, Thorsten Seitz via swift-evolution <swift-evolution at swift.org> wrote:
>>>>
>>>> No exhaustiveness checking is a serious deficiency :-(
>>>>
>>>> -Thorsten
>>>>
>>>>> Am 17.12.2015 um 08:09 schrieb Brent Royal-Gordon via swift-evolution <swift-evolution at swift.org>:
>>>>>
>>>>> Actually, this *almost* does what you want. No @autoclosure for the values and no exhaustiveness checking, but otherwise...
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> swift-evolution at swift.org
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> _______________________________________________
> 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/20151229/0a171b06/attachment.html>
More information about the swift-evolution
mailing list