> On Sep 4, 2017, at 4:05 PM, Christopher Kornher via swift-evolution 
> <[email protected]> wrote:
> 
> Apologies for rehashing this, but we seem to be going down that path… I am in 
> the minority on this issue and have held my opinions because I thought that 
> they would have served as simply a distraction and I was extremely busy at 
> the time. That may have been a mistake on my part, because raising these 
> issues now is after the fact.
> 
> I am airing them now for two reasons:
> 1) To ensure that at least the agreed upon compromise is implemented.
> 2) To hopefully improve the evolution process, and help ensure that similar 
> proposals are given the scrutiny that they deserve.
> 
> I have noticed a pattern in software and other projects over the years. The 
> most catastrophic failures and expensive rework has been due to flawed or at 
> least incomplete basic assumptions. New postulates / basic assumptions should 
> be subjected to rigorous scrutiny. I don’t think that they were in this case.
> 
> I am speaking up now because there is a proposal out there to follow what I 
> consider to be a flawed basic assumption to its logical conclusion, which 
> seems quite reasonable, if you accept the basic assumption, which I don’t, of 
> course. 
> 
> Please don’t take this as a personal attack on those on the other side. This 
> is a philosophical disagreement with no “right” and “wrong” answer. I don’t 
> believe that this proposal is terrible. In fact, the agreed-upon compromise 
> does improve the construction and matching of enum values and leaves only 
> edge cases that I hope to address in a future proposal — specifically 
> matching is made more difficult in some cases of name overloading. 
> 
> The history of the process as I saw it:
>       There was a widely perceived problem with enums involving what could be 
> described as “legacy destructuring” which could lead to confusing code and 
> hard to discover transposition errors.
> 
>       A solution was proposed that was based upon an overarching premise: 
> that enums should be modeled as much as possible after function calls to 
> simplify the language. This led to the original proposal always requiring 
> labels (as function calls do, and closures don’t, but that is a discussion 
> for another time).
> 
> I believe that idea of using function calls as the primary model for enums is 
> flawed at its core. The problem is that enums and function calls only 
> resemble each other in Swift because some enums can have associated values. 

If the idea of modeling them as a tag and a tuple were OK, this proposal would 
not exist in the first place - or would be dramatically reduced in scope to 
just redoing pattern matching.  We are remodeling them as function-like 
precisely because the old scheme was causing headaches.  I feel it is 
reductionistic to say it is "only the case” that this is true given these 
circumstances.

> 
> The purpose of enums is to be matched. Enums that are never matched in some 
> way have no purpose. Function calls must always be “matched” (resolved) 
> unambiguously so that proper code can be executed. No such requirement exists 
> for enums. In fact the language includes rich functionality for matching 
> multiple cases and values with a single “case” (predicate). This is not a 
> flaw, it improves the expressive power of the language by allowing complex 
> matching logic to be expressed tersely and clearly.
> 

What complex matching (did you mean Expressive?) logic?  That you can express 
pattern matches just by matching by base name then a tuple pattern of proper 
cardinality with disjointed labels is far more complex and prone to actual 
ambiguities (the rationale and proposal both use some form of the phase “when a 
pattern is unambiguous”).  What this means in practice is that the scheme laid 
out in the proposal is prone to ambiguity by construction.  This does not 
enable expressive pattern matches, this enables users to save typing while 
simultaneously increasing the mental overhead of reading any switch statement.  
Under this proposal it is now impossible to tell at a glance which pattern over 
an Enum with overloaded base names is being matched unless you have the labels 
present.

> So, since the purpose of enums is to be matched, any modification to this 
> accepted proposal that makes that more difficult or cluttered should be 
> rejected.

I agree with the sentiment that we don’t want to increase entropy, but I 
disagree with the logic underpinning it.  You save a few keystrokes with this 
mentality.  You don’t gain anything in return.

~Robert Widmann

> 
> 
>> On Sep 4, 2017, at 9:52 AM, T.J. Usiyan via swift-evolution 
>> <[email protected] <mailto:[email protected]>> wrote:
>> 
>> While re-litigating has it's issues, I am for simplifying the rule and 
>> always requiring the labels if they exist. This is similar to the change 
>> around external labels. Yes, it is slightly less convenient, but it removes 
>> a difficult to motivate caveat for beginners.
>> 
>> On Sun, Sep 3, 2017 at 4:35 PM, Xiaodi Wu via swift-evolution 
>> <[email protected] <mailto:[email protected]>> wrote:
>> The desired behavior was the major topic of controversy during review; I’m 
>> wary of revisiting this topic as we are essentially relitigating the 
>> proposal.
>> 
>> To start off, the premise, if I recall, going into review was that the 
>> author **rejected** the notion that pattern matching should mirror creation. 
>> I happen to agree with you on this point, but it was not the prevailing 
>> argument. Fortunately, we do not need to settle this to arrive at some 
>> clarity for the issues at hand.
>> 
>> From a practical standpoint, a requirement for labels in all cases would be 
>> much more source-breaking, whereas the proposal as it stands would allow 
>> currently omitted labels to continue being valid. Moreover, and I think this 
>> is a worthy consideration, one argument for permitting the omission of 
>> labels during pattern matching is to encourage API designers to use labels 
>> to clarify initialization without forcing its use by API consumers during 
>> every pattern matching operation.
>> 
>> In any case, the conclusion reached is precedented in the world of functions:
>> 
>> func g(a: Int, b: Int) { ... }
>> let f = g
>> f(1, 2)
>> 
>> On Sun, Sep 3, 2017 at 15:13 Robert Widmann via swift-evolution 
>> <[email protected] <mailto:[email protected]>> wrote:
>> Hello Swift Evolution,
>> 
>> I took up the cause of implementing SE-0155 
>> <https://github.com/apple/swift-evolution/blob/master/proposals/0155-normalize-enum-case-representation.md>,
>>  and am most of the way through the larger points of the proposal.  One 
>> thing struck me when I got to the part about normalizing the behavior of 
>> pattern matching 
>> <https://github.com/apple/swift-evolution/blob/master/proposals/0155-normalize-enum-case-representation.md#pattern-consistency>.
>>   The Core Team indicated in their rationale 
>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170417/035972.html>
>>  that the proposal’s suggestion that a variable binding sub in for a label 
>> was a little much as in this example:
>> 
>> enum Foo {
>>   case foo(x: Int, y: Int)
>> }
>> if case let .foo(x: x, y: y) {} // Fine!  Labels match and are in order
>> if case let .foo(x, y: y) {} // Bad!  Missing label 'x'
>> if case let .foo(x, y) {} // Fine?  Missing labels, but variable names match 
>> labels
>> 
>> They instead suggested the following behavior:
>> 
>> enum Foo {
>>   case foo(x: Int, y: Int)
>> }
>> if case let .foo(x: x, y: y) {} // Fine!  Labels match and are in order
>> if case let .foo(x, y: y) {} // Bad!  Missing label 'x'
>> if case let .foo(x, y) {} // Fine?  Missing labels, and full name of case is 
>> unambiguous
>> 
>> Which, for example, would reject this:
>> 
>> enum Foo {
>>   case foo(x: Int, y: Int) // Note: foo(x:y:)
>>   case foo(x: Int, z: Int) // Note: foo(x:z:)
>> }
>> if case let .foo(x, y) {} // Bad!  Are we matching foo(x:y:) or foo(x:z:)?
>> 
>> With this reasoning:
>> 
>>>  - While an associated-value label can indeed contribute to the readability 
>>> of the pattern, the programmer can also choose a meaningful name to bind to 
>>> the associated value.  This binding name can convey at least as much 
>>> information as a label would.
>>> 
>>>   - The risk of mis-labelling an associated value grows as the number of 
>>> associated values grows.  However, very few cases carry a large number of 
>>> associated values.  As the amount of information which the case should 
>>> carry grows, it becomes more and more interesting to encapsulate that 
>>> information in its own struct — among other reasons, to avoid the need to 
>>> revise every matching case-pattern in the program.  Furthermore, when a 
>>> case does carry a significant number of associated values, there is often a 
>>> positional conventional between them that lowers the risk of re-ordering: 
>>> for example, the conventional left-then-right ordering of a binary search 
>>> tree.  Therefore this risk is somewhat over-stated, and of course the 
>>> programmer should remain free to include labels for cases where they feel 
>>> the risk is significant.
>>> 
>>>   - It is likely that cases will continue to be predominantly distinguished 
>>> by their base name alone.  Methods are often distinguished by argument 
>>> labels because the base name identifies an entire class of operation with 
>>> many possible variants.  In contrast, each case of an enum is a kind of 
>>> data, and its name is conventionally more like the name of a property than 
>>> the name of a method, and thus likely to be unique among all the cases.  
>>> Even when cases are distinguished using only associated value labels, it 
>>> simply means that the corresponding case-patterns must include those 
>>> labels; we should not feel required to force that burden on all other 
>>> case-patterns purely to achieve consistency with this presumably-unusual 
>>> style.
>>> Accordingly, while it needs to be possible to include associated value 
>>> labels in a case-pattern, and in some situations it may be wise to include 
>>> them, the core team believes that requiring associated value labels would 
>>> be unduly onerous.
>> 
>> 
>> This sounds fine in principle, but I believe it is inconsistent with the 
>> goals of the proposal and doesn’t actually normalize much about the existing 
>> pattern matching process.  As it stands, labels may be omitted from patterns 
>> because Swift’s philosophy before this proposal is that associated values in 
>> enum cases were conceptually tuples.  With the addition of default 
>> arguments, the ability to overload case names with differing associated 
>> value labels, and making the labels part of the API name, there is no reason 
>> we should allow tuple-like behavior in just this one case.
>> 
>>> While an associated-value label...
>> 
>> While it is true that a user often has a domain-specific intention for 
>> variables created during the destructuring process, the labels do not 
>> distract from the original purpose of the API and the user is still free to 
>> provide whatever name they see fit.
>> 
>>> Therefore this risk is somewhat over-stated, and of course the programmer 
>>> should remain free to include labels for cases where they feel the risk is 
>>> significant...
>> 
>> This is phrased as a matter of choice, in practice this is perplexing.  
>> Recall an earlier rejected pattern:
>> 
>> enum Foo {
>>   case foo(x: Int, y: Int)
>> }
>> if case let .foo(x, y: y) {} // Bad!  Missing label ‘x'
>> 
>> From the user’s perspective, it is obvious what should happen: Either they 
>> did, or did not, intend to match labels.  From the compiler’s perspective 
>> this is a proper ambiguity.  Did the user intend to provide a “more 
>> meaningful name” and hence meant to elide the label, or did the user intend 
>> to match all the labels but forgot or deleted one?  It is not obvious why, 
>> if we’re making the distinction, we should assume one way or the other.   
>> This case only gets worse when we must diagnose intent if the case is also 
>> overloaded by base name.
>> 
>> I don’t see how it is "unduly onerous” to teach code completion to suggest 
>> the full name of an enum case everywhere or to create diagnostics that 
>> always insert missing labels in patterns to correct the user’s mistake.  
>> Freedom of choice is, in this case, only making a hard problem harder.
>> 
>>> It is likely that cases will continue to be predominantly distinguished by 
>>> their base name alone...
>> 
>> This makes sense given the current state of the world, but under this 
>> proposal we fully expect users to be overloading that base name and writing 
>> more and more ambiguous patterns.  We should encourage disambiguating these 
>> cases with labels as a matter of both principle and QoI.  
>> 
>> A pattern is meant to mirror the way a value was constructed with 
>> destructuring acting as a dual to creation.  By maintaining the structure of 
>> the value in the pattern, labels included, users can properly convey that 
>> they intend the label to be a real part of the API of an enum case with 
>> associated values instead of just an ancillary storage area.  Further, we 
>> can actually simplify pattern matching by making enum cases consistent with 
>> something function-like instead of tuple-like.
>> 
>> To that end, I'd like the rationale and the proposal to be amended to 
>> require labels in patterns in all cases.
>> 
>> Thoughts?
>> 
>> ~Robert Widmann
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> 
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to