[swift-evolution] ternary operator ?: suggestion

Craig Cruden ccruden at novafore.com
Fri Jan 8 07:47:41 CST 2016


I did a quick read of the PartialFunction documentation and just reading the example it looks like the pattern matching is not based on the foundation of PartialFunction just that it can be used in a PartialFunction (not exhaustive because it is partial).  If I only do not have an exhaustive pattern matching though it will blow chunks in map because it obviously is not a full function.  

Not being an expert it does not look like case pattern matching is dependent on PartialFunction so it would be a separate feature (obviously a cool feature that would be nice).  


> On 2016-01-08, at 19:58:45, Thorsten Seitz <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
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160108/18636723/attachment.html>


More information about the swift-evolution mailing list