Slashdot Mirror


Developer Argues For 'Forgotten Code Constructs' Like GOTO and Eval (techbeacon.com)

mikeatTB quotes TechBeacon: Some things in the programming world are so easy to misuse that most people prefer to never use them at all. These are the programming equivalent of a flamethrower... [But] creative use of features such as goto, multiple inheritance, eval, and recursion may be just the right solution for experienced developers when used in the right situation. Is it time to resurrect these four forgotten code constructs?
The article notes that the Linux kernel uses goto statements, and links to Linus Torvalds' defense of them. ("Any if-statement is a goto. As are all structured loops...") And it points out that eval statements are supported by JavaScript, Python, PHP, and Ruby. But when the article describes recursion as "more forgotten than forbidden," it begs the inevitable question. Are you using these "forgotten code constructs" -- and should you be?

8 of 600 comments (clear)

  1. Doing it wrong? by marc.pn.beaupre · · Score: 5, Insightful

    Honest question: Am I not supposed to use recursion? Am I missing something?

    1. Re:Doing it wrong? by j_kenpo · · Score: 5, Insightful

      I'm just as baffled by this. I wasn't aware that recursion went out of style. Just another tool in the algorithm and design pattern toolbox. Did I miss the memo that it was taboo as GOTO?

    2. Re:Doing it wrong? by quenda · · Score: 5, Funny

      Honest question: Am I not supposed to use recursion?

      It depends. See https://developers.slashdot.or...

    3. Re: Doing it wrong? by gravewax · · Score: 5, Informative

      No but there are plenty of scenarios that require far more code an complexity when you don't use recursion, when the limits are well understood recursion is a valuable tool.

    4. Re: Doing it wrong? by AmiMoJo · · Score: 5, Interesting

      I am an embedded software engineer.

      You have to be extremely careful with recursion, because often you have a very small stack. We also try to avoid any dynamic memory allocation when possible, only using automatic variables. With some types of firmware, even automatics are not allowed, but I don't go that far.

      The danger with recursion is that even if you try to limit it, if you screw up it can be very bad. It can be much worse than, say, an infinite loop. The loop can be caught by a watchdog and if designed carefully shouldn't start corrupting other stuff. Recursion that grows the stack or allocates memory could end up overwriting things and causing all kinds of unpredictable behaviour. Remember that embedded systems typically don't have any memory protection or stack guarding, and only extremely simple memory management.

      Of course it does depend on the type of firmware too. My stuff often has to run for 5+ years without a reset, and is sealed so you can't just reset it if something does go wrong. If resetting is an option, you can take more risks. One option we considered was to do one reset every day by design, so that any issue which took longer than a day to emerge would never affect us.

      --
      const int one = 65536; (Silvermoon, Texture.cs)
      SJW, n: "Someone I don't like, and by the way I'm a fuckwit" - AC
    5. Re: Doing it wrong? by Anonymous Coward · · Score: 5, Insightful

      Well, most compilers convert most recursions into loops anyway: it is called tail recursion optimization.

      Correction: *some* compilers will convert *some specifically structured* tail-recursive function calls into loops.

      There are lots of ways to make recursive function calls not tail-calls which renders them ineligible for compiler optimization.

  2. What the article says by jbolden · · Score: 5, Interesting

    The article talks about 4 features: goto, eval (run code from a string), multiple inheritance, and recursion. It discusses why the 4 get attacked by simplicity advocates:

    goto -- incomprehensible logic in programs
    eval -- security risks
    multiple inheritance -- breaks single responsibility since one module can have subtle impacts on how other modules acts in this context
    recursion -- article isn't clear though the comments above are mostly correct. In non-tail recursive languages recursion usually creates algorithms that are O(n) in memory. Even in tail recursive languages this can happen (and in fact in those languages because more complex recursions are encourages O(n^2) isn't uncommon when recursion isn't used carefully / well understood).

    It then mentions that these things should be used to avoid complexity in certain situations.
    goto -- error handling
    multiple inheritance -- is generally too useful to give up. implement with interfaces and be careful
    eval -- JSON, HTML, math...
    recursion -- trees, some list algorithms... recommend to implement imperative style mostly though (article assumes the language can't handle recursion)

    Now my opinion:
    Recursion is obviously the best understood of the 4. It is easily provable that there exists recursive algorithms which are both important and are not implementable as loops. Recursion classification is a still active research problem. Most imperative programers don't even bother to think deeply about their algorithms and not using design patterns from recursive features means the same bugs are introduced over and over again in code. IMHO there is no reason not to be abstracting loops away using built in functional design patterns in code.

    Multiple inheritance is too powerful to give up. Java was wrong here. Better safety than the C++ style seems to be needed though. For OO languages this should be an active area of experimentation.

    goto is today rarely used and when it is it often avoids complexity. I think we hit the right level of compromise here decades ago and this is a dead issue.

    Eval I think history has shown that without explicit evals developers end up having to create implicit evals where the code acts in complex ways on input. The code / data duality is not dead. Complex evaluation of input and layering aren't going away. Perl's concept of taint checking is likely the best approach: make it explicit and let the compiler check for accidental security risks.

  3. Re:Poor article? by grep+-v+'.*'+* · · Score: 5, Interesting

    Recursion is an easy way to implement solutions to a number of problems. But if you don't have a clearly finite depth then it can be dangerous.

    In '88 (90?) I had a copy of Unix Sort for PC (MS-DOS) complied in I believe a Lattice C compiler from LifeBoat. It worked fine but ran slow as a dog, and this was when IBM AT were fast. So I found the routine that did the actual in-memory sort and made it recursive. It easily worked over 5x as fast but had the slight problem of ABENDing when it ran out of stack space, which the old version didn't have.

    So I fixed it: I left the recursive sort in place but did a free space stack check on entry. If there was less than 4K (4K!) left I switched to the slower non-recursive routine. I was able to keep sort speed around 4x of the original slower program but still have the program always successfully complete.

    It was a simple fix, but I have to admit I was impressed with myself for implementing that.

    EVERYTHING can be misused. Add meaningful comments so they are not misunderstood. Write everything for your peers and their less-experienced colleagues. If you're a genius who writes working code that no one else understands, you're not a genius. But if the person following you really is a blithering idiot, then nothing you do will help.

    --
    If the universe is someone's simulation -- does that mean the stars are just stuck pixels?