[swift-evolution] ternary operator ?: suggestion

Jo Albright me at jo2.co
Tue Jan 5 12:58:38 CST 2016


> On Jan 5, 2016, at 12:23 PM, Thorsten Seitz <tseitz42 at icloud.com> wrote:
> 
> While it is real nice what can be done with a library solution, the switch-expression allows more than just comparing with a value. Library solutions won't be able to achieve the following features:
> 
> - pattern matching
> - where clauses
> - exhaustiveness check



I agree that all of those are also important. Below would allow for pretending to be a ternary operator with the switch style. The ternary switch proposal would basically be a reduction in syntax… removing “return”, “switch $0”, and some brackets. It could potentially open it up to some other possibilities as well. Just trying to come up with all options that are possible currently. Not against the proposal… just playing devil’s advocate.


func ??? <T:Comparable>(lhs: T, rhs: T -> AnyObject?) -> AnyObject? { return rhs(lhs) }

let color = 10 ??? {

    switch $0 {
        
    case 0..<10: return UIColor.clearColor()
    case let x where x < 20: return UIColor.yellowColor()
    case let x where x < 30: return UIColor.orangeColor()
    case let x where x < 40: return UIColor.redColor()
    default: return UIColor.whiteColor()
        
    }
    
}


 Nerd . Designer . Developer
Jo Albright



> 
> 
> -Thorsten 
> 
> Am 05.01.2016 um 18:10 schrieb Jo Albright via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>>:
> 
>> I am really enjoying this conversation. I think the ternary switch is useful for advanced one line case values. I have been playing to see what can currently be done. Attached is a playground for those who want to see results… the range case takes a second to run. I know there can be optimizations done, but just wanted to add my thoughts to the conversation. 
>> 
>> Chose ??? to denote a ternary switch, to be inline with ? = ternary, ?? = nil coalescing … the other two operators where just placeholders. I don’t believe || is a great solution as it is a comparison operator and —> is confusing and resembles return… but again, nothing serious... just playing with playground (indulging my current obsession with custom operators).
>> 
>> With the below, I don’t feel there is a huge need to change the language… unless incorporating the actual switch optimization is worth it.
>> 
>> Thanks,
>> Jo Albright
>> 
>> 
>> // ??? loops array and returns first element where lhs == element.0
>> infix operator ??? { associativity left precedence 200 }
>> 
>> // || merges values into an array
>> infix operator || { associativity left precedence 210 }
>> 
>> // --> convert lhs & rhs to tuple (lhs,rhs)
>> infix operator --> { associativity left precedence 220 }
>> 
>> func ??? <T: Equatable>(lhs: T?, rhs: [(T,AnyObject)]) -> AnyObject? {
>>     
>>     for r in rhs { if lhs == r.0 { return r.1 } }; return nil
>>     
>> }
>> 
>> func ??? <T: Equatable>(lhs: T, rhs: [(T,AnyObject)]) -> AnyObject? {
>>     
>>     for r in rhs { if lhs == r.0 { return r.1 } }; return nil
>> 
>> }
>> 
>> func || <T>(lhs: (T,AnyObject), rhs: (T,AnyObject)) -> [(T,AnyObject)] {
>>     
>>     return [lhs,rhs]
>> 
>> }
>> 
>> func || <T>(lhs: [(T,AnyObject)], rhs: (T,AnyObject)) -> [(T,AnyObject)] {
>>     
>>     return lhs + [rhs]
>> 
>> }
>> 
>> func || <T>(lhs: (Range<T>,AnyObject), rhs: (Range<T>,AnyObject)) -> [(T,AnyObject)] {
>>     
>>     return lhs.0.map { ($0,lhs.1) } + rhs.0.map { ($0,rhs.1) }
>>     
>> }
>> 
>> func || <T>(lhs: (Range<T>,AnyObject), rhs: (T,AnyObject)) -> [(T,AnyObject)] {
>>     
>>     return lhs.0.map { ($0,lhs.1) } + [rhs]
>> 
>> }
>> 
>> func || <T>(lhs: [(T,AnyObject)], rhs: (Range<T>,AnyObject)) -> [(T,AnyObject)] {
>>     
>>     return lhs + rhs.0.map { ($0,rhs.1) }
>> 
>> }
>> 
>> func --> <T>(lhs: T, rhs: AnyObject) -> (T,AnyObject) {
>>     
>>     return (lhs,rhs)
>> 
>> }
>> 
>> 
>> enum LifeStatus { case Alive, Dead, Zombie }
>> 
>> let life: LifeStatus? = .Dead
>> 
>> // embedded ternary operators … how I have built a ternary switch in past
>> let color1 = life == .Alive ? UIColor.greenColor() : life == .Dead ? UIColor.redColor() : life == .Zombie ? UIColor.grayColor() : UIColor.whiteColor()
>> 
>> // using custom operators
>> let color2 = life ??? .Alive --> UIColor.greenColor() || .Dead --> UIColor.redColor() || .Zombie --> UIColor.grayColor() ?? UIColor.whiteColor()
>> 
>> let age = 15
>> 
>> // works with ranges
>> let ageGroup = age ??? (0...1) --> "baby" || (2...4) --> "toddler" || (5...12) --> "kid" || (13...19) --> "teen" ?? "adult"
>> 
>> ageGroup // “teen”
>> 
>> 
>> <TernarySwitch.playground.zip>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160105/3850b6ae/attachment.html>


More information about the swift-evolution mailing list