
Tom Duff: Reading Code From Top to Bottom (1999) - gnosis
http://iq0.com/notes/deep.nesting.html
======
bumbledraven
Duff's advice on avoiding if/else is echoed in a functional programming
context by CMU's Bob Harper, who writes, "[A]void if-then-else entirely, and
instead use only case analysis for branching..."
[http://existentialtype.wordpress.com/2011/04/17/some-
advice-...](http://existentialtype.wordpress.com/2011/04/17/some-advice-on-
teaching-fp/)

~~~
mahmud
Uhh, not same reasons. Harper is an ML hacker, he wants to avoid IFs to
encourage generic programming and pattern matching. Adding a new branch to an
if clause requires some nesting, adding a branch to a case/cond is just one
entry of many. After that, pattern matching becomes natural an you tend to see
a function not as a single wholesome "body", but a family of mappings.

Again, switch, duff's device & other computed-goto hacks are "constructs", a
chunk of "decision" code that sits in the middle of the page directing
traffic. Pattern-matching is far more sublime than that: along with
manifesting itself as a visual construct, it can also hide in the head of the
function, cozzying up with its parameters, and also in binding/assignment
forms.

A distant, but weaker cousin of pattern-matching is destructuring, more common
in Lisps.

------
mquander
Can someone older or wiser than me discuss what the idea is behind "only one
return per method" in imperative code? I agree completely that it makes many
methods much more difficult to read, and I've never understood why it was
taught as a guideline in the past (and why some people still seem to subscribe
to it today.)

EDIT: It makes a lot more sense to me now that I think about it in the context
of a language like C, with no garbage collection and no exceptions. Thanks!

~~~
brnstz
It was part of the structured programming dogma. One entry point, one exit
point. Multiple return was lumped in with using goto.

I never use goto, but I often use multiple returns similar to the examples in
this article.

I have sadly code reviewed many pieces of code with the nesting problem.

~~~
malkia
if you have to use C++ without exceptions (console video games), then goto is
much needed to handle exceptional situations locally. For example there would
be label "fail:;" or "out:;" at the end of the function, where release of
resource would happen, and you would "goto" to it, rather than releasing the
resources in multiple exceptional places and return from there.

~~~
__rkaup__
Why don't console games use exceptions?

~~~
to3m
No compiler support on one common system.

You should be handling every case anyway - by the time the code is done, there
are no exceptional situations left ;)

------
barrkel
On the topic of loops which end in a break ("Most egregious is the loop whose
last statement is break;!"): this can be useful for avoiding contorted control
flow when you have a switch statement inside the loop. Instead of coding:

    
    
        cont = 1;
        while (cont)
        {
            foo = bar();
            switch (foo)
            {
                case 0:
                    cont = 0;
                    break;
                default:
                    // other work
                    break;
            }
        }
    

You can do this instead:

    
    
        for (;;)
        {
            foo = bar();
            switch (foo)
            {
                case 0:
                    break;
                default:
                    // other work
                    continue;
            }
            break;
        }
    

IMO the idiom, once you're used to it, reads better.

(Yes, I know you can reduce the lines further e.g. putting foo=bar() into the
for statement, but it's the multi-level break I'm focused on here.)

~~~
ch
Why not:

    
    
        while( (foo = bar()) != 0 )
        {
            /* other work */
        }
    

Or even simpler (since 'foo' serves no real purpose in the example):

    
    
        while( bar() )
        {
            /* other work */
        }

------
chadnickbok
One, very simple, example:

int some_function( some_variable ) {

    
    
      if (some_variable) {
        b = 1;
      } else {
        b = 2;
      }
    
      log("Its important I log that I'm returning %d\n", b);
    
      return b;
    

}

If its not obvious why this is superior...

~~~
palish

      int some_function( some_variable ) {
    
        log("Its important I log that I'm returning %d\n", (some_variable ? 1 : 2));
    
        return (some_variable ? 1 : 2);
      }

~~~
mrspandex
Now you're duplicating logic for a log statement...

~~~
mahmud
I have a new __no_ computation in log statements_ rule. A bug in there is nigh
near impossible to fix because you're _not_ looking for it.

------
bumbledraven
I found a few other interesting little notes on his site:

<http://iq0.com/notes/trig.html> All you need to know about Trignometry

<http://iq0.com/notes/frobenius.html> The Frobenius-Burnside Counting Formula

<http://iq0.com/notes/geometric.html> Sum of a Geometric Series

