[swift-evolution] ternary operator ?: suggestion
James Campbell
james at supmenow.com
Tue Dec 29 02:07:57 CST 2015
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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151229/cbaba067/attachment.html>
More information about the swift-evolution
mailing list