Loop Variables

A subscriber to my Real Studio training videos sent me an email the other day asking me why I did something in the videos.  He was asking why I did this

for i as integer = 0 to ar.ubound

rather than

dim i as integer

for i = 0 to ar.ubound

I had no real answer except that it’s a little less typing and that the variable, i, can’t be used outside of the for next loop.

The subscriber went on to say that he tested both for speed and that there’s essentially no difference between the two versions.  That has been my experience too.

I initially was very against this ‘shorthand’ method.  It was introduced to me by my senior developer, Seth, and it just looked…odd.  I think at one point I might have even emailed him to ask him to stop doing it.  After a brief discussion he convinced me it didn’t matter to him but if I really wanted him to go back to the other method he could.

To make a long story short, I tried it out for a week and I discovered that I really prefer it to the other way and I’ve used it consistently ever since.  It’s a bit less typing.  I don’t know about you but I am essentially a lazy programmer so anything that means less typing is good for me.

The second reason is that when you declare the variable in the for next loop the variable is local only to the loop.  This means I can’t reuse it outside of the loop by accident.  If I declare the variable outside the loop I can use it again (sometimes by accident).  Of course, there are times you actually WANT to reuse the variable but I find those rare.

The other thing that I tend to do is reuse the same loop variable time and time again even in the same method.  So I get code like this:



for i as integer = 0 to ar.ubound
   
   //Do something in this loop
   
next

//Some other code

for i as integer = 0 to iMax
   
   //Do something in this loop
   
next

//Wrap up the function


I find this to be very readable (though I’m not doing anything in these examples). ‘i’ is my default loop variable and I think I’ve had entire apps where my only loop variable is i even though I’ve had thousands of for next loops.

Anyway, given the recent discussion on standards, I thought I’d ask what you do?  Do you have a preference?  Do you despise one over the other?  Does it really matter to you?

Happy coding!

24 thoughts on “Loop Variables

  1. This is not specific to REALbasic per se, but I prefer to have the loop induction variable as part of the loop statement itself. It has nothing to do with typing and everything to do with intent and clarity. The rule of thumb I follow is that you declare variables as close to where they are used, and you give them the smallest possible (sensible) scope. This makes your code easier to understand, and reduces the chance of accidental errors.

    I was really excited when we changed the language to allow this sort of expression in REALbasic. You are right that there (should never be) a performance difference. It’s purely scope-related, so the same work has to be done either way.

  2. The only reason I personally won’t do this is for readability. If you have all your local data declared at the top of a method, you know where to look for the declaration. Also if you only specify one variable per line, when you change things around it makes it easier to spot when the compiler marks them as unused variables. The same principles could be applied to those who locate their variable declarations as close to where they are used (like in a middle of a method). You have to ask yourself what is your goal? For me the goal is maximum readability which translates into better ROI because your code then doesn’t become OPC. The compiler doesn’t care, but if your eyes are fishing around each method for declarations and you multiply that by how many times per day you look for such things, it can add up and not to mention the constant micro-mental-overload.

    In the scheme of coding, placement of variables is minor area of concern. The bigger fish to fry is adding comments to the code. It is rare that someone does comment their code and it doesn’t matter how well they structure the actual code, because it takes a lot longer to figure out what they were intending to accomplish if there are no comments.

    If you’re a lazy programmer is not determined by what practice you adopt, but to the rigor you stick to whatever your goal is in these matters. Next rhetorical question is what is your goal?

  3. I can’t add nothing new to what Aaron Ballman explained so well.
    I just completelly agree on the fact that having the variable local to the loop, permits to avoid accidental errors.
    Also, when possible, I declare variables and instantiate classes inside other blocks such as the if…end if blocks for the same reason. This also helps on reduce the memory footprint in some cases.

  4. I used to agree with Brendan about declaring all variables at the top (dating back way back when, even before VB) but I have come around to defining temporary loop variable in the loop for the reasons you’ve mentioned: it doesn’t appear to affect the speed and it limits the scope so you can’t accidentally use a value from a previous loop elsewhere in the routine.

    It also means that all the remaining variables, which are still defined at the top, are the meaningful name ones, and the single letter variables are locally defined in the loop using them.

  5. If your goal is readability, then…

    for i as integer = 0 to ar.ubound

    …is less readable than…

    for i = 0 to ar.ubound

    …because you have to mentally parse the extra phrase in the logic predicate.

    Again, I ask what is your goal? I would not embed variable in the guts of a method because it is harder to parse them out (from the human brain perspective) and it is equally as likely to be error prone when one refactors, so what is the difference? So I choose readability because programmer time is more expensive. Simpler is usually better for humans.

    As a minor optimization point, when the RS compiler encounters a variable declaration, it sets it to a default value like zero for integer. So when you embed a variable in some sub-scope like shown below, it always initializes x before you use it. If you are doing a million iterations, stuff like this can make a difference in speed.

    for i = 0 to 1000000
    for j = 0 to 1

    Dim x as integer

    next
    next

    In the end, these types of arguments come down to the bias of the one who writes the official coding standard of the organization. I can live with people embedding their variables in sub-scopes because it is really a minor issue as long as they are consistent, but I rarely find that is the case. Again simpler is better. I would rather have people comment their code first and then worry about variable placement.

  6. @Brendan Murphy
    You can argue ‘simplicity’ all you want and, if memory serves, you did, when RB Code Reports called local to use variable declaration ‘wrong’ and many users thought you were wrong. Despite your argument you ended up changing it due to consensus. I think your argument is showing your own bias toward the way you prefer.

  7. Bob, of course I am showing my preference just as you are and I thought that was pretty clear! You are taking my “bias” comment out of context in that I was pointing out what gets implemented in an organization in these matters is in a sense dependent on who gets control of the coding standard. So it can be arbitrary what get set in stone for the employees that have to follow it. Are you following me? With RB Code Reports I think you are mistaken. Obviously from my comments it is clear I haven’t changed my position, but what I did do is make a “business” decision to make it more flexible and I didn’t remove the check. In general, you can’t go around and state “consensus” proves right because that will get you in trouble. History is littered with the fallen ideals of the consensus. So what you presented in that regard is more of a poke in the eye argument which is really not an argument at all.

    Simplicity is a valid argument for readability. In your own blog post you say, “and it just looked…odd.” That is cognitive dissonance you were experiencing in trying to rectify the combination of statements. Eventually you learned to overcome that dissonance and things smoothed out for you. In essence you have proved my point that combining orthogonal concepts like static variable declarations with active logic code is not the best way to go for readability. If your goal is “convenience” then the combination works. This is why I keep asking what is your goal? If you say, “for i as integer = 0 to ar.ubound” is more readable than the simpler version, then the buden of proof is on you.

  8. @Brendan Murphy
    Yes, I find it more readable because I know *exactly* what the scope of that variable is. If it’s defined at the top of the method then I have to wonder if it’s being used anywhere else in the method. So it’s not only more readable, but inherently safer since the compiler will then complain if you attempt to use it outside of loop.

    Just because it looked ‘odd’ doesn’t mean that it’s not valid way to code. I came from a language that couldn’t do that inline declaration. And, if you go back in the Wayback Machine, REALbasic couldn’t do that for many years. So when it was introduced it *did* seem odd because I wasn’t used it.

    My ‘simplicity’ argument was poorly worded and thought out. I think Aaron’s comment was really what I was striving for. The inline declaration makes “intent” clearly known and *that* is what I think makes it easier to read.

  9. Just when I start thinking that I am both a programmer and a “regular guy”, my wife reminds me that I keep coming back again and again to a blog where the hot topic of discussion is where the best place is to declare a local loop variable.

  10. I’d tend to agree that declaring the induction variable as close to use makes thing less likely to accidental reuse & easier to read code simply because you do not have to scroll code all over to know if

    for each thing in things
    next

    has each thing as an object, integer, etc

    for each thing as myThing in things
    next

    you can tell without moving your working focus around

  11. @Brendan Murphy

    I disagree Brendan — when you don’t have the declaration next to the variable, you don’t know what type the variable is without working at it. Is it an Int32? UInt32? Double? And this is quite important information to have. If you were doing a downto 0 loop and you had a UInt of some type, you’d have a fancy infinite loop.

    Good type locality rarely leads to *less* readable code in pretty much every stronly-typed language I’ve ever used with regularity.

  12. I’d just like to say that I like lines of code to be as short as possible.
    I’d rather 10 short lines to 5 long ones.
    It’s easier for my brain to follow the flow that way.
    So as a rule I’d rather fewer expressions per line.
    So I guess I’m with Brendan on this.

  13. When you embed the type in a loop construct you increase the information density and reduce its simplicity. This results in a statement that is less readable by definition. There is no getting around that fact. If you say it is more readable you are incorrect, but it may be better stated it makes it more “safe,” so you are going for safety. When I write code I will choose a goal like maximize readability which goes along the lines I have already stated. With the FTC I made the choice to sacrifice readability for some parts of it and go for end user discoverability where I selected the get/set/find paradigm so the end user could leverage the auto completion in the IDE. That is why I keep saying what is your goal. Think of Windows 8 where they combined two distinctly different paradigms into one package. There is a huge cognitive dissonance that goes on until the brain adjusts to it. It like the experiment where they made people wear glasses that made everything upside down. At first the subjects were completely disoriented, but after a week their brains adjusted and they were able to operate normally even though they were seeing everything upside down. When they ended the experiment and took off the glasses they again became disoriented for a short time because because the brain needed to readjust. So I still stand by my assertion that what you guys are suggesting is not more readable and that you have adjusted to a new paradigm and just call it more readable because you are used to it.

  14. @Brendan Murphy
    The issue with “code” is that it IS code – it’s already dense and only readable by people who have become familiar with the syntax & semantics of it. It’s why the world isn’t full of programmers.

    You’ll never make code read like English prose (or any kind of prose event though Cobol sure as heck tries) which is readable by a different audience.

    What I mean by “readable” is “understandable” and having variables typed close to where they are used helps that since I don’t have to scroll past a long list of declarations just to get to the guts of the particular code and then also scroll back to see what type was declared.

    The other reason to declare them right where used, specially in the case of loop variables, is that the compiler can help you find & avoid issues like using the loop variable outside where it should be used.

    When you declare everything at the top of the routine or block everything is valid everywhere in the enclosing scope & that may be completely counter to intent.

    For my money declaring them when they are first used makes life simpler the code more understandable and, FWIW, has helped me resolve a number of interesting issues in the IDE where loop variables were used outside the scope they should have been used. Simply by altering the code to declare the loop variable as part of the for loop I’ve had the compiler actually flag these errors with no extra effort on my part. Fixing the bug was then trivial.

  15. @npalardy
    There is a false premeis in your reasoning when you say, “…that it IS code…It’s why the world isn’t full of programmers.” First we call them programming “languages” and programming is a lot like learning english, french, music, logic, mathematics etc. They are all languages. It is true to say that programmers are human and they have brains like everyone else, so we are subject to the same principles that govern other languages. So to say it is “already dense” is not an argument. The contention is if you pack in more information, does it degrade readability? In general, yes it does. The same principle applies to english. The common factor that ties all this together is the human brain that has to interpret the language and you can’t escape that fact.

    The problem here is a problem of identity. What is readability? What I am contending is your definition of readably doesn’t match the reality of how the brain processes information. We should conform to how the brain works if you want to maximize readability. I hope you guys realize I am not saying you can’t or shouldn’t use local variables as you have stated, but to program with purpose and understand why you do what you do. If your definitions are incorrect of what is readable, then you can’t correctly judge it and what becomes judged as more readable is relative/subjective. All the counter arguments stated so far have to do with things like convenience or code safety. Fine then correctly label it as such and then you are doing things with a well defined purpose. Like I said in the beginning, I usually go for maximum readability because that has the best ROI. You may have other goals that are different from mine, but don’t confuse the fundamental definitions just so one can push a point of view. The constraining factor is our brain and it is very adaptive as I have pointed out and because someone overcomes a cognitive dissonance does not mean the fundamentals have changed.

    If you don’t understand what I am says at this point, then there is nothing that can be said. So Bob, next blog post!

  16. The problem here is a problem of identity. What is readability? What I am contending is your definition of readably doesn’t match the reality of how the brain processes information.

    I think the bottom line is that your definition of readability is different than mine. You keep arguing that your way matches the way the brain works. I disagree and so do others.

    What we’re arguing is purely semantic as neither way is right or wrong – it’s a preference. At the end of the day, you can code Real Studio the way you want and we’ll code the way we want. I never said I would force my way on anyone else and neither should you.

  17. I wish we could have “deep” discussions on other parts of RS that I have a lot stronger convictions about (such as the debugger which affects my understanding of my code infinitely more than where I declare loop variables). In the final analysis, I bet it affects the productivity of programmers in either camp very little. For the record I agree with Brendan, putting them all in place at the top of the method seems more orgranized to me, and organization of my code and thoughts is what I struggle with most. But as Bob says do what work best for you

  18. @Merv

    Yeah, the debugger went backwards from the 5.5 version to the new 2005+ versions. The stack was easier to understand in the older version and I never got lost drilling down. I figured it was just an issue of getting used to it. Well, it’s been about 7 years and I still hate the ‘new’ debugger. It’s not intuitive and has a bunch of stuff that is of little interest to me. The words “convoluted” and “cluttered” come to mind.

  19. “Cluttered” is an understatement. Most of the time I find it easier to just Dim a local variable, make the assignment, put a breakpoint in and check the value. I just get lost in that variable table way too much. Coming from VB6 I was spoiled with the Immediate Window and Edit-and-continue. I know we are not going to get Edit-and-continue because the RS IDE doesn’t run the code in interpeted mode like VB6 does, but it ought to be unbelievablly easy to improve on the the current variable viewer.

    RS developers I know you are check here, I hope you guys had the sense to make the Breakpoint marker bigger in the new IDE. Under Windows, the darn thing is so small I have to really look to find breakpoints. It needs to be much bigger than a few pixels wide circle, it ought to be clear where the code is going to stop, I shouldn’t have to look for it.

Comments are closed.