[swift-evolution] ternary operator ?: suggestion

Thorsten Seitz tseitz42 at icloud.com
Fri Jan 8 07:34:30 CST 2016


> Am 08.01.2016 um 14:09 schrieb Craig Cruden <ccruden at novafore.com>:
> 
> Interesting, I have to take more time digging down.  
> 
> BTW, would it not be `case .Red in “0xFF0000” ` not case .Red: “0xFF0000” since `=>` in Swiftese is `in` 

My take is that the „=>“ after „case“ in Scala corresponds to the colon after „case" in Swift but the waters are a bit muddy here as the „case <pattern>“ takes the role of a function parameter as well.
I wouldn’t want to have two different „case“ expressions in Swift, though. Either both should use the colon or both should use „in“.

-Thorsten


>> On 2016-01-08, at 19:58:45, Thorsten Seitz <tseitz42 at icloud.com <mailto:tseitz42 at icloud.com>> wrote:
>> 
>> That is not a feature of Scala’s map or filter functions.
>> 
>> Writing { case (x, y) => x + y } just defines an anonymous unary function, more specifically a partially defined function or PartialFunction (http://www.scala-lang.org/api/current/index.html#scala.PartialFunction <http://www.scala-lang.org/api/current/index.html#scala.PartialFunction>).
>> 
>> Btw: partial functions are quite cool as they can be chained, e.g. by „orElse“ if the first function is not defined for a given input. This allows quite nice abstractions (I’m thinking or error handler functions, for example).
>> 
>> So the question is whether we would want something like that in Swift, too, i.e.
>> 
>> { case <pattern1>: <expr1> [case <pattern2>: <expr2>]* [default: <expr>] } 
>> would define a unary function which matches its input against the case patterns and returns value of the matching expression.
>> 
>> (It would probably make sense to introduce partial functions as well on top of that, i.e. make this a partial function which might even statically know that it is defined everywhere in case the compiler can check the exhaustiveness of the patterns.)
>> 
>> Then we could simply define the following function
>> 
>> func match<T,U>(x: T, f: T -> U) {
>> 	return f(x)
>> }
>> 
>> which would allow us to write a switch-expression without any further syntax extensions:
>> 
>> let value = match(color) { 
>> 	case .Red: "0xFF0000“
>> 	case .Green: "0x00FF00“
>> 	case .Blue: "0x0000FF“
>> }
>> 
>> And we could also just write the map example Craig gave with no magic in the definition of map required:
>> 
>> num.map {
>> 	case x where x < 5: x + 1
>> 	case x: x - 1
>> }
>> 
>> 
>> For comparison: with my proposal of a ternary-like switch-expression this would look like follows instead:
>> 
>> num.map { elem in elem?
>> 	case x where x < 5: x + 1
>> 	case x: x - 1
>> }
>> 
>> where we are using the switch-expression
>> 
>> elem?
>> 	case x where x < 5: x + 1
>> 	case x: x - 1
>> 
>> 
>> But then the question arises: shouldn’t { case <pattern>: <expr> … } allow statements, too?
>> I would think so.
>> In Scala this is allowed, e.g. I can write
>> val f: PartialFunction[Any, Int] = { case x: Int => { println(x); x + 1 } }
>> 
>> -Thorsten
>> 
>> 
>> 
>>> Am 08.01.2016 um 06:11 schrieb Craig Cruden via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>>:
>>> 
>>> I was thinking about this a bit, and was thinking that maybe we would not need a new keyword at all but just use `map` with pattern matching `case` clauses.  It would mean adding `map` to individual values — or anything that we might want to use as input for matching.  
>>> 
>>> Reference scala (section 8.5) pattern matching: http://www.scala-lang.org/docu/files/ScalaReference.pdf <http://www.scala-lang.org/docu/files/ScalaReference.pdf>
>>> 
>>> In scala inside `map` and `filter` (unfortunately not on things like `reduceLeft` or `foldLeft` you can specify pattern matching anonymous functions as such:
>>> 
>>> val num = List(1, 5, 7)
>>> 
>>> num.map {
>>>   case x if x < 5 => x + 1
>>>   case x => x - 1
>>> }
>>> 
>>> output: List(2, 4, 6)
>>> 
>>> So if the pattern matching was added (I don’t believe Swift currently allows case classes in maps - but then I am rather junior in the language) Swift would not need a `match expression` it would simply be part of map and become something like:
>>> 
>>> let commission = trade.map {
>>> 	case .Buy(let quantity, let price) where Double(quantity) * price > 10000 in
>>>     		Double(quantity) * price * vipCommissionRate / 100
>>> 	case .Buy(let quantity, let price):
>>>     		Double(quantity) * price * commissionRate / 100
>>> 	case .Sell(let quantity, let price) where Double(quantity) * price > 10000:
>>>     		Double(quantity) * price * vipCommissionRate / 100
>>> 	case .Sell(let quantity, let price):
>>>     		Double(quantity) * price * commissionRate / 100
>>> }
>>> 
>>> 
>>> 
>>> 
>>>> 
>>>> But if we go with brackets then I would recommend something like this: 
>>>> 
>>>> let commission = match (trade) {
>>>> case .Buy(let quantity, let price) where Double(quantity) * price > 10000:
>>>>     Double(quantity) * price * vipCommissionRate / 100
>>>> case .Buy(let quantity, let price):
>>>>     Double(quantity) * price * commissionRate / 100
>>>> case .Sell(let quantity, let price) where Double(quantity) * price > 10000:
>>>>     Double(quantity) * price * vipCommissionRate / 100
>>>> case .Sell(let quantity, let price):
>>>>     Double(quantity) * price * commissionRate / 100
>>>> }
>>> 
>>> 
>>> _______________________________________________
>>> 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/20160108/e975f513/attachment.html>


More information about the swift-evolution mailing list