[swift-evolution] ternary operator ?: suggestion

Maximilian Hünenberger m.huenenberger at me.com
Sun Jan 17 20:21:41 CST 2016


See below

> Am 17.01.2016 um 20:05 schrieb Paul Ossenbruggen <possen at gmail.com>:
> 
> 
>> On Jan 17, 2016, at 10:07 AM, Maximilian Hünenberger via swift-evolution <swift-evolution at swift.org> wrote:
>> 
>> I totally agree with your statement that it should only be a short form of a single switch in a closure.
>> 
>> I think only allowing expressions is too limiting so in case of writing `return` it can be omitted if there is only one expression after a case-label. 
> 
> I am fine with this idea. It would require that we check the number of lines in in the statement and produce an error or warning if there are more than one statement. This works especially well when the expression is on the same line as the label.
> 
>> 
>> Having more types which have a `map` function it seems that it could be handled with a protocol with a default implementation.
>>         Concern: Also it could be easily confused with the `map` of collections where the closure doesn't take the collection itself but it's elements. Would be a new name like `mapElements` for collections considerable?
> 
> We want to allow the higher order functions such as map, reduce on both containers and scalars. So on a collection it would perform the case mapping on each element in the collection. Unless I am misunderstanding what you are saying. 
> 

If a switch statement can in future destruct a Sequence/Array the call of `map` would be ambiguous:

// [Int] mapped to one Int?
[1, 2, 3].map{
    case let [x]: x
    case let [1, x]: x
    case let [1, 2, x]: x
    default: nil
}

// [Int] mapped to [Int] / multiple Int
[1, 2, 3].map{
    case 1: 3
    case 2: 2
    case 3: 1
    default: 0
}

So in the latter example `map` could be renamed to `mapElements`.

You said `reduce` could be used. Can you give an example how to use this?:
1234.reduce(...)


- Maximilian

>> 
>> 
>> Should the ternary operator be removed in favor of:
>> 
>> (4 < index).map{ cases true: 5, false: 7 }
>> // in comparison
>> 4 < index ? 5 : 7
>> 
>> I would not remove the ternary operator since it is "too" concise and useful for short expressions.
>>         Otherwise since this is a short `switch` statement there could also be a short `if`:
>> 
>> // to be discussed
>> (4 < index).map{ 5 ||| 7 }
> 
> I was thinking something like this for the else. It is less than or greater than. It kind looks like a scale to make a decision.
> 
> (4 < index).map{ 5 <> 7 }
> 
> Anyway, this is not much longer than:
> 
> 4 < index ? 5 : 7
> 
> But sure, we can keep ternary as is. Python generally tries to have one way to do things,  Ruby goes to the other extreme of multiple ways to do the same thing. I have heard no such argument made with Swift though. Swift does seem to more closely follow the Python philosophy because it allows breaking changes that can be fixed up with the conversion tools, but ternary may be the exception just because it has so much history around it. 
> 
>> 
>> Because we are moving away from a ternary operator should this be discussed in a new thread?
>> Like: Add short form of `switch` and `if` in closures
> 
> Well, we are over 300 messages now, so why stop? Should be no problem for someone to get caught up. :-) Actually, maybe not a bad idea. 
> 
>> - Maximilian
>> 
>>> Am 17.01.2016 um 18:00 schrieb Thorsten Seitz via swift-evolution <swift-evolution at swift.org>:
>>> 
>>> Maybe I misread your proposed beginning, but the proposal should not be about introducing a new map method. 
>>> It introduces a new way of writing unary closures (i.e. closures taking one argument) with case clauses, i.e
>>> 
>>> instead of having to write
>>> 
>>> { x in 
>>> 	switch x {
>>> 	case .Cold: return „Too cold“
>>> 	case .Hot: return „Too hot“
>>> 	default: return „Just right“
>>> 	}
>>> }
>>> 
>>> we could just write
>>> 
>>> { 	
>>> 	case .Cold: „Too cold“
>>> 	case .Hot: „Too hot“
>>> 	default: „Just right“
>>> }
>>> 
>>> The case clauses may (or must?) be expressions instead of statements.
>>> 
>>> This will work with any higher order function, not just map, as the result is just a normal closure. No special version of „map“ needed.
>>> 
>>> -Thorsten
>>> 
>>> 
>>>> Am 17.01.2016 um 13:37 schrieb Charles Constant via swift-evolution <swift-evolution at swift.org>:
>>>> 
>>>> It's better, but it still seems a bit dry to me. I tried rewriting the beginning. Is it better to start off like this?
>>>> 
>>>> We are proposing a new “map” method. It directly addresses a “mapping” problem that pops up in almost all Swift programs, and currently has no elegant solution. The syntax we propose makes Swift code easier to read, easier to write, and less buggy.
>>>> 
>>>> Here is an example of the problem, where we want to assign a string mapped to an enum case:
>>>> 
>>>> 	let str:String
>>>> 	
>>>> 	switch state {
>>>> 	case .Cold: 
>>>> 		str = “Too cold”
>>>> 	case .Hot: 
>>>> 		str = “Too hot”
>>>> 	default: 
>>>> 		str = “Just right”
>>>> 	}
>>>> 
>>>> The syntax above does not elegantly express our intent. The “switch” statement is designed for “flow control”, but aside from choosing a single value, our example needs no “flow control”. Moreover, the ability to execute unrelated statements inside the “switch” encourages buggy code. Use of the “switch” statement for this task leads to bloated, confusing, error-prone code.
>>>> 
>>>> Do you like it? It's all pretty subjective, I suppose.
>>>> 
>>>> 
>>>>> On Sat, Jan 16, 2016 at 8:51 PM, Craig Cruden <ccruden at novafore.com> wrote:
>>>>> Forgot to include the link so people don’t need to search:
>>>>> 
>>>>> https://github.com/cacruden/swift-evolution/blob/master/proposals/0000-Pattern-Matching-Partial-Function.md
>>>>> 
>>>>> 
>>>>>> On 2016-01-17, at 11:43:39, Craig Cruden <ccruden at novafore.com> wrote:
>>>>>> 
>>>>>> Updated the the motivation clause - not sure I am 100% there yet - but hopefully closer.  
>>>>>> 
>>>>>> As well as a few minor updates to things like let on reduce example and clarifying that the partial closures can use the optional return keyword.
>>>>>> 
>>>>>> 
>>>>>>> On 2016-01-15, at 4:16:56, Charles Constant <charles at charlesism.com> wrote:
>>>>>>> 
>>>>>>> Hi Craig,
>>>>>>> 
>>>>>>> Well done, what you wrote looks pretty good to me. I had no trouble understanding the proposal. It's a good length, too - I think the shorter we can make it, the more appealing it is. 
>>>>>>> 
>>>>>>> The only section that I think needs improvement is "Motivation." I think we could sell it better. I know when I've read some of the other proposals, I do it in fairly cursory way.
>>>>>>> "Motivation" could be clearer for those of our peers who haven't followed the thread. 
>>>>>>> 
>>>>>>> The motivation, from my point of view:
>>>>>>> - the need to use a value from one domain, as a "key" to another is very common. The ternary is a special case of this, and for all it's flaws, it's a very popular expression in multiple languages  
>>>>>>> - using the existing "switch" to do this is bloated (more so in Swift because you have to declare the variable before the switch statement)
>>>>>>> - using the existing "switch" to do this is less safe, because unrelated code can be inserted in the case statements
>>>>>>> - current alternatives to "switch" aren't good (e.g.: using a Dict has quirks that add the cognitive load)
>>>>>>> - this new "map" method can make code less verbose, easier to read, and safer
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>>> On Thu, Jan 14, 2016 at 11:23 AM, Craig Cruden <ccruden at novafore.com> wrote:
>>>>>>>> Paul, 
>>>>>>>> 
>>>>>>>> I tried to put my understanding on the latest proposal option into a draft on github (instead of my usual BitBucket repo).  
>>>>>>>> 
>>>>>>>> Take a look at it and see if there is anything useable.
>>>>>>>> 
>>>>>>>> https://github.com/cacruden/swift-evolution/blob/master/proposals/0000-Pattern-Matching-Partial-Function.md
>>>>>>>> 
>>>>>>>> Craig
>>>>>>>> 
>>>>>>>>> On 2016-01-11, at 14:17:09, Craig Cruden <ccruden at novafore.com> wrote:
>>>>>>>>> 
>>>>>>>>> Ignore the last comment - tired and mistaken. :p
>>>>>>>>> 
>>>>>>>>> 
>>>>>>>>>> On 2016-01-11, at 14:16:01, Craig Cruden <ccruden at novafore.com> wrote:
>>>>>>>>>> 
>>>>>>>>>> I just realized “cases” probably is not needed - if it see’s a comma after case but before “:” then it is the concise form.  
>>>>>>>>>> 
>>>>>>>>>> If the switch / case can do that , the partial function case should be able to do the same thing.
>>>>>>>>>> 
>>>>>>>>>> 
>>>>>>>>>>> On 2016-01-11, at 13:23:19, Craig Cruden <ccruden at novafore.com> wrote:
>>>>>>>>>>> 
>>>>>>>>>>> I have thought about it a bit more and I think this would cover all the cases that interest me (in addition to others needs for a little more conciseness on the most simple case).  
>>>>>>>>>>> 
>>>>>>>>>>> I also think we need to be clear that the “case” (or cases) and “default” are is really just a partial function which in it’s entirety is really just a complete function for used wherever a complete function (exhaustive) can be passed (e.g. reduce, filter, etc.) - otherwise they might get confused on why we are adding it to “map”.  
>>>>>>>>>>> 
>>>>>>>>>>> The optional where clause should also be part of the case clause as part of the proposal.  
>>>>>>>>>>> 
>>>>>>>>>>> There would be no need for statement based “fallthrough”.
>>>>>>>>>>> 
>>>>>>>>>>> You mentioned your proposal….  have you drafted a formal proposal draft?
>>>>>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>>> 
>>>>>>>>>>>> On 2016-01-10, at 12:41:03, Paul Ossenbruggen via swift-evolution <swift-evolution at swift.org> wrote:
>>>>>>>>>>>> 
>>>>>>>>>>>> I agree that it would be really useful to keep things concise. I am going to suggest again an idea I had in the past, it is also in my proposal, which might work well for this problem. This might address the verbosity of the “case” and at the same time make it obvious we are dealing with a switch expression. So both would be valid: 
>>>>>>>>>>>> 
>>>>>>>>>>>> 	let num = color.map {
>>>>>>>>>>>> 		cases   .Red: 100, 
>>>>>>>>>>>> 			     .Green:  200, 
>>>>>>>>>>>> 			     .Blue: 300
>>>>>>>>>>>> 		default: -1 
>>>>>>>>>>>> 	}
>>>>>>>>>>>> 	let num = color.map {
>>>>>>>>>>>> 		case     .Red: 100
>>>>>>>>>>>> 		case     .Green:  200 
>>>>>>>>>>>> 		case     .Blue: 300
>>>>>>>>>>>> 		default: -1 
>>>>>>>>>>>> 	}
>>>> 
>>>> _______________________________________________
>>>> 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/20160118/2c6408f6/attachment.html>


More information about the swift-evolution mailing list