3

A while loop can be written as follows in C# (and many other languages):

int someValue;
int someTerminatingValue;

while ((someValue = GetSomeValue()) != someTerminatingValue)
{
    // Do something interesting
}

Is there a name for this pattern of assigning the value inside the while loop's expression?

NB I'm not asking if it is a good idea or a bad idea, just if there's a name for this pattern. Whether it's good or bad, people will see it so they need to know what it is. If there isn't a name for it then that's fine, I'm just asking if there is one.

BanksySan
  • 714
  • 2
  • 6
  • 15
  • 5
    It is not a pattern, it is a consequence of evaluating an assignment expression with the value being assigned (instead of, say, void). – SJuan76 Jul 12 '15 at 17:34
  • 3
    I guess some would argue this is an anti-pattern, because it violates the command-query separation principle and makes the code intention a bit less clear, not to mention the "one-liner" assignment/test makes it a bit harder to spot an error in case of debugging. – heltonbiker Jul 12 '15 at 18:00
  • 1
    You might want to take a look: http://stackoverflow.com/q/2576571/401828 – heltonbiker Jul 12 '15 at 18:04
  • @heltonbiker I agree that it can make things harder to read, but there are some common 'well known' situations that it's used. The code is just to show some junior devs what it is if they do come across it. I just wanted to be able to call it the right thing. – BanksySan Jul 12 '15 at 18:13
  • 1
    @SJuan76 It's definitely a pattern, even if it doesn't have a name or is in any books purely because it is repeated in many code bases. If it repeats then it's a pattern. I'm not implying that it is a *good* pattern, just that it is a pattern. – BanksySan Jul 12 '15 at 18:15
  • I agree this is a somewhat commont practice, and it might have its use, and calling it by _name_ is for this very reason yet more important. But I believe it is not a "pattern" in the sense of a design pattern (these must be very formally defined, for what I know). Perhaps a better way to call it is an _idiom_, because it's very _idiomatic_ of C-based languages (so as they call something "pythonic" when it is idiomatic in python, and some constructs are idiomatic in C#/Linq, or in functional languages, etc.) https://en.wikipedia.org/wiki/Programming_idiom – heltonbiker Jul 12 '15 at 18:38
  • Thanks @heltonbiker, at last a useful comment regarding the question rather than what is good coding practice. *Idiom* is a good name. It's not a 'Design Pattern' (capitalised), it is something I've seen many times; e.g. when reading a file line by line. – BanksySan Jul 12 '15 at 18:44
  • @heltonbiker: Certainly not an anti-pattern, nor making things less clear. It's simply good idiomatic code, and clearer than any alternative could be. – Deduplicator Jul 12 '15 at 18:52
  • 2
    In the years I've been writing code, I haven't really bumped into this approach, and frankly I'm pleased with that- I would quickly change this if I saw it. This is frankly far too dangerous, without benefit (saves a single line of code..), and more importantly breaks the fluent reading of the code. `while (condition)` is simply more clear in it's intent than what you have there. Just don't do it, and your question becomes moot. No it doesn't have a name, for it is not common, and there's good reason. – Jimmy Hoffa Jul 12 '15 at 22:45
  • Well this pattern is very common in simulation application. Where threads get to some results that require the intoduction of new inputs in the simulation engine that will need to start using them on it's next pass or phase. But i never heard a name for this pattern. It also depend on who wrote it because there is other way to do it, here id say it's written like the above 80-85% of the time. – Franck Jul 13 '15 at 11:52
  • The TryParse pattern might be slightly related to this. It is a .Net idiom where you return a boolean with true when something executes fine, and false if some internal (and expected) exception happened: http://stackoverflow.com/a/17207748/401828 – heltonbiker Jul 16 '15 at 14:44

2 Answers2

5

There is no name for this specific idiom.

And it's a good idea™ to write idiomatic code, instead of trying to dumb it down further or writing code which is too clever by half.

Especially if any alternatives are long-winded, tedious, repetitive or otherwise bad.

Deduplicator
  • 8,591
  • 5
  • 31
  • 50
  • I think this code is idiomatic in C, but in C# I'd rather use an enumerator instead of a function that either returns a value or a special terminator. – CodesInChaos Jul 13 '15 at 08:14
  • @CodesInChaos: See [`System.Console.Read`](https://msdn.microsoft.com/en-us/library/system.console.read(v=vs.110).aspx) – Deduplicator Jul 13 '15 at 11:32
  • I know that a few APIs following this pattern exist in C#, but usually `foreach` together with an enumerable is the cleaner choice. It's certainly rare enough to not count as a C# idiom. – CodesInChaos Jul 13 '15 at 11:45
2

Idiom

At this scale, reoccurring motifs are called idioms rather than design patterns. The design patterns work on a larger scale than just a single line of code or a single loop.

Clever code

This would also qualify as clever code anti-pattern. Clever code is not advisable, because it will be harder to read for your teammates and for yourself 6 moths later.

Better alternatives

Loop initialization, loop "propulsion", loop exit conditions are separated.

    int someValue;
    int someTerminatingValue;

    for (someValue = GetSomeValue();         // initialize the loop variable
         someValue = GetSomeValue();         // move the loop onward
         someValue != someTerminatingValue)  // exit condition
    {
        // Do something interesting
    }

But this is still clever code. McConnell call this "a while loop abusively crammed into a for loop header" (see Code Complete 2, p.374). he also proposes a better alternative.

    someValue = GetSomeValue();                 // initialize the loop variable
    while (someValue != someTerminatingValue)   // exit condition
    {
        // Do something interesting
        someValue = GetSomeValue();             // move the loop onward
    }

Related:

enter image description here (source)

Nick Alexeev
  • 2,484
  • 2
  • 17
  • 24
  • 1
    Actually, it's idiomatic good code, thus certainly not an anti-pattern nor too clever for it's own good. – Deduplicator Jul 12 '15 at 18:50
  • @Deduplicator This answer gives some reasons to support its point, but your comment doesn't. Why is is to be considered good code instead of the clever anti-pattern? – heltonbiker Jul 12 '15 at 18:52
  • 1
    This does not answer the question as asked. –  Jul 12 '15 at 18:54
  • @heltonbiker: Actually, it asserts without any support that it's "too clever". But what would be an equally idiomatic alternative? Being idiomatic makes it far better understood, increasing clarity. – Deduplicator Jul 12 '15 at 18:55
  • @Deduplicator You also commented that the O.P.'s idiom is "clearer than *any* alternative could be [emphasis mine, N.A.] ." It would be good to see some support for that. For once, I can think of two ways to set up this kind of loop in a clearer and more maintainable way. – Nick Alexeev Jul 12 '15 at 18:56
  • It depends on the context, it can be much easier to read if the variables and methods are names correctly. If you're comparing two dynamic quantities then it might be awful. Either way, if peeps know the *pattern* then it is at least one less "WFT?" than if they don't. – BanksySan Jul 12 '15 at 18:56
  • @Nick: Well, what do we have? The infinite loop with a conditional break at the start, or duplicating the call to GetSomeValue before the loop and re-setting it at the end, which duplicates code. Do you have a better one? – Deduplicator Jul 12 '15 at 18:59
  • @NickAlexeev That first option is terrible, really, please don't ever write that code (it's not idiomatic in my experience) . The second option will have to go to a vote, I quite like the *idiom* in the question in the correct context. It's an easily recognisable, repeatable structure. – BanksySan Jul 12 '15 at 22:08
  • @BanksySan That's what I said, isn't it. But even my first version is two or three WTFs better that your one-liner. That was my point. – Nick Alexeev Jul 12 '15 at 22:13
  • 2
    Having seen your update by chance, I already discounted your second example. And the first is not better in any but one way: The duplicated code is in consecutive lines, so it's more obvious when the copies get out-of-sync. It buys that one advantage over your other terrible example by abusing the for-loop though, so it ain't any better. – Deduplicator Jul 12 '15 at 22:21
  • I disagree with avoiding idioms and I dislike the last alternative code example you give: you assign the output of a function to the same variable TWICE, that's code duplication. If a line of code is tedious, it should be compressed into the line that makes use of it wherever possible, imo. I don't like reading ten lines that ultimately do only one thing. I don't like people that put function output into a temp variable and use that temp variable as an argument in another call two lines down, without further use. That makes it verbose and distracts me from the bigger picture. – klaar Apr 18 '16 at 07:32