[swift-evolution] [Pitch] Retiring `where` from for-in loops

Xiaodi Wu xiaodi.wu at gmail.com
Mon Jun 13 17:32:30 CDT 2016


On Mon, Jun 13, 2016 at 4:36 PM, let var go <letvargo at gmail.com> wrote:

>
>
> On Mon, Jun 13, 2016 at 12:21 PM Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>
>> On Mon, Jun 13, 2016 at 12:20 PM, let var go <letvargo at gmail.com> wrote:
>>
>>>
>>>
>>> On Mon, Jun 13, 2016 at 9:46 AM Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>>>
>>>> On Mon, Jun 13, 2016 at 11:41 AM, let var go <letvargo at gmail.com>
>>>> wrote:
>>>>
>>>>>
>>>>>
>>>>> On Mon, Jun 13, 2016 at 9:04 AM Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>>>>>
>>>>>> Moreover, I should add, if your goal is to eliminate the possibility
>>>>>> of continuing and breaking from inside the loop, `.forEach()` does that
>>>>>> exactly, so your argument would be for the elimination of `for..in`
>>>>>> altogether.
>>>>>>
>>>>>
>>>>> I have no "goal" of eliminating the possibility of continuing or
>>>>> breaking from inside the loop. In general, it is not my goal to try and
>>>>> control how other people code their programs at all. I don't want to tell
>>>>> you that you can't 'continue' if you want to 'continue.'
>>>>>
>>>>> *I am not trying to make everyone adopt my own personal coding style
>>>>> and/or philosophy.*
>>>>>
>>>>
>>>> We're not discussing style.
>>>>
>>>
>>> Yes, we are discussing style, and for a very simple reason: Style is
>>> essential to readability and clarity.
>>>
>>> When we talk about for...in...where vs. guard...continue, all we are
>>> talking about is style. In terms of functionality, they do exactly the same
>>> thing. In terms of style, however, *one is easier to read than the
>>> other. *
>>>
>>> Some people think that guard...continue is easier to read and
>>> understand. Others, like me, think that for...in...where is easier to read
>>> and understand. *But that is a disagreement over style, not
>>> functionality*.
>>>
>>> And here is the difficult thing about debates like this: Both sides are
>>> right. What I consider to be the clearest, most readable style of coding
>>> may be confusing to someone else, and vice versa. Different people find
>>> different styles confusing. Not everyone learns the same way. Not everyone
>>> reads the same way. Not everyone codes the same way. What is hard for me to
>>> understand may be easy for you to understand.
>>>
>>> So if using 'continue' inside your for...in loops makes sense to you,
>>> and it helps you understand your own code, then go for it. It's not my
>>> style, not because it is "unfashionable", but because it has the opposite
>>> effect on me - it makes the code harder for me to understand.
>>>
>>
>> You misunderstand me. I am not supporting this proposal because I think
>> `guard` is superior style. I am supporting it because I have come to the
>> conclusion that `where` is harmful. I do happen to think that `guard` is a
>> superior style, but that's not the motivation for removing `where`, nor
>> could it be a justification.
>>
>
> No, I didn't misunderstand you. You are talking about style, even if you
> don't realize it. Examine these two pieces of code:
>
> Example 1:
> for x in xs where x < 10 {
>     print(x)
> }
>
> Example 2:
> for x in xs {
>     guard x < 10 else { continue }
>     print(x)
> }
>
> Example 1 and Example 2 are functionally equivalent. They do exactly the
> same thing. They will produce exactly the same output. *They only differ
> with regard to style.*
>
> You think that Example 2 is a better style than Example 1 because you
> think that Example 1 is confusing to new programmers. You argue that the
> confusion is harmful.
>

If you define 'style' as the difference between any two things that produce
the same output, then indeed all language design is 'style.' Writing in
Lisp vs. writing in C++ would be a choice of 'style.' When you say that
Swift should accommodate your own 'style,' then, that could just as well be
an argument for Lisp-like syntax. This is not, however, what people
generally understand to be 'coding style.'

The fact is that there are even experienced users of Swift who see `where`
and affirmatively believe it does what it does not do. The same cannot be
said for `guard`. That is, a user might say, 'What in the world does guard
mean?', but even a totally new user is unlikely to say, 'I can guess what
guard means, and it means [something that guard does not in fact mean].'
That is not at all an argument about style. And yes, I argue that confusion
is harmful.

I think that Example 1 is a better style than Example 2 because I think
> that it is easier to read and expresses my intent with greater clarity.
> Whatever cognitive burden is placed on the new programmer to learn about
> the 'where' clause is extremely modest and more than made up for by the
> ability to express their intentions in a way that is both concise and
> readable. Example 2, by contrast, looks cluttered and splits the
> control-flow logic into two parts creating a cognitive burden that I
> consider harmful.
>

You are stretching here; `guard` imposes a 'harmful cognitive burden'?
Again, if you truly believe that, please do propose a change to the list.

These are debates about style, and that is okay, because style is about
> clarity, readability, and expressiveness, all of which are essential goals. *Style
> is substance*. Half the battle is getting the computer to follow the
> correct instructions. The other half is making the code readable so that
> human beings can understand it - and that is a matter of style.
>
> There are times where I will choose to use a 'continue' statement inside a
> for...in loop. The reason hardly ever has anything to do with functionality
> - I could design the code differently to avoid that particular code smell
> if I put my mind to it. No, I would choose the 'continue' statement because
> in that particular context it makes my code more accessible to human beings
> (including myself, later on). The ability to choose one solution over
> another for purely stylistic reasons means that I can maximize both the
> functionality and the readability of my code.
>
> This proposal prevents the programmer from writing the best possible code
> because it disallows a stylistic choice that improves readability. I don't
> like that. It means that I have to write code that is worse than it has to
> be. It means that I have to write code that is uglier and more disjointed
> than it needs to be. That doesn't make any sense at all.
>
>
>>
>>
>>> You made a very strong claim: use of `guard...continue` leads to
>>>> 'smelly' code, or in other words bad code. In other words, you claim that
>>>> `guard...continue` is harmful. That is grounds for removal, and if you
>>>> believe it to be true, I encourage you to propose it to the list and get
>>>> feedback on that opinion.
>>>>
>>>> If you're saying that you simply don't prefer it for reasons of
>>>> 'style,' again I emphasize that the topic at hand here is not about
>>>> personal coding style. The claim we are making is that `where` is harmful.
>>>> I too like it for style, and I'll be sad to see it go. But I have concluded
>>>> that it must go.
>>>>
>>>>
>>>>> There is also a big difference between 'break' and 'continue'. I am
>>>>> not afraid to use 'break', and I don't consider it a code smell. It allows
>>>>> for early exit from a loop based on conditions that are not always known at
>>>>> the time the loop is entered. for...in loops are necessary precisely
>>>>> because they allow for the early exit.
>>>>>
>>>>> You don't need for...in if you want to continue - you can use forEach
>>>>> for that. Instead of using 'continue', you just use 'return' without doing
>>>>> anything and it moves on to the next iteration. So really, the only purpose
>>>>> that for...in serves that is not served by forEach is early exit. But
>>>>> regardless, *even if for...in served no additional purpose that
>>>>> couldn't be served by forEach, I would keep it in the language because
>>>>> there are situations where I believe it is easier to read, and
>>>>> expressiveness and clarity are important to me.*
>>>>>
>>>>>
>>>>>>
>>>>>> On Mon, Jun 13, 2016 at 10:55 Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>>>>>>
>>>>>>> On Mon, Jun 13, 2016 at 10:44 AM, let var go <letvargo at gmail.com>
>>>>>>> wrote:
>>>>>>>
>>>>>>>> I think we must be reading different discussions.
>>>>>>>>
>>>>>>>> What I have seen in this discussion is the following:
>>>>>>>>
>>>>>>>> a) The need to filter a for-in loop doesn't arise that often; but,
>>>>>>>> b) When it does arise, everyone who has chimed in on this thread
>>>>>>>> (except the two people who are proposing the change) thinks that the
>>>>>>>> "where" clause is the clearest, most expressive way to do it.
>>>>>>>>
>>>>>>>> Something that would help me get on board with this change is more
>>>>>>>> evidence about what kind of problems it is actually creating.
>>>>>>>>
>>>>>>>> As best I can tell, this proposal got started because "somewhere"
>>>>>>>> some new programmers (no one knows how many) expressed some confusion (no
>>>>>>>> one knows how seriously they were confused, or how long it took them to
>>>>>>>> figure it out) about how the where clause worked in a for-in loop. For all
>>>>>>>> we know, once they learned the way it works, they may have said, "Hey
>>>>>>>> that's cool! I'm gonna use that from now on!"
>>>>>>>>
>>>>>>>> In other words, you seem to be talking about removing a feature
>>>>>>>> that is liked by *a lot* people, based on some unsubstantiated reports of
>>>>>>>> user error that may or may not have been totally unsubstantial.
>>>>>>>>
>>>>>>>> I don't want new programmers to be confused, either, but the
>>>>>>>> "where" clause is such a basic programming construct - the keyword is new,
>>>>>>>> but the idea itself is as old as programming - that I don't mind expecting
>>>>>>>> new programmers to learn how to use it. The learning curve should be
>>>>>>>> incredibly short - it is nothing more than a filter operation.
>>>>>>>>
>>>>>>>> There's something else here that is really important to me, though
>>>>>>>> I don't know how others feel about it.
>>>>>>>>
>>>>>>>> Using the guard...continue approach that you are promoting is a
>>>>>>>> code smell. It puts control-flow logic inside the for-in loop. That is
>>>>>>>> something I have always tried to avoid. I know that the language allows for
>>>>>>>> it, but I believe it is bad programming practice. In fact, if you get rid
>>>>>>>> of the `where` keyword, I'm still not going to use guard...continue. I'll
>>>>>>>> just filter the collection first and then loop it.
>>>>>>>>
>>>>>>>
>>>>>>> This is quite the statement. It sounds like you'd be for the
>>>>>>> elimination of `continue`?
>>>>>>>
>>>>>>>
>>>>>>>>
>>>>>>>> It is a code smell for the same reason that messing with the index
>>>>>>>> inside a for;; loop was a code smell. I was always taught never to do this:
>>>>>>>>
>>>>>>>> for var i = 0; i < array.count, i++ {
>>>>>>>>   if iWantThisToLoopAnExtraTime {
>>>>>>>>     i--
>>>>>>>>   }
>>>>>>>> }
>>>>>>>>
>>>>>>>> Why? Because code like that is confusing. It becomes difficult to
>>>>>>>> know how many times the loop will execute, what the looping logic is, etc.
>>>>>>>> Sure, I might get away with it most of the time, but it is bad practice and
>>>>>>>> there is always a better way to do what you want to do. The only thing that
>>>>>>>> keeps you from the better way is laziness.
>>>>>>>>
>>>>>>>> The same is true (albeit to a lesser degree) for the
>>>>>>>> guard...continue. It may not be as extreme, but it is still a code smell.
>>>>>>>> It divides the control-flow logic into two parts - one outside the loop,
>>>>>>>> and one inside the loop, and it suddenly becomes twice as easy to miss
>>>>>>>> something.
>>>>>>>>
>>>>>>>> Using for-in-where, all of the control-flow logic is on one single
>>>>>>>> line, and once it is known that "where" operates as a filter operation, it
>>>>>>>> all works together in a single, harmonious statement that declares exactly
>>>>>>>> what is going to happen in a way that is totally unambiguous.
>>>>>>>>
>>>>>>>> So by getting rid of the "where" clause, I believe that you are
>>>>>>>> actually encouraging bad programming practice. Instead of encouraging the
>>>>>>>> new user to learn this very simple construct that will ultimately make
>>>>>>>> their code safer and more expressive without dividing their control-flow
>>>>>>>> logic unnecessarily into two separate parts, you are encouraging them to
>>>>>>>> just "do what they know". I think that is terrible, and you are doing them
>>>>>>>> a disservice.
>>>>>>>>
>>>>>>>> And from a personal standpoint, you are telling me that I have to
>>>>>>>> write smelly code, even though there is this perfectly good non-smelly
>>>>>>>> option sitting right there, because you don't want someone else to have to
>>>>>>>> learn something.
>>>>>>>>
>>>>>>>> On Mon, Jun 13, 2016 at 5:29 AM Xiaodi Wu <xiaodi.wu at gmail.com>
>>>>>>>> wrote:
>>>>>>>>
>>>>>>>>> I think this discussion has made it pretty plain that what is
>>>>>>>>> claimed to be 'so useful' is barely ever used. Moreover, it provides no
>>>>>>>>> independent uses. The point of these pitches is to sound out arguments,
>>>>>>>>> not, as far as I was aware, to take a vote.
>>>>>>>>>
>>>>>>>>> On Mon, Jun 13, 2016 at 1:54 AM Jose Cheyo Jimenez <
>>>>>>>>> cheyo at masters3d.com> wrote:
>>>>>>>>>
>>>>>>>>>> --1
>>>>>>>>>>
>>>>>>>>>> I think it would be a waste of the community's time to do a
>>>>>>>>>> formal review when only two people are in favor of this removal.
>>>>>>>>>>
>>>>>>>>>> 'for in where' is so useful especially since we don't have for;;;
>>>>>>>>>> loops anymore. I'd say leave this alone; the majority doesn't want this
>>>>>>>>>> changed.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On Jun 10, 2016, at 10:17 AM, Xiaodi Wu via swift-evolution <
>>>>>>>>>> swift-evolution at swift.org> wrote:
>>>>>>>>>>
>>>>>>>>>> I think this idea--if you don't like it, then you don't have to
>>>>>>>>>> use it--is indicative of a key worry here: it's inessential to the language
>>>>>>>>>> and promotes dialects wherein certain people use it and others wherein they
>>>>>>>>>> don't. This is an anti-goal.
>>>>>>>>>>
>>>>>>>>>> On Fri, Jun 10, 2016 at 12:10 let var go <letvargo at gmail.com>
>>>>>>>>>> wrote:
>>>>>>>>>>
>>>>>>>>>> Leave it in!
>>>>>>>>>>>
>>>>>>>>>>> It's a great little tool. I don't use it very often, but when I
>>>>>>>>>>> do it is because I've decided that in the context of that piece of code it
>>>>>>>>>>> does exactly what I want it to do with the maximum amount of clarity.
>>>>>>>>>>>
>>>>>>>>>>> If you don't like it, then don't use it, but I can't see how it
>>>>>>>>>>> detracts from the language at all.
>>>>>>>>>>>
>>>>>>>>>>> The *only* argument that I have heard for removing it is that
>>>>>>>>>>> some people don't immediately intuit how to use it. I didn't have any
>>>>>>>>>>> trouble with it at all. It follows one of the most basic programming
>>>>>>>>>>> patterns ever: "For all x in X, if predicate P is true, do something." The
>>>>>>>>>>> use of the keyword "where" makes perfect sense in that context, and when I
>>>>>>>>>>> read it out loud, it sounds natural: "For all x in X where P, do
>>>>>>>>>>> something." That is an elegant, succinct, and clear way of stating exactly
>>>>>>>>>>> what I want my program to do.
>>>>>>>>>>>
>>>>>>>>>>> I don't doubt that it has caused some confusion for some people,
>>>>>>>>>>> but I'm not sold that that is a good enough reason to get rid of it. It
>>>>>>>>>>> seems strange to get rid of a tool because not everyone understands how to
>>>>>>>>>>> use it immediately, without ever having to ask a single question. As long
>>>>>>>>>>> as its not a dangerous tool (and it isn't), then keep it in the workshop
>>>>>>>>>>> for those times when it comes in handy. And even if there is some initial
>>>>>>>>>>> confusion, it doesn't sound like it lasted that long. It's more like, "Does
>>>>>>>>>>> this work like X, or does this work like Y? Let's see...oh, it works like
>>>>>>>>>>> X. Ok." That's the entire learning curve...about 5 seconds of curiosity
>>>>>>>>>>> followed by the blissful feeling of resolution.
>>>>>>>>>>>
>>>>>>>>>>> On Fri, Jun 10, 2016 at 9:32 AM Xiaodi Wu via swift-evolution <
>>>>>>>>>>> swift-evolution at swift.org> wrote:
>>>>>>>>>>>
>>>>>>>>>> On Fri, Jun 10, 2016 at 11:23 AM, Sean Heber via swift-evolution
>>>>>>>>>>>> <swift-evolution at swift.org> wrote:
>>>>>>>>>>>>
>>>>>>>>>>> > And to follow-up to myself once again, I went to my "Cool 3rd
>>>>>>>>>>>>> Party Swift Repos" folder and did the same search. Among the 15 repos in
>>>>>>>>>>>>> that folder, a joint search returned about 650 hits on for-in (again with
>>>>>>>>>>>>> some false positives) and not a single for-in-while use.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Weird. My own Swift projects (not on Github :P) use “where”
>>>>>>>>>>>>> all the time with for loops. I really like it and think it reads *and*
>>>>>>>>>>>>> writes far better as well as makes for nicer one-liners. In one project, by
>>>>>>>>>>>>> rough count, I have about 20 that use “where” vs. 40 in that same project
>>>>>>>>>>>>> not using “where”.
>>>>>>>>>>>>>
>>>>>>>>>>>>> In another smaller test project, there are only 10 for loops,
>>>>>>>>>>>>> but even so one still managed to use where.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Not a lot of data without looking at even more projects, I
>>>>>>>>>>>>> admit, but this seems to suggest that the usage of “where” is going to be
>>>>>>>>>>>>> very developer-dependent. Perhaps there’s some factor of prior background
>>>>>>>>>>>>> at work here? (I’ve done a lot of SQL in another life, for example.)
>>>>>>>>>>>>>
>>>>>>>>>>>> That is worrying if true, because it suggests that it's
>>>>>>>>>>>> enabling 'dialects' of Swift, an explicit anti-goal of the language.
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>>> I feel like “where” is a more declarative construct and that
>>>>>>>>>>>>> we should be encouraging that way of thinking in general. When using it, it
>>>>>>>>>>>>> feels like “magic” for some reason - even though there’s nothing special
>>>>>>>>>>>>> about it. It feels like I’ve made the language work *for me* a little bit
>>>>>>>>>>>>> rather than me having to contort my solution to the will of the language.
>>>>>>>>>>>>> This may be highly subjective.
>>>>>>>>>>>>>
>>>>>>>>>>>>> l8r
>>>>>>>>>>>>> Sean
>>>>>>>>>>>>>
>>>>>>>>>>>> _______________________________________________
>>>>>>>>>>>>> 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/20160613/1f2c2410/attachment.html>


More information about the swift-evolution mailing list