2

I would like to know other people's opinion on the following style of writing a for loop:

for (int rep = numberOfReps; rep --> 0 ;) {
   // do something that you simply want to repeat numberOfReps times
}

The reason why I invented this style is to distinguish it from the more general case of for loops. I only use this when I need to simply repeat something numberOfReps times and the body of the loop does not use the values of rep and numberofReps in any way.

As far as I know, standard Java for example doesn't have a simple way of saying "just repeat this N times", and that's why I came up with this. I'd even go as far as saying that the body of the loop must not continue or break, unless explicitly documented at the top of the for loop, because as I said the whole purpose is to make the code easier to understand by coming up with a distinct style to express simple repetitions.

The idea is that if what you're doing is not simple (dependency on value of an inreasing/decreasing index, breaks, continues, etc), then use the standard for loop. If what you are doing is simple repetition, on the other hand, then this distinct style communicates that "fact" (once you know the purpose of the style, of course).

I said "fact" because the style can be abused, of course. I'm operating under the assumption that you have competent programmers whose objective is to make their code easier to understand, not harder.


A comment was made that allude to the principle that for should only be used for simple iteration, and while should be used otherwise (e.g. if the loop variables are modified in the body).

If that's the case, then I'm merely extending that principle to say that if it's even simpler than your simple for loops (i.e. you don't even care about the iteration index, or whether it's increasing or decreasing, etc, you just want to repeat doing something N times), then use the winking arrow for loop construct instead.


What a coincidence, Josh Bloch just tweeted the following:

  Goes-to Considered Harmful:

  public static void main(String[] a) {
    int i = 10;
    while (i --> 0) /* i goes-to 0 */ {
      System.out.println(i);
    }
  }

Unfortunately no explanation was given, but it seems that at least this pseudo operator has a name. It has also been discussed before on SO: What is the name of this operator: “-->”?

Community
  • 1
  • 1
polygenelubricants
  • 376,812
  • 128
  • 561
  • 623

2 Answers2

6

You have the language-agnostic tag, but this question isn't really language agnostic. That pattern would be fine if there wasn't already a well established idiom for doing something n times in your language.

You go on to mention Java, whicha already has a well-established idiom for doing something n times:

for (int i = 0; i < numberOfReps; i++) {
   // do something that you simply want to repeat numberOfReps times
}

While your pattern works just as well, it's confusing to others. When I first saw it my thoughts were:

  1. What's that weird arrow?
  2. Why is that line winking at me?

Unless you develop a pattern that has a significant advantage over the standard idiom, it's best to stick with the standard so your fellow coders don't end up scratching their heads.

Laurence Gonsalves
  • 137,896
  • 35
  • 246
  • 299
  • The thing with the standard for loop is that it's NOT just doing something N times. You can `break`, you can `contine`, you can modify `i` and `numberOfReps` in the body, etc. The for loop construct is very powerful, and simple repetition doesn't need all that power, and that's why I distinguish it with the arrow and the winking. – polygenelubricants Feb 24 '10 at 02:13
  • 4
    Yeah, but you can do all of those things with your pointing winking construct as well. If the problem is with `continue` and `break`, then have a convention that discourages their use. Also, it seems like common sense that messing around with the loop limit and counter would be a bad idea. Personally, I rarely use `continue`, and tend to use a `while` loop rather than a `for` loop if I need to use `break`. Likewise, if I need to manipulate the loop limit or counter I'll tend to use a `while` loop. – Laurence Gonsalves Feb 24 '10 at 02:27
  • Hopefully I'm summarizing you correctly, but is it fair to say that you're saying that "use `for` only if it's simple enough, otherwise use `while`"? If that's the case, then I'm just extending that by saying "and if it's even simpler than that, use the winking arrow `for`". – polygenelubricants Feb 24 '10 at 03:00
  • 1
    He also made the point that there's nothing keeping someone from using your loop the same way that they would use a standard `for` loop. It would simply be a coding convention, but one that no one would know about until you told it to them. You could achieve the same thing by adding a comment before the loop stating `// Don't break, continue, or use the value of rep in this loop`. It would be more wordy, but would also be clear to anyone who hadn't read your style guide. Of course, it still wouldn't stop someone from `break` -ing, `continue` -ing, or using `rep` in the loop. – Josh Townzen Feb 24 '10 at 04:13
  • Yes, unless I have a static checker or something like it, this is strictly a coding convention that needs self-enforcing to work. Thus the question is: is it a convention worthy of adopting? – polygenelubricants Feb 24 '10 at 04:38
  • 1
    @polygenelubricants the problem with the winking arrow convention is that no one has ever seen it, and it almost seems designed to obfuscate what's actually going on. Saying "don't write confusing for loops" is a much easier convention to follow, and seems to come automatically to most (good) programmers anyway. – Laurence Gonsalves Feb 24 '10 at 06:20
2

Nearly every language these days has lambda, so you can write a function like

nTimes(n, body)

that takes an int and a lambda, and more directly communicate intent. In F#, for example

let nTimes(n,f) =
    for i in 1..n do f()

nTimes(3, fun() -> printfn "Hello")    

or if you prefer extension methods

type System.Int32 with
    member this.Times(f) =        
        for i in 1..this do f()

(3).Times(fun() -> printfn "Hello")    
Brian
  • 117,631
  • 17
  • 236
  • 300
  • Standard Java doesn't have such feature. I'm aware that there have been attempts to bring functional style of programming to Java that probably would allow something like this, though. – polygenelubricants Feb 24 '10 at 01:19
  • 1
    A language without lambda is like a day without sunshine. (Which is like night.) – Brian Feb 24 '10 at 01:20
  • That's like saying European languages is "like a day without sunshine" for not having grammatical clusivity (http://en.wikipedia.org/wiki/Clusivity). Obviously if the language contains the features to express what I wanted, I would have used it. The point is that languages like Java doesn't, and that's why I came up with this. – polygenelubricants Feb 24 '10 at 01:42
  • 1
    You tagged the question "language-agnostic", so I provided the most language-agnostic answer I could think of. :) A variant of this answer works for F#, C#, VB, Perl, Python, Ruby, Javacsript, Scala, Closure, Lisp, Scheme, Smalltalk, Haskell, OCaml, and even now C++(1x), and most other popular languages. Maybe re-tag the question with 'Java' and 'C'. – Brian Feb 24 '10 at 01:54