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?

600 comments

  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 Anonymous Coward · · Score: 1

      Well recursion incurs overheads such as pushing the current function's working values to the stack, passing the parameters onto the stack, then when the recursive call ends, it needs to pop stuff of the stack. The stack can grow big enough to crash the machine in some cases, and in most cases you can replace recursion with other means.

      Obviously if you're using it with a low number of levels it won't make much difference, it can make code neater and easier to understand, and in many cases the recursion itself can be optimized away (as in "tail recursion"). So it has uses but should only be applied to processes with a known, small number of steps/levels.

    3. Re:Doing it wrong? by Anonymous Coward · · Score: 1

      I thought it was widely recognized that recursion is often the most efficient solution. Then again, it should be widely recognized that gotos and evals are not evil, it is only terrible "programmers" who don't understand how computers work that shouldn't be allowed near them (because programmers already knew about if/switch/etc without linus having to say anything).

    4. Re:Doing it wrong? by Anonymous Coward · · Score: 0

      ... *elegant* solution, in terms of code. It's definitely not the most *efficient* in terms of processor load and memory. If you're working with memory and CPU constraints, recursion is not often going to be the best solution.

    5. Re:Doing it wrong? by Required+Snark · · Score: 2
      Without recursion, data structures like trees or graphs are useless. Kind of a problem if you have a directory tree structure, or you want to follows URL links for web scraping. Just on that alone, I would assume the rest of the article is crap.

      Does this horrible misrepresentation mean there are coders who don't realize that they are using a recursive algorithm? This lack of understanding could be a result of how some languages hide all the details of data structure implementation. Specifically, I'm thinking about Java. I saw a code example recently that was building a tree, but there were no obvious recursive calls anywhere. All the details were hidden in the data structure access interface. The way I knew what was going on was because "tree" was part of the object name.

      Given how "high-level" a lot of programming has become, I have a bad feeling that someone could be a working programmer and still have no idea what their data structures do. So if they do see recursive algorithms, they would call it a "forgotten code construct". Is this possible?

      --
      Why is Snark Required?
    6. Re:Doing it wrong? by Anonymous Coward · · Score: 0

      Also using recursion is by definition cache local, so these days they can be a lot faster than iterative versions of algorithm that have to store a reasonable amount of data.

    7. Re:Doing it wrong? by Dog-Cow · · Score: 2

      You seem to have a poor understanding of programming.

      1) Hiding implementation, including algorithm selection, is a large part of what objects are for.
      2) It's possible to write any traversal algorithm using loops, without any recursion.

    8. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      Recursion is forbidden in many embedded and security critical standeards due to uncrontrolled stack overflow.

      I do in all the time I C++ on Linux: the is just extents the stack as it would have with the heap if I had done the same with temporary objects needed to make the algorithm with iteration.

    9. Re: Doing it wrong? by PoopJuggler · · Score: 4, Interesting

      Recursion is undesirable because it doesn't scale - you run out of stack pretty quickly. There isn't really ever any need for recursion anyway as there's nothing you can do recursively that you can't do non-recursively.

    10. 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...

    11. 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.

    12. Re: Doing it wrong? by religionofpeas · · Score: 2

      Sometimes recursion is appropriate, e.g. when walking binary trees, and a non-recursive solution requires just as much space to keep track of what you're doing. On big platforms with virtual memory, the stack will grow with as needed. On small platforms, the recursion doesn't need to go as deep.

    13. Re:Doing it wrong? by religionofpeas · · Score: 4, Insightful

      2) It's possible to write any traversal algorithm using loops, without any recursion.

      Sure, but if that requires building your own stack, you haven't really gained anything.

    14. Re:Doing it wrong? by jbolden · · Score: 1

      The article is a bit lite the summary on /. is worse. The article itself specifically mentions your use case: data structures where you want to convert a list of data into a list of actions as examples where recursion is often helpful.

    15. Re:Doing it wrong? by scamper_22 · · Score: 1

      I generally advise against it.

      This doesn't mean it should never be used.
      But a lot of the time, it doesn't NEED to be recursive and making it recursive complicates thing.

      I'll give a practical example. I worked on router firmware when I first graduated and got assigned this bug where a router in South Korea kept crashing. Really hard to debug it. After a lot of debugging, I found out it was related to the number of ACLs applied to a policy. Went through the code and the section that applies those ACLs was recursive.
      So when the number of ACLs got too high, this function was recursively called and it ended up blowing the stack on the firmware and crashing.

      Was there any reason for this to be recursive? Nope.
      A simply refactoring and I made it into a for loop. Problem solved.

      Recursion just introduces more ways things can screw up. I generally like the idea of it being cautioned against. If you really can't write it resonably in a loop, then go ahead.

    16. Re: Doing it wrong? by Anonymous Coward · · Score: 3, Insightful

      Elegance.

    17. Re: Doing it wrong? by Some+nick+or+other · · Score: 0

      Try to write any sort of backtracking solver (e.g. integer or constraint programming, Sudoku, alpha-beta pruning, MCTS game AI) without recursion. Or even just a password brute-forcer. Listing every password of length n is a pain without recursion; you either get a loop n deep or you end up implementing your own stack.

      What these problems have in common is that they grow so fast that the computer doesn't really have time to reach stack overflow. Consider chess, for instance. No chess AI can go 100 turns deep, but pretty much every stack can handle 100 entries.

    18. Re:Doing it wrong? by Rockoon · · Score: 1

      Busting a hand-crafted software stack is far less problematic than busting the hardware stack that the cpu's call and return instructions directly use, and rapidly using a lot of stack brings in cache issues on many of the instructions compilers had expect to be low latency, significantly hurting performance.

      The fact is that recursion does not perform well on general purpose silicon. The performance degradation can be so significant that modern compilers are advertised to be able to perform an optimization that removes the recursion in some cases ("tail call optimization.")

      At least restrict your recursions to the cases of trees rather than lists.

      --
      "His name was James Damore."
    19. Re: Doing it wrong? by Cafe+Alpha · · Score: 1

      Uhm then you're using the wrong language.

      Lua and scheme have tail call optimization.

    20. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      Learn scala where everything is done with recursion to prove yourself wrong.

    21. Re:Doing it wrong? by Anonymous Coward · · Score: 0

      You mean, while you're not bored yet, see https://developers.slashdot.or...

    22. Re: Doing it wrong? by hcs_$reboot · · Score: 2

      If the algorithm is well designed and its complexity well calculated no bad surprise is to be expected. And anyway most algorithms, based on recursion or not, do not dive very deeply (i.e. do not consume much stack), since the time complexity, depth wise, is usually exponential and too much depth implies too much time.

      --
      Slashdot, fix the reply notifications... You won't get away with it...
    23. Re:Doing it wrong? by Anonymous Coward · · Score: 0

      Programming has always been in such a sorry state, and it's going to be worse the more people get dumped into it. Just think how idiotic would a field like mathematics look if, in their own slashdot, which had become only a sad shadow of what it once was, appeared an article like "huuuhhhh don't use because some collegues don't get it and can make a mess, mmkay"

      Yes, every recursive algorithm can be turned to an iterative one, and you are a sad idiot if you think it buys you something. If you manage to get it functionally right, you have turned possibly beautiful code into an ugly, unwieldy, contraption that needs the same state keeping that's automatically done by the compiler. That's just ignorance. Recursion was never a programming resource or a programming technique to begin with, it's a way to define objects in terms of themselves until some condition is reached. It's powerful, flexible and beautiful and it can get translated into a programming language and it's elegant and easy to maintain; only a sick mind would see something beautiful and turn it into a mess and be satisfied with the deed. This is putting weight in the wrong place. All languages have become more expressive over time, all of them. Even in assembler you can be elegant, but sadly what we see here is the confusion of Industry Needs(TM) with what CS is. To conclude I use my opening remark. The industry wants more and more "programmers". When all the real programmers are taken there are no more, no matter what they call themselves, they are monkey see monkey do people, and when you work with idiots you spawn middle management and meetings and detailed work orders and the crap that only idiots find good. I hope I never have to maintain some idiot's code.

      PS I have working code labelled considered_harmful just so I can write goto considered_harmful; screw this insanity of "forbidden" programming constructs.

    24. Re: Doing it wrong? by Anonymous Coward · · Score: 1

      Listing every password of length n is a pain without recursion

      FYI: Looping with std::next_permutation() runs within a constant factor of the recursive solution.

    25. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      Both can be useful. Sometimes it's better to use the heap or even the ssd for tree traversal.

    26. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      I've written a non-recursive chess engine. :/

    27. Re:Doing it wrong? by Anonymous Coward · · Score: 0

      Without recursion, data structures like trees or graphs are useless.

      Gee, that's funny, because with recursion, data structures like linked lists are useless. Guess what trees and graphs decay to in the worst case? Oh shit!
      Segmentation Fault (core dumped).

      tl;dr: You fail it. Don't use recursion unless you know the depth is bounded to less than a known small value (e.g. log(N)).

    28. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      Usually is the right word. A list is a tree.

    29. Re: Doing it wrong? by religionofpeas · · Score: 1

      Tail call optimization only works if you're actually doing a tail call, which isn't always the case. And if you're always doing a tail call, the recursion can be replaced by an iteration without too much trouble.

    30. Re: Doing it wrong? by Anonymous Coward · · Score: 1

      > just extents the stack as it would have with the heap if I had done the same with temporary objects

      This is why recursion should be forbidden: People don't even think about it or don't have a clue.
      OpenBSD used to have a stack limited to 64kB just a couple of years back.
      In a multithreaded environment, it is not even POSSIBLE to extend the stack as much as you want (as you will usually run into some other thread's stack REAL quick, 8 MB is the default in Linux).
      That results in code that works fine for the developer, then someone makes the architecture threaded and suddenly it crashes.
      There are also other issues, like that more data on stack usually means the program is much easier to exploit (this, among other things, was behind OpenBSD's restriction).
      These are the main reasons why recursion should be considered harmful (in C-like languages using the hardware stack):
      1) People implement it because it is "clean", but that is bought with them not even thinking 1 second about stack usage (otherwise they'd realize just how messy and complicated it actually is), so that the algorithm will randomly fail. Even if the recursion depth is fixed, adding a variable declaration can suddenly make your program crash. Algorithms using tail recursion don't suffer from that, but instead suffer from breaking if someone a bit carelessly adds code that breaks tail recursion.
      2) stack usage massively limits the possibility of threading (as a large number of threads means you need small stacks fit them all in the area the OS reserved for them).

      TL;DR: "Cleanliness" of recursion is usually bought via greatly reduced correctness and maintainability.

    31. Re:Doing it wrong? by Anonymous Coward · · Score: 0

      Ok, you say easy to maintain (and I assume you include C-style languages).
      So please tell me, how do you ensure your recursive functions isn't called with input it can't handle due to stack limits (how do you even figure out the stack limits on your architecture)?
      How do you even ensure it terminates gracefully if it does?
      How do you ensure nobody adds a 2 MB on-stack array in that recursive function, thus breaking it except for the simplest cases?
      How do you ensure your tail recursive functions is actually recognized as such by the compiler?
      I do not know a solution to ANY of these. If you do, you would do me a great favour if you told me, and I will have learned something.
      If you don't: You are NOT writing maintainable code, you are writing buggy and unmaintainable code, and you got fooled by it looking simple getting lucky that it never broke.
      It is beautiful and maintainable in the same ways a function "int random() { return 3; }" is a beautiful, simple and maintainable random number function.

    32. Re:Doing it wrong? by Required+Snark · · Score: 1
      Claiming "It's possible to write any traversal algorithm using loops, without any recursion." is incorrect for both trees and graphs. The closest you can come is to maintain a stack structure and manually push and pop data and control flow information on the stack. It's ugly, and recursion is much easier to code and debug. Having done it both ways, I can say that coding your own stacks and using loops is not easy.

      Your reply has answered the final question I asked: it is possible to be a "coder" and not understand recursion or recursive data structures. If you had ever studied data structures in computer science you would know that just looping is not enough.

      To be even more pedantic, there are some recursive data structures, such as the threaded binary tree that allow tree traversal without recursion. This works by replacing null links in the tree structure with pointers to the next node for a specific traversal order. This is more expensive to build or modify then a general binary tree, and making it in the first place uses recursion. If you want to know what other similar tricks like this you can pull, look at The Art of Computer Programming volume 1 chapter 2.3.

      --
      Why is Snark Required?
    33. Re:Doing it wrong? by Anonymous Coward · · Score: 0

      No, you didn't miss a memo.

      Hipsters.

    34. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      Lua iterator construction is bordering on beautiful. I always feel like I've crafted something when I finish with lua code, not all languages do that.

    35. Re: Doing it wrong? by AmiMoJo · · Score: 2

      Yep. Embedded people avoid recursion like the plague because they have limited resources. Sometimes desktop guys use it, and it works okay until someone opens a big file and it needs 18GB of RAM...

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

      Every time you make a function call, some amount of bookkeeping data has to be stored on the stack in addition to the actual data you care about.
      If you do "manual recursion", with a loop and a resizable container, then you can achieve lower overhead.

      Although I guess most of the time it doesn't really matter.

    37. Re: Doing it wrong? by whopis · · Score: 2

      Read this post and it's replies. It is a good explanation of the issues with recursion.

      http://slashdot.org/comments.p...

    38. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      Elegance.

      To reverse a string: Take the last character of the string and follow it with the rest of the string reversed.

    39. Re:Doing it wrong? by Z00L00K · · Score: 1

      Recursion is a very useful tool used right but very confusing for people trying to understand it if it's not well declared.

      Consider traversing a directory tree - that's a typical example of a "problem" that's solved with recursion.

      --
      If builders built buildings the way programmers wrote programs, then the first woodpecker would destroy civilization.
    40. Re: Doing it wrong? by Z00L00K · · Score: 4, Funny

      Whenever recursing, have a recursion counter and a termination condition that stops infinite recursions.

      --
      If builders built buildings the way programmers wrote programs, then the first woodpecker would destroy civilization.
    41. Re: Doing it wrong? by burnetd · · Score: 1

      You've not written stuff for browsers then. Some of them have had very strict limits on recursion, some of them still do.

      http://www.browserscope.org/us...

    42. Re: Doing it wrong? by Z00L00K · · Score: 1

      Just have a good exit criteria to avoid too deep recursions and it's not a problem on any system. Unless you code for a 4 bit processor or something other extremely small and weird.

      --
      If builders built buildings the way programmers wrote programs, then the first woodpecker would destroy civilization.
    43. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      That problem goes away with coroutines.

    44. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      There isn't really ever any need for recursion anyway as there's nothing you can do recursively that you can't do non-recursively.

      Try Prolog programming: it has no iteration, everything is done by recursion.

      testloop(0).
      testloop(N) :- N>0, write(‘Number : ‘), write(N), nl, M is N-1, testloop(M).
      ?- testloop(3).
      Number : 3
      Number :2
      Number :1
      yes

    45. Re:Doing it wrong? by jellomizer · · Score: 1

      I think we all missed the memo.
      Now there are some places where it is misused.
      1. Can make code too cryptic. When tracing code a recursive algorithm forces the observer to understand the full algorithm vs just the part which can make debugging an odd use case difficult.
      2. Limited stack space. So if you don't know how deep that routine will go. You could end up with some hard to fix problems.

      However some language like JavaScript really don't give you much of an option. Such as a lack of a sleep command and poorly implemented synchronize way to call data. Means using recursive method is necessary where one normally wouldn't.

      Then sometime there are problems where recursion is much more logical way to solve. While can be done with a loop but you need to make a stack by itself vs using the natural one that is in a recursion.

      --
      If something is so important that you feel the need to post it on the internet... It probably isn't that important.
    46. Re: Doing it wrong? by MagicMerlin · · Score: 1

      Ackerman can only be coded recursively...heh

    47. Re: Doing it wrong? by flux · · Score: 1, Informative

      You know, it might be a pretty good idea to not use recursion and just implement your own stack in many of those cases, because recursion locks you into one traversal algorithm, namely depth-first.

      If instead you collect the new nodes to visit to a list, you are able to choose whichever order to traverse those nodes easily. Such as in the order of "most promising prospect".

      With a list you can also wait until its size is larger than n and then split the list for multiple cores to execute, merge the resulting lists and gain some concurrency benefits this way.

      It's just a few lines of code to do the stack anyways in modern programming languages anyway.

    48. Re: Doing it wrong? by flux · · Score: 1

      Proper tail call optimizations also optimizes the case of not recursing to the same function That's a bit more difficult to make an iteration and you need to move all those functions involved into the same iterative loop.

    49. Re: Doing it wrong? by K.+S.+Kyosuke · · Score: 1

      Recursion is undesirable because it doesn't scale - you run out of stack pretty quickly.

      Tail calls, tail calls everywhere - at least in sane languages.

      There isn't really ever any need for recursion anyway as there's nothing you can do recursively that you can't do non-recursively.

      Modular compilation, actually. Coroutine-like transfer of control into places not known at compile time is very cumbersome. You need something like a trampoline. (Plus, recursion as a structural element of the program and recursion on the execution stack are two different things anyway.)

      --
      Ezekiel 23:20
    50. Re: Doing it wrong? by K.+S.+Kyosuke · · Score: 4, Insightful

      Every time you make a function call, some amount of bookkeeping data has to be stored on the stack

      Not necessarily, really, these days. But yes, if your compiler is really dumb, like in the 1970s, the difference can be significant.

      If you do "manual recursion", with a loop and a resizable container, then you can achieve lower overhead.

      Chances are that if you can do that easily, you should have done it in the first place, and if you can't, there was a reason for that.

      --
      Ezekiel 23:20
    51. Re: Doing it wrong? by K.+S.+Kyosuke · · Score: 0

      Just because someone has derived a "closed form" solution for a well-known, simple problem doesn't mean that you will be able to do the same thing with your own specialized problem.

      --
      Ezekiel 23:20
    52. Re: Doing it wrong? by K.+S.+Kyosuke · · Score: 2

      And if you're always doing a tail call, the recursion can be replaced by an iteration without too much trouble.

      Well, the good thing is that the compiler can do this automatically, so if you're writing a program from scratch and already know what it will do (which is often the case), these manual decisions are fine, but if you already have a working program and the desired logic changes a bit, switching between iterations and recursions by hand is much more involved now than just letting the compiler figure out the changed tail call positions.

      --
      Ezekiel 23:20
    53. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      There are languages that do not optimise tail-recursion, such as C .In such languages, computing the sum of the elements of a large array is efficiently done with a for-loop, whereas recursion would use excessive stack space. In many cases your recursion depth scales with the log() of the input size, making it efficient.

      Anything that can be done iteratively, can be done recursively; sequential thinking is a hallmark of the newbie hacker.

    54. Re: Doing it wrong? by religionofpeas · · Score: 1

      Embedded people avoid recursion like the plague because they have limited resources.

      You can't make blanket statements like that. It all depends on the recursion depth, your embedded platform, and the requirements of an alternative solution. You can have embedded platforms with 100 bytes or with 100 MB, with or without virtual memory and possible dynamically growing stacks. Also, if you need to build your own stack to avoid recursion, where are you going to store it ? Static memory is wasteful, and not all embedded platforms have heaps. And what are you going to do when your manual stack isn't big enough ?

      Sometimes desktop guys use it, and it works okay until someone opens a big file and it needs 18GB of RAM

      Never heard of paging ?

    55. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      No but there are plenty of scenarios that require far more code an complexity when you don't use recursion

      That isn't necessarily a bad thing.
      It's a bit of abstractions really. They can make the code look neat but that also hides horrible performance bombs and security issues.
      Recursions also hides performance holes in a neat little function call.

      The main downside is that it doesn't give a fine grained control over what resources are allocated for each iteration in the recursion-loop.
      In many cases where recursion solves the issue you often only need one or two variables stored for each level. Recursion doesn't care, it will allocate a complete stack-frame for each iteration.

    56. Re: Doing it wrong? by Anonymous Coward · · Score: 1

      It's just a few lines of code in assembly on any architecture that can access memory with an address stored in a register.
      If it isn't trivial in a modern programming language it is probably very specialized for a specific type of problems. (See how I don't outright call it a bad language.)

      Unless you have decided that it is easiest to write your program in a functional language you are probably better off avoiding recursion.

    57. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      Some algorithms, such as path compression by Rank in union-find will naturally limit the recursion by Inverse of Ackerman.
      That's max 5 levels for any problem ever.

    58. Re: Doing it wrong? by K.+S.+Kyosuke · · Score: 3, Insightful

      They can make the code look neat but that also hides horrible performance bombs and security issues.

      Then they're lousy abstractions. Abstractions are here to hide irrelevant details that you'd get wrong if you had to do stuff by hand identically in many places and correctly all the time. Doing something right just once is the exact opposite of having a security issue.

      Regarding stack allocation, that ought to be O(1), anyway.

      --
      Ezekiel 23:20
    59. Re: Doing it wrong? by N!k0N · · Score: 1

      Lua iterator construction is bordering on beautiful. I always feel like I've crafted something when I finish with lua code, not all languages do that.

      I feel the same about Java ... granted, that something would be right at home in the 9th circle of hell ...

    60. Re:Doing it wrong? by jenningsthecat · · Score: 1

      You seem to have a poor understanding of programming.

      1) Hiding implementation, including algorithm selection, is a large part of what objects are for...

      IANAP - I'm a hardware guy, more into analog and RF than digital. When I'm dealing with hardware that has a 'black box' module, or an IC I can't find data on, or even when I'm repairing a complete system for which I don't have schematics or even wiring diagrams, I'm working in the kind of 'hidden implementation' space you're talking about. And whenever I'm in that position, the first thing I try to do is gain an understanding of the design and the behaviour of the module, circuit, or whatever. It always makes the work easier, and sometimes it's necessary, as in I if I can't figure it out I can't fix it. And when I'm designing a circuit, I always like to know what's going on inside any 'black-box' items I'm thinking about using.

      I've also worked with programmers and heard them talking about the unexpected behaviour of some function or object. I totally get the purpose and power of objects in programing - but aren't there times when penetrating that abstraction will allow a programmer to write better code? And aren't there times when it's outright necessary for debugging the program?

      --
      'The Economy' is a giant Ponzi scheme whose most pitiable suckers are the youngest among us and the yet-unborn.
    61. Re: Doing it wrong? by angel'o'sphere · · Score: 4, Informative

      Stack frame allocation costs exactly: nothing.
      So why do you care?

      You fear an endless loop and running out of stack space?

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

      I don't remember when I saw recursion the last time in production code, likely decades ago, and you care about the raw cases where a manually written loop is "better" than recursion ... wow.

      --
      Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
    62. Re: Doing it wrong? by angel'o'sphere · · Score: 1

      And if you're always doing a tail call, the recursion can be replaced by an iteration without too much trouble.
      Yeah ... but why would anyone do that?

      --
      Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
    63. Re: Doing it wrong? by angel'o'sphere · · Score: 1

      Embedded people use C/C++ and mostly GCC wich means: it has tail recursion optimization just like any other modern language/compiler.

      No idea why people always spread myths about embedded programming. It is not different to other programming for most people involved.

      --
      Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
    64. Re: Doing it wrong? by religionofpeas · · Score: 1

      Yeah ... but why would anyone do that?

      Because you don't know always for sure that your compiler implements tail recursion optimization. I've worked on embedded projects, where the whole project was compiled with -O1 and tail recursion wasn't optimized. So, if the iterative solution isn't any more complex, I'd use that instead.

    65. Re: Doing it wrong? by angel'o'sphere · · Score: 1

      That is wrong.
      Every recursion can be expressed as a loop or nested loops.

      --
      Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
    66. Re: Doing it wrong? by jiriw · · Score: 0

      Hmmm, I do use recursion as one of my main data patterns.When you have a graph of elements it's damned useful to use recursion to set all elements in a wanted state or to access information buried deep from the entry point.
      Who runs out of stack space on modern desktop computer platforms anyway unless you messed up your break condition or you've made very, VERY large data structures? I can expect such concerns on embedded devices, but even mobile stuff nowadays has (relatively speaking) 'infinite' memory. We're not programming for dumb phones or Palm Pilots anymore (and yes I did do programming for those and used recursion even there).

    67. Re: Doing it wrong? by religionofpeas · · Score: 1

      There are languages that do not optimise tail-recursion, such as C

      A good C compiler will do tail recursion.

    68. Re: Doing it wrong? by sg_oneill · · Score: 1

      Recursion is undesirable because it doesn't scale - you run out of stack pretty quickly.

      Badly designed recursion doesnt scale. However well defined problems that require it and have well understood limits, its fine and often optimal, particularly if the algorithm can be tail recursed.

      There isn't really ever any need for recursion anyway as there's nothing you can do recursively that you can't do non-recursively.

      Yes, but many algorithms will still require a stack and become incredibly more complicated and slow, such that there are literally no benefits.

      --
      Excuse the Unicode crap in my posts. That's an apostrophe, and slashdot is busted.
    69. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      Lol the 4 bit processor i work on has a stack size of precisely 1 (plus 1 for interrupts). And with the 128 nybbles of ram split up into banks i dont think i want to implement manual stacks...

    70. 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
    71. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      No gcc for pic18 or 8051 or stm8 sadly.

    72. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      It is called misra and it runs your cars.

    73. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      Yes, but, do Black Lives Matter?

    74. Re:Doing it wrong? by Anonymous Coward · · Score: 0

      Recursion limits your traversal through the graph to depth first search if I'm not mistaken.
      If you want to do breath first, or some other approach you will need some stack like data structure anyway.
      That said, needlessly avoiding recursion when it's clearly appropriate seems like pure idiocy to me.

    75. Re: Doing it wrong? by ShanghaiBill · · Score: 1

      a non-recursive solution requires just as much space to keep track of what you're doing.

      Nope. Recursion saves the instruction pointer on the stack, in addition to whatever other data is required. So a non-recursive equivalent will be slightly faster and use slightly less memory, at the cost of being slightly less understandable.

    76. Re: Doing it wrong? by DarkOx · · Score: 0

      I am going toss this out there. The whole reason to use a binary try is for efficient searching. If the tree is so big that you potentially can't search it because of stack space burned in a recursive walk, than a binary tree was probably the wrong choice for a top level data structure anyway.

      --
      Repeal the 17th Amendment TODAY! Also Please Read http://www.gnu.org/philosophy/right-to-read.html
    77. Re: Doing it wrong? by religionofpeas · · Score: 2

      Maybe the tree is on an SD card, and the stack resides in a small RAM.

    78. Re: Doing it wrong? by angel'o'sphere · · Score: 1

      So you consider it easier to change perfectly running code (for what reason?) instead of fixing the compiler settings?

      --
      Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
    79. Re: Doing it wrong? by religionofpeas · · Score: 1

      if you screw up it can be very bad. It can be much worse than, say, an infinite loop.

      I'd rather have very bad effects in my embedded code than small and subtle effects that can stay hidden for a long time, but still have the potential to screw up the application.

    80. Re: Doing it wrong? by religionofpeas · · Score: 0

      In the general case, if you convert a recursive program to non-recursive, you also need to save the current state, including something equivalent to an instruction pointer if there are multiple places in your routine where you want to go a level deeper. In addition, you may need a dispatcher to go back to that point when you come back. Using a function call + return may even be faster in those cases because you're using the native support, and you don't need to waste another register on a user stack painter. Also, maintaining your own stack requires additional memory. If you put this on the heap, you also have the overhead of malloc/free.

    81. Re:Doing it wrong? by jcr · · Score: 1

      There are plenty of situations where recursion gets the job done with a minimum of code complexity. You just need to be aware of what the runtime costs might be.

      -jcr

      --
      The only title of honor that a tyrant can grant is "Enemy of the State."
    82. Re: Doing it wrong? by jcr · · Score: 1

      That would be good to know if, god forbid, I ever had to deal with C++ again.

      -jcr

      --
      The only title of honor that a tyrant can grant is "Enemy of the State."
    83. Re: Doing it wrong? by religionofpeas · · Score: 4, Insightful

      So you consider it easier to change perfectly running code (for what reason?) instead of fixing the compiler settings?

      Sometimes, yes. The project was for a medical application, with 99% of the code written by others. I'm not going to change global compiler settings and risk exposing some optimization error, when I can simply change a few lines of my code.

    84. Re:Doing it wrong? by geoskd · · Score: 3, Informative

      Am I not supposed to use recursion? Am I missing something?

      Recursion has a whole host of negative consequences that make it an undesirable programming construct. The most basic ones don't apply universally, but are nonetheless relevant.

      The number one reason not to use recursion is because it is very easy to exhaust the stack in system with more limited memory like embedded systems.

      The next most important reason to not use recursion is because it is slower. Iterative loops are easy for a compiler to optimize, and the branch instructions used for iterative loops are single cycle (or on some architectures less than 1 cycle) instructions. This makes them fast. Compare that with function calls which are always more than 1 cycle per call (at least 1 cycle for the call, and another one for the return). It is also extremely difficult for a compiler to unroll a recursive calling structure whereas loop unrolling is almost trivial. Compiler that can do recursion unrolling will hate you if the recursion depth is greater than about a thousand levels deep, as the compiler will eventually exhaust memory and fail.

      Recursion is a maintenance nightmare. Trying to ferret out what a recursive function is doing can be difficult even in relatively trivial implementations. The maintenance phase of the software lifecycle is more than half of the total effort, so give those guys a fighting chance and avoid "elegant" solutions unless you have an overriding reason, which you will never have when it comes to recursion.

      Recursion uses more memory. Each pass through the recursive function, you have to pile return vectors and function parameters into new locations on the stack. These data have nothing to do with your algorithm and represent pure overhead. iterative loops do not have this overhead penalty.

      In the end, recursion is one of those things that makes a great teaching tool, because it forces programmers to think about the consequences in non-linear program space. In practice it is a bad idea and will get you into trouble sooner or later. It is in fact so troublesome that recursion is expressly forbidden in safety critical systems.

      --
      I wish I had a good sig, but all the good ones are copyrighted
    85. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      Commas and fullstops are also valuable. Learn to use them properly.

    86. Re:Doing it wrong? by Anonymous Coward · · Score: 0

      You think about your code and don't blindly follow rules.

    87. Re: Doing it wrong? by Wuhao · · Score: 1

      I'm not sure what you mean when you say "you run out of stack pretty quickly." You run out of space in an 8-bit int "pretty quickly," but I still use those when the situation calls for it and I know I'm never going to need that much range. I don't get to use recursion often, but when I do, it improves readability and elegance. In most cases, I value those more than execution time or a restriction on domain that I was never going to exceed in the first place.

    88. Re: Doing it wrong? by geoskd · · Score: 1, Interesting

      You can't make blanket statements like that. It all depends on the recursion depth, your embedded platform, and the requirements of an alternative solution.

      Yes, you can make blanket statements like that. *Every* embedded software design standard expressly forbids recursion. There is 50 years of experience with these kinds of systems that pretty conclusively condemns recursion.

      You can have embedded platforms with 100 bytes or with 100 MB, with or without virtual memory and possible dynamically growing stacks. Also, if you need to build your own stack to avoid recursion,

      If you are building a stack to avoid recursion, then you haven't thought through the problem very well, and are just trying to emulate recursion without recursion. The problem space can always be transformed into one that does not require recursion, and it is that transformation that is critical, because it is what changes the problem from one that is effectively unbounded to one that is provably bounded. Embedded systems (especially safety critical systems) *must* be bounded. If you want to write programs without understanding the fundamentals of computer science then go be a windows programmer, but don't be too shocked when your software is bloated, slow, and prone to crash

      --
      I wish I had a good sig, but all the good ones are copyrighted
    89. Re:Doing it wrong? by luis_a_espinal · · Score: 1

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

      In general, only for prototyping, describing problems or when using a language that has sufficient support for tail recursion. Otherwise, I'd say no.

      You have to understand it though, and understand it well. But if I see someone on the wild using a recursive solution from scratch, I'd be wondering wtf is going on.

      Honestly, I've only seen custom code recursive code, and it was a fuck up.

    90. 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.

    91. Re: Doing it wrong? by thsths · · Score: 1

      Exactly. Recursion is heavy on stack use, and you cannot be sure that your target system has enough stack space available.

      But it depends on how you use it. Binary recursion is usually considered ok, because you end up with a reasonably small number of levels (in the tens). Divide and conquer is a classic example, but even there you will usually find a loop implementation, because it is faster, and only marginally more difficult to code. Linear recursion on the other hand is complete madness, both in terms of stack use and in terms of performance.

      A decent functional language will unroll recursion into a more efficient loop implementation. C will not do that. So as always, you should understand your language and your compiler.

    92. Re: Doing it wrong? by Anonymous Coward · · Score: 1

      I defy you to name one compiler that doesn't at least store the return address - i.e. "some minimum amount of bookkeeping data" - on a stack-like structure in memory.

    93. Re:Doing it wrong? by ceoyoyo · · Score: 1

      I think they stopped teaching children what recursion is.

      They can all get off my lawn.

    94. Re: Doing it wrong? by Fragnet · · Score: 1

      Many uses of recursion aren't required to scale.

    95. Re: Doing it wrong? by Fragnet · · Score: 1

      because recursion locks you into one traversal algorithm, namely depth-first.

      What? No it doesn't.

    96. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      And pray tell me, of the developers who use recursion, how many of them do you think keep tail recursion optimisation in mind when they write their code?

    97. Re: Doing it wrong? by religionofpeas · · Score: 1

      *Every* embedded software design standard expressly forbids recursion

      My embedded software design standard doesn't.

      because it is what changes the problem from one that is effectively unbounded to one that is provably bounded

      Recursively searching a binary tree is bounded by the depth of the tree, just like many other recursive methods are naturally bounded by the data they work on. And If the original problem space is unbounded, your recursive code is crap, and needs to be fixed properly. Just changing it to a non-recursive method doesn't magically fix the problem, or make it bounded.

      If you want to write programs without understanding the fundamentals

      I do understand the fundamentals. That's why I can safely use recursion when the problem calls for it.

    98. Re: Doing it wrong? by religionofpeas · · Score: 1

      Recursion is heavy on stack use, and you cannot be sure that your target system has enough stack space available.

      Of course you can. You just figure out maximum recursion depth, and then check if there's enough stack space.

      C will not do that. So as always, you should understand your language and your compiler

      GCC has no problem identifying tail recursion and optimizing it away. I'm sure other modern C compilers do the same thing.

    99. Re: Doing it wrong? by TheRaven64 · · Score: 1

      This is true for a language like C, where you have strict constraints on the function call ABI. For languages that are designed with recursion in mind, it's common to transform a recursive call into a continuation passing representation. Called functions are then always tail called, but sometimes take a continuation as an extra argument (which they then tail call instead of returning). The last step prior to the back end will then turn some of these back into call-return structures to take advantage of the hardware's support for the stack.

      --
      I am TheRaven on Soylent News
    100. Re: Doing it wrong? by lgw · · Score: 1

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

      They don't though, is the problem. But that's a problem with compilers, not the concept.

      I've done "manual recursion" before -- creating a stack as a variable in order to use a loop -- in kernel space where the stack was too small to do otherwise. It's not a pleasant approach, but was still better than the alternatives.

      --
      Socialism: a lie told by totalitarians and believed by fools.
    101. Re: Doing it wrong? by lgw · · Score: 1

      That's true for trivial tail recursion, and refactoring that into a loop often makes sense, with no loss in clarity. But for something like a tree walk, the iterative approach (one that doesn't just make its own stack) is usually "too clever", the sort of code that breaks the first time a maintainer touches it.

      --
      Socialism: a lie told by totalitarians and believed by fools.
    102. Re: Doing it wrong? by TheRaven64 · · Score: 1

      Embedded is a term that ranges from 4- and 8-bit microcontrollers with under 1KB of RAM up to storage appliances with multi-core multi-GHz CPUs and hundreds of GBs of RAM. There are very few generalisations that are true for that entire space.

      --
      I am TheRaven on Soylent News
    103. Re:Doing it wrong? by Anonymous Coward · · Score: 0

      My main problem with recursion is that my computer has 16GB of RAM and a 64bit address space but my stack is tiny -- I keep having to transform problems which use recursion into a using a custom-written stack, just to get around stack limits. If only the stack could grow as much as heap, I'd be happy recursing all day long.

    104. Re: Doing it wrong? by lgw · · Score: 1

      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 [the stack]

      You wot mate?

      When I did low-level programming last, we didn't use a stack, most memory used was either a fixed-sized data structure loaded with the code, or a fixed-size data structure passed by the caller (and, in turn, either loaded with it's code or passed by its caller).

      The limited dynamic allocation we did was all slab-allocated. E.g., the spec says we support 100 connections, and we pre-allocate a slab of 100 connection data structures, but allocate dynamically within that.

      --
      Socialism: a lie told by totalitarians and believed by fools.
    105. Re: Doing it wrong? by lgw · · Score: 1

      Meh, "manual recursion" is still recursion - allocating your own stack on the side isn't really changing the problem, just expressing it awkwardly in code.

      --
      Socialism: a lie told by totalitarians and believed by fools.
    106. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      Been doing this professionally for 20 years in the gaming industry. If recursion works, is easier to write and read and given the constraints would never cause a problem with stack, memory or efficiency, then imho, recursion would be the right tool for the job.

      Unrolling or doing recursion manually would generally be considered a premature optimization in these cases, and just cause unnecessary complexity.

    107. Re: Doing it wrong? by prefec2 · · Score: 1

      Recursion is acceptable, but you may run out of stack space iff you get into endless recursion. However, this can be detected by a compiler under some conditions.

      GOTO however, is weaker in semantics than a loop or condition, as it can imply both.

      The article is stupid anyway. He only added recursion so that he can easily claim that it us useful and so is goto. That happens when.people stop reading Kuth and get their education from YouTube.

    108. Re: Doing it wrong? by prefec2 · · Score: 1

      Exactly. But it can be done by the compiler and I can specify the function much more elegant and readble.

    109. Re: Doing it wrong? by AmiMoJo · · Score: 1

      As I say, it depends on the system. In the stuff I'm working on we allow automatic variables and passing on the stack (although GCC always uses registers in all the code we have), but keep them small. Anything more than a few bytes gets statically allocated.

      If I were allowing 100 connections, I would statically allocate memory for 100 connections and then dynamically assign slots. I wouldn't use malloc() or it's kin, even with a limited size section.

      This is on devices with a few kilobytes of RAM. If memory pressure is an issue we do statically allocate everything. Sometimes twice, if we are concerned about RAM being corrupted.

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

      Recursion is forbidden in some safety critical applications. MISRA (Motor Industry Software Reliability Association) C specification rule 70 forbids recursion.

      With recursion there is no way for a static code analysis tool to check the maximum stack usage, and static code analysis is a very important in software development for safety critical applications.

      Some (maybe all?) Harvard architecture microcontrollers have a hardware stack for storing the program counter.

    111. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      Not all recursion is tail recursion so cannot always be unrolled by the compiler.

    112. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      Maintainabilty over efficiency will pay off over time imho. Only if the reward outweighs the costs of complexity should the higher performing solution be considered.

    113. Re: Doing it wrong? by ziggystarsky · · Score: 1

      *Few* compilers would be more be even more correct.

    114. Re:Doing it wrong? by Anonymous Coward · · Score: 0

      Recursion is something you do in C, and maybe Javascript. All the "OOP" languages discourage you from this because they want you to create objects with their own functions, and functions that do nothing but return variables. Yes, basically making everything half as efficient instead. Recursion lets you just do A>B>A>B>A>B or A>A>A>A>A>A until it reaches a terminate condition, just like while. In things like Java, and interpreted languages you run out of stack space quickly.

      There are dangerous things in programming. The "goto" statement is one of them, which is a holdover from BASIC, and Assembly before it. You can't use a GOTO statement in C++ or in C11 that would make it jump out of scope, which is why it's discouraged (much like Annex K, which Microsoft depreciated the normal functions and nags you to use the Annex K versions.)

      eval however is the most dangerous function in the world, as that is how every malware leaks into PHP, and how every dangerous script gets into Javascript. You should never use eval for any reason, and if you have to use eval, you aren't a good programmer. A similar thing can be said about document.write in Javascript (which is worse than eval except it only applies to html markup, but lets you write any arbitrary dangerous thing into the page.)

    115. Re:Doing it wrong? by Anonymous Coward · · Score: 0

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

    116. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      Stack frame allocation costs exactly: nothing.

      No, it has extremely low cost, but it's not exactly cost free. This statement is also misleading because recursion will trigger variable initialization (much of which may be non-obvious).

    117. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      gcc 4.8.4, in certain circumstances. You may be conflating the function calls you make (e.g., the C code you write) with the lower level instructions that the compiler produces and the hardware executes. The more sophisticated the compiler's optimizations, the greater the possible dissimilarities.

      When gcc optimizes tail recursion, the emitted assembly code contains no recursive calls. Thus, the C code is written with recursive calls, but at run time nothing is placed on the stack to carry out the computations.

    118. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      Stack frame allocation costs exactly: nothing.

      If you are doing crazy performance sensitive stuff you get inliner issues and function call overhead.

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

      That wont happen unless your compiler can prove that your code is tailrecursive and in most languages there is no way to force this optimization. Relying on a it "might work" when the worst case is a stackoverflow in production is not good. The nice feature of tail recursive algorithms is that they are trivial to turn into a loop, so the only use of the recursive version is to kill debug and other -O0 builds.

      I don't remember when I saw recursion the last time in production code

      I see it daily, traversing a generally flat nodegraph ( 4 to 20 layers deep). Theoretically it could overflow with a bad graph, practically it would crash the application on startup, so it can't cause any real damage.

    119. Re: Doing it wrong? by fahrbot-bot · · Score: 4, Informative

      Recursion is undesirable because it doesn't scale - you run out of stack pretty quickly. There isn't really ever any need for recursion anyway as there's nothing you can do recursively that you can't do non-recursively.

      While that's basically true, as a former LISP programmer, I can attest that recursion can be simpler and more elegant to code, understand and maintain. It's really good for prototyping and proof-of-concept work, where speed and scaling may not matter. For example, coding a tree search is about 3 lines of recursive code vs. 2 pages of non-recursive code. I sometimes even use a recursive version of a function to verify the operation of a non-recursive function.

      --
      It must have been something you assimilated. . . .
    120. Re:Doing it wrong? by zifn4b · · Score: 1

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

      Nope. Recursion is incredibly useful for graph traversal.

      --
      We'll make great pets
    121. Re:Doing it wrong? by Anonymous Coward · · Score: 0

      I use recursion quite a bit...it can be extremely elegant. The only real problem is when it's in the hands of someone relatively inexperienced with them. They can be hard to conceptualize, and it's super-easy to get stack overflows in the hands of a neophyte. Particularly nasty because stack overflows often blow up the debugger, so an inexperienced coder will have to deal with simply figuring out what the exception is since it's crashing the debugger.

    122. Re:Doing it wrong? by zifn4b · · Score: 1

      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?

      This article is incredible questionable as to its credibility and competence. Real programmers that have been in the business like myself for 30 years and have used many languages and styles of programming styles (procedural, functional, OOP, etc.) will tell you that recursion is still incredibly useful (especially for graph traversal) and functional programming languages also rely heavily on it. GOTO/GOSUB on the other hand have no practical use anymore. The only thing I might think you would consider using this for is for assembly language to optimize a particular piece of code for performance like in a device driver but most of the time these types of semantics are done via computer optimization like a compiler or perhaps something that is trying to optimize a circuit board design. If you compile something in any compile time language like C++ and decompile it, you will see lots of JMP's (the equivalent of a GOTO in assembler, go to this [memory address]). In fact I think you see that in JIT languages like java and C# too in the byte code as well. However, you should never be writing high level language code in this way because it turns into a spaghetti code mess that after awhile cannot be followed even by the best and brightest software engineers.

      --
      We'll make great pets
    123. Re: Doing it wrong? by zifn4b · · Score: 1

      Recursion is undesirable because it doesn't scale - you run out of stack pretty quickly. There isn't really ever any need for recursion anyway as there's nothing you can do recursively that you can't do non-recursively.

      If you're concerned about that then use a stack object on the heap to accomplish the same thing. It's still recursion just a different implementation.

      --
      We'll make great pets
    124. Re: Doing it wrong? by david_thornley · · Score: 4, Insightful

      Some algorithms are naturally recursive. For example, in-order traversal of a binary tree is easiest described as: deal with the left child, deal with this node, deal with the right child. Tower of Hanoi is easily solvable with: Move all disks above the one you want to move to the other peg, move the disk you want to move to the peg you want to move to, move the disks you moved earlier to on top of the disk you wanted to move.

      In these cases, if you use loops, you're going to be making up all the stuff recursion is good for, and you're going to be maintaining your own stacks. There's no advantage to doing this rather than using recursion. If you were going to get into a loop and recurse indefinitely, if you translate it into loops you're going to get into a loop and push indefinitely.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    125. Re: Doing it wrong? by tender-matser · · Score: 1

      Algorithms using tail recursion don't suffer from that, but instead suffer from breaking if someone a bit carelessly adds code that breaks tail recursion.

      I always wondered why nobody thought about implementing some sort of pragma / gcc-style attribute to mark a function call as a tail call (and let the compiler error out if it's not a tail call, or if it's just not able to optimize the outer frame away).

      2) stack usage massively limits the possibility of threading (as a large number of threads means you need small stacks fit them all in the area the OS reserved for them).

      That's one of the reasons why running the threads in separate address spaces would be such a great idea ;-)

    126. Re: Doing it wrong? by zifn4b · · Score: 1

      I don't remember when I saw recursion the last time in production code, likely decades ago, and you care about the raw cases where a manually written loop is "better" than recursion ... wow.

      It's not useful in most common programming situations especially in business software. Where it is useful is when dealing with non-linear graphs like binary search trees. Consider this application, we have a text adventure game and an actor is in one room and another actor is in a different room. Describe the general purpose algorithm to find the shortest path from actor A to actor B without recursion. In other words, implement a breadth first search of depth first search without recursion. You will find it's significantly more difficult to do without recursion.

      --
      We'll make great pets
    127. Re: Doing it wrong? by zifn4b · · Score: 1

      If you do "manual recursion", with a loop and a resizable container, then you can achieve lower overhead.

      Chances are that if you can do that easily, you should have done it in the first place, and if you can't, there was a reason for that.

      If the first thing that comes to mind when thinking about how to implement a recursive algorithm without using compile time function stack isn't using some type stack then you really don't know what you're talking about. Go back to Computer Science class.

      --
      We'll make great pets
    128. Re: Doing it wrong? by david_thornley · · Score: 1

      Yup. Programming with limited resources can result in hard-to-understand programs that would be easier to understand if the right abstractions were available, typically on a larger machine. PNGs at 11.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    129. Re: Doing it wrong? by david_thornley · · Score: 1

      Exactly. Recursion is heavy on stack use, and you cannot be sure that your target system has enough stack space available.

      If your solution involves a stack, it doesn't matter within a constant factor whether you use recursion or keep a stack manually. If it's recursing endlessly, it's going to blow either way.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    130. Re:Doing it wrong? by david_thornley · · Score: 1

      If you're working with cache constraints, recursion might be better than iteration. In different circumstances, different techniques can be better.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    131. Re:Doing it wrong? by david_thornley · · Score: 1

      Overall, it's generally impossible to say that, of two reasonable approaches to programming, one is always better. (It is possible to do this with unreasonable approaches to programming, such as generating random programs until one passes the acceptance test.)

      Abstractions can leak when they're used in unusual ways. As Joel Spolsky put it, TCP is an abstraction that makes it possible to maintain a continuous lossless two-way connection - until you find that the reason it isn't working is that your pet snake chewed through the Ethernet cable. At that point, you have to disregard abstraction of the hardware layer. Even in a world with snakes, though, it's almost always better to use TCP facilities when appropriate than to go to the bare metal.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    132. Re:Doing it wrong? by david_thornley · · Score: 1

      There are ways to avoid trees decaying into linked lists. As long as you have to treat it as a tree, though, you need to keep a stack, and a manually controlled stack can blow stack space itself.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    133. Re: Doing it wrong? by david_thornley · · Score: 1

      This is why recursion should be forbidden: People don't even think about it or don't have a clue.

      Eliminate every programming construct that careless people can misuse, and you've got nothing left.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    134. Re: Doing it wrong? by ShanghaiBill · · Score: 1

      I'd rather have very bad effects in my embedded code than small and subtle effects that can stay hidden for a long time, but still have the potential to screw up the application.

      That is the point. If you implement a recursive function to walk a tree, it will work fine as long as the tree is somewhat balanced ... and if random data is inserted, a tree will almost always be balanced. Almost. But not always. So one day, the tree is not balanced, and your recursion overflows the stack, trashing the very call chain that you need to figure out what went wrong. That can be a subtle bug that is hard to track down.

      There are several ways to avoid (or at least detect) this problem:
      1. Count the depth, and increment each time you recurse.
      2. Put a sentinel like "0xDEADBEAF" near the bottom of the stack space, and check it.
      3. During development, use a much smaller stack than in deployment. If your deployment will have a 2K stack, then use 1K in development. This will expose a lot of fragile algorithms.
      4. At each level of recursion, avoid storing unnecessary data in each stack frame. Instead, try to store data in static variables. For instance a depth counter does not need to be passed to a subfunction. It can be a static variable that is incremented when the subfunction is called, and decremented when it returns.
      So instead of this:

      void
      foo(int depth)
      {
            foo(depth + 1);
      }

      Do this:

      static int depth;
      void foo()
      {
          ++depth;
          foo();
          --depth;
      }

    135. Re:Doing it wrong? by david_thornley · · Score: 1

      If we're talking about an inherent recursive algorithm (tree traversal is an obvious example), we have to maintain a manual stack. Go through your earlier questions and ask them about the manual stack.

      As far as adding a 2MB array, I have a suggestion: test your code before you check it in.

      Also, problems you don't know a solution to may in fact have solutions, although you may not realize this due to Dunning-Kruger.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    136. Re: Doing it wrong? by jbolden · · Score: 1, Interesting

      The ones who use it a lot. I'd say most. Most use recursion schemes: maps, folds, catamorphism... to guarantee they are using tail calls.

    137. Re: Doing it wrong? by ShanghaiBill · · Score: 1

      C will not do that

      All modern C compilers will detect and optimize tail recursion. It is a very easy optimization to do, and is often a big win.

      So as always, you should understand your language and your compiler.

      Yes, you should.

    138. Re: Doing it wrong? by jbolden · · Score: 0

      Well the obvious ones: Common Lisp, Rabbits, Schemes... to modern languages like ML, F#, Haskell the domain in which recursion is far and away the most common looping pattern.

    139. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      Not everything needs to scale. Running through a list of elements and performing a quick transform doesn't exactly require CUDA. There is a place for these constructs in many instances and it's the programmer's job to keep it straight.

    140. Re:Doing it wrong? by david_thornley · · Score: 1

      The number one reason not to use recursion is because it is very easy to exhaust the stack in system with more limited memory like embedded systems.

      If the algorithm is recursive, it probably requires you to maintain a stack if you don't use recursion. If the algorithm gets into unlimited recursion, it will blow either way. If you're working in tight embedded systems, you probably can't afford to make a stack without hard limits on it anyway, and again it doesn't matter (except that you can probably make the special-purpose stack take less memory than recursion).

      The next most important reason to not use recursion is because it is slower....Recursion uses more memory.

      Computers tend to be bigger and more powerful than we actually need, and sacrificing raw efficiency for things like readability, maintainability, etc., is completely standard in most cases. Modern software tends to be sufficiently complex that it would never get written without compromises like that.

      Recursion is a maintenance nightmare.

      Let's assume we have a binary tree with nodes like struct node { datapackage stuff; struct node * left, right; }

      where "datapackage" is a struct or class type. Now, for in-order traversal:
      void traverse (struct node * n) {
      if (left) traverse(left);
      process(stuff);
      if (right) traverse (right);
      }

      Now tell me how difficult this is to maintain. Now, write code to do the in-order traversal without using recursion and tell me how easy that is to comprehend at a glance.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    141. Re: Doing it wrong? by ShanghaiBill · · Score: 2

      There are languages that do not optimise tail-recursion, such as C .

      All modern C compilers optimize tail-recursion.

      computing the sum of the elements of a large array is efficiently done with a for-loop, whereas recursion would use excessive stack space.

      Only a total idiot would use recursion to sum an array. There are many other tasks, such as searching a tree, where a recursive algorithm makes much more sense.

      Anything that can be done iteratively, can be done recursively

      Anything that can be built with a hammer can be built with a rock.

    142. Re:Doing it wrong? by Anonymous Coward · · Score: 0

      Question of degree. Limited recursion is fine, crazy-deep recursion and you're going to run out of stack. No-one is saying that you should avoid all recursion - or at least not that I'm aware of - but keep in mind how deep the recursion is and how it might grow when you're code gets deployed in the wild.

      (learned this the hard way: when I was at uni recursion was actively encouraged as good style and the downside was never mentioned).

    143. Re:Doing it wrong? by ShanghaiBill · · Score: 3, Funny

      In the book "C Traps and Pitfalls", on page 146 of the index it says "recursion 88, 146".
      The index also contains “pitfalls, see traps” and “traps, see pitfalls.”

    144. Re: Doing it wrong? by religionofpeas · · Score: 1

      or 5. Use an algorithm that keeps the trees (mostly) balanced.

    145. Re: Doing it wrong? by Thanatiel · · Score: 1

      Don't forget that the recursion will most likely save some register context you have no control of plus the call return address.
      Plus calling is not free.

      That being said, I find the drawback acceptable in most cases.
      If optimization is required, there is always time to do a more suitable implementation later.

      --
      Irrelevant news and morons using moderation to mod down what they disagree on. 2018 resolution: so long.
    146. Re: Doing it wrong? by allo · · Score: 1

      > you run out of stack pretty quickly
      Maybe in python. Other programming languages allow you to use a large stack, if you need to. And this isn't a bad thing. It may be a bad thing in python, because the call stack has overhead, but in C it is no bad thing.

    147. Re: Doing it wrong? by allo · · Score: 2

      Most modern C compilers, given certain constraints about return values.

    148. Re: Doing it wrong? by allo · · Score: 2

      Nope. You need to get the computer scientists point of view: Have a termination condition. And this is usually NOT a counter, but a condition, which needs to be fulfilled. i.e. you visited every node of a tree. This takes 1 mio steps? Yep, then it does. Your counter is arbitrary and/or hard to calculate and some measure for ppl who don't trust their code to have the right condition. Which is made easier by recursion, because functions tend to be more understable, as they are similiar to their math equivalents.

      The only thing to keep in mind: Don't recalculate values. Things like adding fib(n) and fib(n+1) shouldn't Take 2n+1 steps.

    149. Re: Doing it wrong? by allo · · Score: 1

      Tail OPTIMIZATION means, that your compiler moves the recursive call to the end, not you. You may do, because it often adds clarity, though.

    150. Re:Doing it wrong? by istartedi · · Score: 1

      It depends on the language. In Lisp dialects, it's practically required and IIRC compliant Scheme requires tail-call optimization so that it doesn't cause performance issues. My experience in C is that people prefer iteration. One time I did it in assembly and the professor marked me down, but I think it had to do more with combining self-modifying code *and* recursion. Dang, it was compact code though. You might even say it was elegant; but I get the lesson he was teaching and I would never do that now.

      --
      For all intensive purposes, "whom" is no longer a word. That begs the question, "who cares"?
    151. Re: Doing it wrong? by tepples · · Score: 2

      Who runs out of stack space on modern desktop computer platforms anyway unless you messed up your break condition or you've made very, VERY large data structures?

      People programming in languages that do not offer tail recursion optimization. For example, Guido van Rossum decided explicitly to exclude tail recursion optimization from Python because it would make the output from functions in the traceback module less clear.

    152. Re: Doing it wrong? by SharpFang · · Score: 1

      Try to process data in a tree structure without recursion. Say, scan all files in a directory tree for a string.

      Recursive approach:
      - iterate over every file and directory in current directory
      - if file, scan. If found, return the find, or add it to the list of found files.
      - if directory, open and restart self recursively with that directory as new root.

      Now if you want to do this iteratively, you're most likely to duplicate the recursive algorithm, except turning all the neat recursive calls the compiler normally makes for you into a hand-crafted monstrosity of storing current state on custom stacks.

      --
      45 5F E1 04 22 CA 29 C4 93 3F 95 05 2B 79 2A B2
    153. Re: Doing it wrong? by Z00L00K · · Score: 1

      Have fun with the linked directories in *Nix then... "ln /usr/local /usr/local/work/local"

      --
      If builders built buildings the way programmers wrote programs, then the first woodpecker would destroy civilization.
    154. Re:Doing it wrong? by Anonymous Coward · · Score: 0

      I think the problem with recursion is if you use it for an open-ended sequence which can cause a stack overflow. Of course that gets filtered through Junior Blogger's busy hands and comes out as "don't use recursion."

    155. Re: Doing it wrong? by PoopJuggler · · Score: 1

      It's not difficult at all. You just push nodes into a queue instead of using the system stack. Every iteration on the queue processes that set and possibly adds more nodes to the queue. Rinse and repeat. Recursion is a terrible solution to that problem because you've just limited the size of the trees that you can process.

    156. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      I don't remember when I saw recursion the last time in production code, likely decades ago, and you care about the raw cases where a manually written loop is "better" than recursion ... wow.

      You don't work with tree and graphs? They are almost always easier to code recursively

    157. Re: Doing it wrong? by PoopJuggler · · Score: 1

      or you've made very, VERY large data structures

      Why do you think that's such an anomaly?

    158. Re: Doing it wrong? by allo · · Score: 4, Insightful

      That's a termination condition: If you ever visit a node, which was visited before, stop.

      You do not follow the symlink 1000 times and then abort. You follow it one time and the next time you see a mark "followed it" and stop. Without error as successful termination of a directory traversal.

      You think such a link would be an invalid condition, but it is actually not. And it isn't even a special case to the algorithm, which has the invariant "always take a node, which wasn't visisted yet until there are no such nodes".

    159. Re: Doing it wrong? by PoopJuggler · · Score: 1

      Just have a good exit criteria to avoid too deep recursions

      You've just crippled your processing ability.

    160. Re: Doing it wrong? by PoopJuggler · · Score: 1

      Or just don't use recursion

    161. Re: Doing it wrong? by Darinbob · · Score: 1

      It's undesirable only if you assume it scales. If you just call the same function a second time, then it's perfectly acceptable. It's no different than any other function call in that regard. Also note that all functional language programs are essentially highly recursive if written according to the language's style. Coming out and saying essentially "don't use this feature because there is a possibility of it being abused" means we can't use any computer language.

    162. Re: Doing it wrong? by Darinbob · · Score: 4, Funny

      There are people who think such things are beyond the ken of mortal man. Mere programmers should use libraries and only the gods themselves write the libraries.

    163. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      > That's a termination condition: If you ever visit a node, which was visited before, stop.

      You want me to compare every node I visit to every node I've already visited? That sounds like a recipe for combinatorial explosion.

    164. Re: Doing it wrong? by Darinbob · · Score: 1

      Gcc 4.8.4 does put the return address on the stack for everything but a leaf function.

    165. Re: Doing it wrong? by PoopJuggler · · Score: 1

      That's fine if it suits your needs, but to write robust and reusable code you avoid imposing limits like that if possible. Remember Y2K?

    166. Re: Doing it wrong? by Darinbob · · Score: 1

      Very often the amount of storage space used by a loop is as much or even more than using the stack. If you've got the stack space, then use it. Less memory used, less code space, less chance of leaked memory. I'm saying this as someone who works on very tiny systems. But too many programmers are stuck with superstitious nonsense, they refuse to use recursion because they heard it was bad but then go and make a huge array to do the same thing with a loop, or they refuse to use GOTO because it makes you go blind but they'll happily use break, return, throw, etc. They'll go and double the code size and make a confusing unmaintainable mess just to avoid some rule of thumb they heard once in school. Yes, the rules of thumb are very good things to follow, but they are not strict taboos they are meant to teach novices to beware of coding horrors like Fortran computed goto spaghetti code.

    167. Re:Doing it wrong? by tepples · · Score: 1

      However some language like JavaScript really don't give you much of an option. Such as a lack of a sleep command

      Of course there's a sleep command.

      setTimeout(function() { /* what to do after sleeping */ }, time_in_ms);

    168. Re: Doing it wrong? by Darinbob · · Score: 1

      If each call of a recursive function requires storage (state variables) then it will use a roughly similar amount of memory storage. Sometimes people avoiding recursion use MORE memory overall as they grab dynamically allocated memory from a heap which has a lot more overhead. Very often recursive programs with the right amount of stack space are smaller and faster than the non-recursive workaround.

      If you're on a unix like system, then you can assume your stack is very large, and the OS will allocate or free a new page when necessary, so these often work better than allocating a huge array. Sure, fibonacci in a loop will be more efficient (in C like languages, but in Scheme or Haskell it's more efficient recursively). But a tree walking or graph traversal function is very hard to make as efficient without recursion, and those types of problems are very common.

      (I've seen some people link all the nodes in a tree together with forwards/backwards links to avoid recursion even though it is harder to maintain and does not save memory, it's one of those silly tricks that sounds good at first but turns out to be something people will curse at when they try to debug it a few years down the road)

    169. Re: Doing it wrong? by Darinbob · · Score: 1

      A topic often overlooked by the average web programmer.

    170. Re: Doing it wrong? by Darinbob · · Score: 1

      Recursion does not lock you into depth-first traversal. What was your grade in algorithms class?

    171. Re: Doing it wrong? by Darinbob · · Score: 1

      Yes, those are more advanced algorithms. Sometimes you are forced to abandon the first readily elegant solution. But there are often other elegant solutions to investigate. Sorting algorithms for example, on mainframes most of the data would be on mag tapes and the RAM could not hold all that much, so you couldn't use quicksort or heapsort or most certainly not merge sort. But there are other types of sort and if you had a better sort for mainframes then you could make a ton of money (and they did).

    172. Re: Doing it wrong? by Darinbob · · Score: 1

      It also means that when you're using functional programming that the programmer with experience knows how to revise the loop to enable the optimization. It's one way you can spot the novice Scheme programmer.

    173. Re: Doing it wrong? by Darinbob · · Score: 1

      And yet it gets used in embedded systems with limited stack. Not arbitrary depth recursion of course. But calling the same function twice (with intervening fucntions) is often a convenient and efficient way to do some operations. Ie, start operation, go down a few calls, determine that some storage needs re-arranging before being able to continue, then recursively restart the original function (often optimized away with tail call optimization. I have seen code reviewer gag at that because they're afraid that recursion will go out of control despite the very obvious exit conditions that prove it won't, and they propose a complicated solution that doesn't save any additional memory. (generally the EE people freak out at recursion)

    174. Re: Doing it wrong? by Howitzer86 · · Score: 1

      So... if I can do it does that make me a master programmer? Recursion is great. I used it most recently for binary search. Yeah there's probably a library for that, but I had fun. I can also do heap sort.

      Can I work for Google now?

    175. Re: Doing it wrong? by Darinbob · · Score: 1

      I've seen cases where people follow their rules of thumb too rigidly. Ie, put all memory into pools, no exceptions. But then there's a case where I only need some temporary storage to live cross a couple functions, and there is absolutely without a doubt not enough memory if everything is pre-allocated during init. So I use the very tiny seldom used heap for this purpose, allocating the memory only for the duration of the operation. At which point someone complains that I should use a global buffer instead or malloc once only during init. Not because they thought about the issues and debated the various design choices, but because it was a knee jerk response to violating the "use memory pools" guideline.

    176. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      I don't remember when I saw recursion the last time in production code, likely decades ago, and you care about the raw cases where a manually written loop is "better" than recursion ... wow.

      That's because you do not use F#, OCAML, Haskell, Lisp, ...

    177. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      How do you walk the tree? If you stop on a previously visited node then there is no way to explore a sibling branch. That may not matter for the specific algorithm you are implementing, but you suggestion does not work for all applications.

    178. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      That happens when.people stop reading Kuth and get their education from YouTube.

      Indeed, this is the source of all evil.

    179. Re: Doing it wrong? by Lodragandraoidh · · Score: 1

      It's not a simple as that. If you are on a team of developers who are building applications on top of clearly defined APIs, all the heavy lifting from a systems perspective should already be done for you. This is to ensure the company doesn't end up with 15 different versions of the same code in each release that needs to be maintained in the future. I think mostly it comes down to the bottom line: a business doesn't want to spend money on building the same library over and over again.

      There are instances when low level systems programming is needed, and whoever is assigned that task should have the freedom to do what is needed to ensure the systems provided can perform at the desired level and provided whatever is necessary for security and so on. There is nothing canned that can do that, so you better have your best developers on that given the potential impacts to your customers and therefore to your bottom line.

      If you work for yourself - then do what you want since you're calling the shots.

      Policy choice is relative to your business risk/exposure. Ultimately whatever you choose to do with your own programming (if you work for yourself or you're just a hobbyist) will be proved out by your clients/users when they use (break) your software and systems. On the other hand, if you work for someone else as an employee, then you are bound to follow their rules, regardless of your views. You can try to change it, or you can find another job elsewhere.

      It's not simply a matter of these things being beyond anyone's ability, but it is also true that there are different levels of skills and experience that exist in a business environment. A good choice would be to partner your systems developer with your brightest applications developer to cross pollinate. Unfortunately, my experience also suggests that many companies don't do a good job of mentoring and growing talent within the company. People get assigned to silos and languish unless explicitly transfered to the group with a different focus. It really comes down to the philosophy of your employer.

      --

      Lodragan Draoidh
      The more you explain it, the more I don't understand it. - Mark Twain
    180. Re: Doing it wrong? by AmiMoJo · · Score: 1

      Can you describe a practical application of this where you couldn't just do the checks to see if the storage re-arranging first, or in a separate function that can then be re-called non-recursively? I can't think of one but I'm intrigued.

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

      Yes, IF you screw up. If you have very clear and unambiguous exit conditions then you don't screw up. The code is very clear, and yet a code reviewer may say "what if we run out of stack?" even though I proved it isn't a problem.

      I see the same thing with loops - programmer insists we must have a loop time out, even if it's reading hardware and the only reason for the loop is to handle clock syncing across domains, and the watchdog is active to handle the case of broken hardware.

    182. Re: Doing it wrong? by Lodragandraoidh · · Score: 1

      I think the real issue here is 'access to' versus 'elimination'.

      If you are your own boss, or you are a hobbyist, then this question is irrelevant. You can and should have access to every capability - it is up to you to manage based upon your own capabilities.

      In a business with a gaggle of programmers that is evolving over time, it is a different story. In that situation, you have developers of all different skill levels potentially, coming into and leaving the business if you are growing, and you have to take into consideration the risks associated with allowing poor code to impact your paying customers. In that case, I think it would make sense to create access limits for different programmers based upon their skill levels and areas of responsibility. You could also cross train and provide options for people without this access to prove they can be trusted to get higher level access to more of the 'shoot yourself in the foot' tools/constructs - which would expand your cadre without risking your business in the process.

      --

      Lodragan Draoidh
      The more you explain it, the more I don't understand it. - Mark Twain
    183. Re:Doing it wrong? by Anonymous Coward · · Score: 0

      Thanks for that!

    184. Re: Doing it wrong? by phantomfive · · Score: 4, Informative

      Most c compilers. Take this program: #include

      int recurse(int x) {
      if(x<=0) return 42;
      return recurse(x - 1);
      }

      int main() {
      return printf("%d\n", recurse(6502));
      }
      Then we compile it, adding -S so we can look at the assembly output:
      $ clang -S -O3 test.c The compiler recognizes that the printf() call is a tail call, and uses a jmp (which places nothing on the stack in x86), but it also recognizes that recurse() evaluates to a constant and returns that. I was going to post the assembly output for you to look at, but Slashdot said it had too many junk characters.

      There is a lot to complain about in terms of efficiency in clang and gcc, but tail recursion is a well-understood problem with a lot of research behind it, and they both do it well.

      --
      "First they came for the slanderers and i said nothing."
    185. Re: Doing it wrong? by ShanghaiBill · · Score: 2

      Or just don't use recursion

      A non-recursive algorithm to walk a tree structure still requires memory space proportional to the maximum depth of the tree, and still requires more memory for an unbalanced tree. You may need less memory than a call stack, since you don't need to store the instruction pointer or stack index pointer (BP register on an x86), but that is only a linear improvement.

    186. Re: Doing it wrong? by phantomfive · · Score: 1

      Searching through a tree is O(lg n), and that's how much space you're going to take on the stack, too. So, if you have a 1k stack (extremely small), and each function call places 10 bytes on the stack, then you're going to be able to search through 2^100 items in your binary tree before running out of stack in your search. If you have that many objects, you can probably afford to increase your stack size a bit.

      --
      "First they came for the slanderers and i said nothing."
    187. Re: Doing it wrong? by phantomfive · · Score: 1

      That sort of situation comes up, but in that case a B-tree is more appropriate. See also this comment. And this comment.

      --
      "First they came for the slanderers and i said nothing."
    188. Re: Doing it wrong? by allo · · Score: 2

      A tree has nodes and leafs. A leaf is where the algorithm terminates. A node has children, which can be followed.
      A search visits each node once, where links between nodes may alter when a node is visited first. When you visit a node, you mark it as visited and add the children (and links) to a queue or stack (depths first / breath first search).
      I do not see any need to visit a node twice, as you get no new information on the second visit.

    189. Re: Doing it wrong? by allo · · Score: 1

      Only if you don't know your data structures.

    190. Re: Doing it wrong? by Darinbob · · Score: 1

      Not easily without pulling out proprietary code, and I forget the details. Of course, things CAN be redesigned to avoid it. In this case it seemed more straight forward to just recursively call an earlier function in the call chain (exceptions with unwinding were not available and I think it would have helped in that situation). And it was known that the stack was ok with this case (it had just called a function with even more stack depth requirement). Nothing wrong with it except for the magic word "recursion".

    191. Re: Doing it wrong? by Megol · · Score: 1

      Most algorithms using recursion can use tail call optimizations, those that can't can be divided into those that would need temporary storage anyway and those that "wastes" space. An experienced programmer should be able to manage that.

      BTW why do you think that emulating recursion with a manually managed stack (or other storage) is any better? Because that's how one do many things non-recursively...

    192. Re: Doing it wrong? by Megol · · Score: 1

      So you don't use the hardware managed stack but create a software managed stack... You write unnecessary code with worse performance and claim that is better? If your trees overflow your stack then maybe you should use an OS that supports growing stacks?

    193. Re: Doing it wrong? by Megol · · Score: 1

      PNG?!? Get with the times dude - WebP is the cool thing!

    194. Re: Doing it wrong? by Megol · · Score: 1

      Of course, given a Turing machine one can port the algorithm to that too. But emulating a stack is still using a stack even if only on a higher level of abstraction.

    195. Re: Doing it wrong? by Darinbob · · Score: 1

      Embedded systems with a small chip. The default RTOS from the chip maker is often too large, the generic ones are inefficient, etc. For instance we have a demo board from a chip maker, we used their SDK to get things going and are now trying to clean stuff up. We ran out of code space already because their SDK used a nano-libc, brought in floating point, brought in a very bulky printf+console, etc. Writing out own drastically reduces memory usage. We can also use their registers directly and adapt the code into our style of device driver rather than using the somewhat bulky method that the chip maker had in their SDK. We also have to add details that most chip makers don't have in their libraries (low power states).

      Also when you're in control of the chip from reset until it gets to main(), you have to know the details of the runtime libary, especially if using C++.

      Silos can be a drawback. You often want to have an employee follow a project over its life. If you've got one guy only doing board bring up, then it gets tossed over the fence to application people, you often find a disconnect between competing needs. For example, the drivers used during testing mgiht not be the same drivers used in production which can lead to some subtle problems. Hhaving dealt with a hardware group that tosses boards over the walls and then scrubs their hands of it ("software can make a workaround for all problems") this is a major problem. This doesn't mean that everyone need to know everything, but it would be nice if everyone knew at least two things, or three even. In an *interview* you're going to be asked about things outside of the comfort zone for sure.

    196. Re:Doing it wrong? by jenningsthecat · · Score: 1

      Thanks for the clarification. I see the point and the value of working with the abstraction, instead of second-guessing its design and creating a non-standard, less well tested, and possibly less modular / portable substitute. I guess what I was questioning was not being able to see and understand the inner workings.

      --
      'The Economy' is a giant Ponzi scheme whose most pitiable suckers are the youngest among us and the yet-unborn.
    197. Re:Doing it wrong? by Megol · · Score: 1

      I'll just post the facts for Intel skylake, throughput (sustained in ideal case) and operations.

      push immediate
      push reg
      - 1/clock, 1 fused op (will execute as one store address + one store data operation)
      push mem
      - 1/clock, 2 fused ops (load + store address + store data)
      pop reg
      - 2/clock, 1 op (load)
      pop mem
      - 1/clock, 2 fused ops (load (stack), store address + store data)

      Compare this with the load/store operations of x86:

      mov [mem], reg
      - 1/clk, 1 fused op (store address + store data)
      mov reg, [mem]
      - 2/clk, 1 op (load)

      Push/pop instructions are small. They also (in all recent x86 processors) have a "free" stack pointer update that don't serialize dependent push/pop instructions (there will be overheads when manipulating the stack pointer though as that is done in the OoO execution stage while the update logic is done in the front end of the pipeline). The memory MOV instructions can use different address modes subset of [segment:basereg+indexreg*scale+offset] but are larger.
      I'll have to mention that x86 also support memory operands for most instructions (e.g. ADD reg, [mem]; SUB [mem], reg) however that doesn't change the general conclusion.

      In short stack operations are fast on mainstream processors. Tail call optimization is an optimization, just as a good compiler optimizes some kinds of complex loops it is another tool. But the main advantage of it isn't performance, it is avoiding blowing up the stack in a way that is unnecessary.

    198. Re: Doing it wrong? by K.+S.+Kyosuke · · Score: 1

      Chances are that if you can do that easily, you should have done it in the first place, and if you can't, there was a reason for that.

      If the first thing that comes to mind when thinking about how to implement a recursive algorithm without using compile time function stack isn't using some type stack then you really don't know what you're talking about. Go back to Computer Science class.

      Wow. No sequitur much? :-p Pray tell, how is that "easier" (or more natural)? Hey, two can play this fun game of yours: If the first thing that comes to mind when thinking about how to implement a recursive algorithm is to avoid the compiler's activation record stack and use some hand-crafted solution of yours, then you really don't know what you're talking about. Go back to Computer Science class.

      Anyway, my computer science class taught me that the one case for this when I need to replace the compiler-generated stack with something of my own is 1) when I have a non-deterministic program mapped onto some kind of interleaved execution or a program with complicated control flow transfers and 2) I don't have built-in continuations handy and/or the implementation doesn't use a programmer-manipulatable spaghetti stack.

      --
      Ezekiel 23:20
    199. Re: Doing it wrong? by K.+S.+Kyosuke · · Score: 1

      I'd be careful, however, with mentioning Common Lisp as one of the examples in that sentence, in case that the scope of the end of the sentence stretches to the beginning. While Lisps are generally recursion-friendly, Common Lisp is more of an ultimate imperative language: It has both a wide support for both basic (DOTIMES) and advanced (DO, DO*, LOOP) structured loops, and the ability to define new ones (such as ITERATE). CL is definitely not the first association that comes to my mind when a "give me examples of pervasive recursion" situation arises.

      --
      Ezekiel 23:20
    200. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      You can't do recursive acronyms non-recursively

    201. Re: Doing it wrong? by jbolden · · Score: 1

      Quite true but CL has tail recursions which was the questions. Schemes were more academic / functional in their feel.

    202. Re: Doing it wrong? by K.+S.+Kyosuke · · Score: 1

      Even in this case, a mere search can probably run in O(1) bounded stack space. Do you need the upper nodes after you're finished with the lower ones? If not, then tail-call.

      --
      Ezekiel 23:20
    203. Re: Doing it wrong? by K.+S.+Kyosuke · · Score: 1

      Perhaps a more correct claim would be that some CL implementations compile tail calls efficiently under some circumstances, while the language spec either doesn't say anything on that matter or implies that tail calls are not performed. It's not really better than what GCC does in terms of things you can rely on. It turns out that proper tail calls are necessary for the reason that when they're not guaranteed, some major expectations about program execution don't hold and one can't use them for these things at all. (It's similar to the DELAY/FORCE problem with some kinds of infinite streams in R5RS Scheme that was solved by adding a third operator in a SRFI.)

      --
      Ezekiel 23:20
    204. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      Arguing about recursion is pointless unless you include both the languages and domains you're talking about. For some languages, there is limited stack space and you can blow that far faster than if the same amount of data was stored in the heap. For these languages, you should never use recursion on user-based data because you can never be 100% sure that it'll always fit in memory under every operating case. Of course most developers don't care about stability so they'll just go ahead and use recursion anyway.

    205. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      Recursion can be good but can also easily be misused. Remember when the toyotas were getting the throttle stuck and killing people? The official cause was because they used recursion improperly and the computer would crash, locking the throttle motor in place (full throttle or otherwise)

    206. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      You suck. Going back to the roots is in now. Next Year's trend is assembly and after that you have to write in Binary. You are not supposed to do ifs and loops.

      Ten years from now we will all need to wire the vacuum tubes manually.

      You need to go retro!

    207. Re: Doing it wrong? by Pseudonym · · Score: 1

      All the Scheme and Haskell programmers. Every single one of them.

      --
      sub f{($f)=@_;print"$f(q{$f});";}f(q{sub f{($f)=@_;print"$f(q{$f});";}f});
    208. Re: Doing it wrong? by Pseudonym · · Score: 2

      I don't remember when I saw recursion the last time in production code, [...]

      See, I've worked in compilers, and software that has compiler-like components (e.g. input languages which resembles programming languages in some way) for a long time, and I see recursion all the time.

      Recursion is all over production code, you just don't work in those spaces.

      --
      sub f{($f)=@_;print"$f(q{$f});";}f(q{sub f{($f)=@_;print"$f(q{$f});";}f});
    209. Re: Doing it wrong? by Pseudonym · · Score: 1

      Recursion is undesirable because it doesn't scale - you run out of stack pretty quickly. There isn't really ever any need for recursion anyway as there's nothing you can do recursively that you can't do non-recursively.

      I once spent a week (a week) writing a non-recursive implementation of Tarjan's strongly connected components algorithm for precisely this reason. It was one of the most painful things I've ever done. (Before you ask: No, we could not use the "normal" iterative algorithm. The graph was too big for that.)

      You can do anything non-recursively, just like you can do anything in COBOL. But a lot of the time, you'd just be simulating the recursion stack anyway. Compilers are much better at this sort of thing than you are and have a lower hourly rate.

      --
      sub f{($f)=@_;print"$f(q{$f});";}f(q{sub f{($f)=@_;print"$f(q{$f});";}f});
    210. Re: Doing it wrong? by Pseudonym · · Score: 1

      Most modern C++ compilers can't because of all those modern C++ programmers who use RAII everywhere

      --
      sub f{($f)=@_;print"$f(q{$f});";}f(q{sub f{($f)=@_;print"$f(q{$f});";}f});
    211. Re: Doing it wrong? by Pseudonym · · Score: 1

      I would be willing to bet money that you don't need to compile any languages or diff any files or traverse any graphs on that CPU, though.

      --
      sub f{($f)=@_;print"$f(q{$f});";}f(q{sub f{($f)=@_;print"$f(q{$f});";}f});
    212. Re: Doing it wrong? by Wuhao · · Score: 1

      I don't believe that's true at all. The Y2K bug was an example of a problem that was foreseeable in the requirements of the program. Scientists in 1980 actually predicted that the year 2000 might happen in as little as 20 years.

      But if I have a problem where the upper bound on the number of calls to my recursive function that is much lower than the very large number of calls it would take to actually run out the stack, then there's no point in worrying about a stack overflow that is simply never going to happen. I'm not gonna buy 50 pounds of steak for a dinner party where I only invited 8 people.

    213. Re: Doing it wrong? by Pseudonym · · Score: 1

      Every recursion can be expressed as a loop or nested loops.

      Especially if you have a stack data structure too.

      --
      sub f{($f)=@_;print"$f(q{$f});";}f(q{sub f{($f)=@_;print"$f(q{$f});";}f});
    214. Re: Doing it wrong? by Pseudonym · · Score: 1

      I'm not sure what you mean when you say "you run out of stack pretty quickly."

      It depends what you're doing, as always.

      For many recursive algorithms (e.g. diff, balanced binary tree traversal, quicksort), unless you implement them stupidly, the maximum recursion depth is within a constant factor of the logarithm of the size of the problem. If the problem size is N, you will never have a call stack more than O(log N) calls deep. On a 64-bit machine, a 64-level-deep call stack is nothing. Hell, Mozilla or Unity 3D probably go 64 function calls deep on every key press.

      For other recursive algorithms (e.g. any graph algorithm based on depth-first search), the maximum recursion depth could be the size of the problem no matter what you do. If the problem size is N, a recursive algorithm might give you a call graph O(N) calls deep. That's not nothing, especially since stacks are typically smaller than they used to be because of multithreading.

      --
      sub f{($f)=@_;print"$f(q{$f});";}f(q{sub f{($f)=@_;print"$f(q{$f});";}f});
    215. Re: Doing it wrong? by Pseudonym · · Score: 1

      Of course you can. You just figure out maximum recursion depth, and then check if there's enough stack space.

      Your mission, should you choose to accept it, is to figure out the maximum recursion depth for Tarjan's strongly connected components algorithm given an arbitrary directed graph. It must be more efficient than just running the algorithm.

      --
      sub f{($f)=@_;print"$f(q{$f});";}f(q{sub f{($f)=@_;print"$f(q{$f});";}f});
    216. Re: Doing it wrong? by Pseudonym · · Score: 1

      Recursion can be good but can also easily be misused.

      I'm trying to think of a tool in the programmer's toolbox that this isn't true of, and I'm drawing a blank.

      --
      sub f{($f)=@_;print"$f(q{$f});";}f(q{sub f{($f)=@_;print"$f(q{$f});";}f});
    217. Re:Doing it wrong? by SeriousTube · · Score: 1

      It seems like the logical thing to use if for instance, you want to print the name of all of the files on a hard drive.

    218. Re: Doing it wrong? by pimproot · · Score: 1

      Are you sure you haven't seen any production code calling library or STL functions that are recursive? There are a lot of them out there.

    219. Re: Doing it wrong? by flux · · Score: 1

      My algorithm class was just fine. But just for sake of discussion, please convert this depth-first binary tree iteration to breadth-first:

              void visit(Node* node)
              {
                  if (!node) return;
                  printf("%d\n", node->value);
                  visit(node->left);
                  visit(node->right);
              }

    220. Re: Doing it wrong? by flargleblarg · · Score: 1

      *Every* embedded software design standard expressly forbids recursion

      My embedded software design standard doesn't.

      Thank you. GP is a fucking moron. As you go on to point out, many algorithms have natural limits on the recursion depth. A recursive mergesort, for example, can never go deeper than ceil(log2(n)) calls, where n is the number of elements to sort. If you have room on your stack for 30 calls deep, you can sort a list of a billion items. People who say recursion has no place in embedded software design either haven't thought their arguments through very carefully, or are very inexperienced programmers, or are just plain dumb.

    221. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      If my recursion is log(n) then processing some 10 billion item tree will only take a few kilobytes of stack per thread. (it goes down slightly per thread you do)

    222. Re:Doing it wrong? by Tough+Love · · Score: 1

      GOTO/GOSUB on the other hand have no practical use anymore

      Beg to differ. In C/C++ if you need to break out of a loop from inside a switch statement your choices are: add an extra variable that obfuscates your code; otherwise obfuscate your code with organizational contortions; use an ugly but obvious goto. Another common use case for goto is, taking error handling out of line so it doesn't obfuscate the main algorithm. And here is one you will probably never run into given your rather limited "real programmer" perspective: implementing state transition networks. Very elegant with goto, the topology is exactly like the state transition diagram that you are hopefully using for reference.

      --
      When all you have is a hammer, every problem starts to look like a thumb.
    223. Re:Doing it wrong? by Tough+Love · · Score: 1

      It's possible to write any traversal algorithm using loops, without any recursion.

      If your algorithm pushes values onto a stack and modifies its control flow according to what it pops off the stack then it is still recursion. You meant "without native recursion". In general, arbitrary recursive data structures are impossible to traverse without recursion. For some theoretical background, look here.

      --
      When all you have is a hammer, every problem starts to look like a thumb.
    224. Re:Doing it wrong? by Tough+Love · · Score: 1

      if that requires building your own stack, you haven't really gained anything.

      True in many cases, however if you are sure of the maximum recursion depth than you may be better off allocating your stack on the stack. Also, not all recursion is about traversing trees. The fastest parsers are written iteratively, and have the ability to examine more than one stack level to make a decision. Examining data in caller stack frames using native recursion is not pretty at all.

      --
      When all you have is a hammer, every problem starts to look like a thumb.
    225. Re: Doing it wrong? by Darinbob · · Score: 1

      A few ways to do it. Not the easiest but they exist.
      - use an array based tree, which you would see a lot in early algorithm papers or books for languages without pointers. Ie, Node n's children are at 2n+1 and 2n+2. Yes it's cheezy.
      - use a counter of the depth you are at; print all nodes at depth 1, then all at depth 2, and so forth. Cheezy too and it's O(n^2).
      - add an extra queue, this is a common approach. If each node already has a next pointer then it's straight forward, but slightly cheezy as it assumes extra storage beyond the stack.
      - Use a functional language (where there isn't a "stack" per se), and there are some advanced algorithms. But hard to convert to C or Python style.

    226. Re:Doing it wrong? by Anonymous Coward · · Score: 0

      If you're following MISRA-C rules, you're totally not supposed to use recursion. For a very good reason.

    227. Re: Doing it wrong? by flux · · Score: 1

      Yes, there are of course ways to do it as you can always convert an iteration to recursion. But, it's pretty much pointless unless you're working with a pure language. If you're going to use a queue, why not just iterate?

      In particular, a version that collects a queue is easily parametrized to work breadth first, depth first, or some alternative strategy.

              enum Mode { DepthFirst, BreadthFirst };

              void visit(Node* root, Mode mode)
              {
                      std::list work { root };
                      while (work.size()) {
                          Node* node = work.front();
                          work.pop_front();
                          if (node) {
                              printf("%d\n", node->value);
                              switch (mode) {
                              case DepthFirst: {
                                  nodes.push_front(node->left);
                                  nodes.push_front(node->right);
                              } break;
                              case BreadthFirst: {
                                  nodes.push_back(node->left);
                                  nodes.push_back(node->right);
                              } break;
                              }
                          }
                      }
              }

    228. Re:Doing it wrong? by jellomizer · · Score: 1

      Yes but that forces you to run a function. If you need to sleep in a loop then you need to change your function to be recursive

      --
      If something is so important that you feel the need to post it on the internet... It probably isn't that important.
    229. Re: Doing it wrong? by dolmen.fr · · Score: 1

      So "no recursion" is a strict rule for your environment.
      That's doesn't make it a general rule for programming.

    230. Re: Doing it wrong? by angel'o'sphere · · Score: 1

      You mean recursion inside of the compiler, right?

      That is not what we call "production code", even if it is strictly speaking production code.
      And: that code you usually don't see anyway. Unless someone is working in crafting compilers, like you :D

      My argument was not "against recursion" but for recursion as basically all arguments against it are either wrong, missleading or in appropriated. Perhaps you did not see my other posts.

      --
      Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
    231. Re: Doing it wrong? by Pseudonym · · Score: 1

      That is not what we call "production code", even if it is strictly speaking production code.

      Haha, well, the person who wrote the query optimiser in your database server would probably differ with that opinion... That was my job a long time ago.

      Perhaps you did not see my other posts.

      Of course. This is Slashdot.

      --
      sub f{($f)=@_;print"$f(q{$f});";}f(q{sub f{($f)=@_;print"$f(q{$f});";}f});
    232. Re:Doing it wrong? by dolmen.fr · · Score: 1

      Unless you write code directly in assembly, the stack is far from what you "the hardware stack".

      A recursive algorithm use the function call stack and the translation of that stack to the CPU stack is dependent on the compiler or the runtime environment. The limits of that stack is also dependent on the runtime environment, and the program may even have control of the size of that stack at runtime to raise the limits if necessary. The OS may also give control to the OS user on the size of that stack (man setrlimit) outside of your program (the program exhausts the stack? run again with a higher "ulimit -s").

      Computer resources (not just the stack) are always limited anyway. Using one algorithm or another is always a tradeoff on which resource you may exhaust first. The stack size is not always the first exhausted resource for a recursive algorithm. So "Never use recursion" should not be general rule.

      Unrolling a recursive algorithm to loops also has a cost: the code is often longer (in lines of code) and more complex (because you have to maintain the state that is handled in the stack in the recursive case), so may be harder to maintain and may have more bugs. You'll often have to write unit tests that compare the correctness of the unrolled implementation against the (simpler) recursive one.

    233. Re:Doing it wrong? by Anonymous Coward · · Score: 0

      Recursion limits your traversal through the graph to depth first search if I'm not mistaken.

      I am obviously mistaken.

    234. Re: Doing it wrong? by angel'o'sphere · · Score: 1

      Calling a library function probably yes, but that a programmer wrote a recursive function, can't remember that.
      OTOH, I'm not hunting for stuff like this.
      In other words: if I have not seen one, it does not mean there are none. It only means I did not run over it through code reviews or debugging etc.

      --
      Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
    235. Re:Doing it wrong? by dolmen.fr · · Score: 1

      There is no generic answer to this question. And that's why also there is no generic answer to the question "should I use a recursive function".
      As a programmer that's your responsibility to use the right tool for the job.

    236. Re: Doing it wrong? by jeremyp · · Score: 1

      In these cases, if you use loops, you're going to be making up all the stuff recursion is good for, and you're going to be maintaining your own stacks. There's no advantage to doing this rather than using recursion.

      Yes there is. If you use your own stacks, you have visibility over when the stack space is going to run out. It will also have a smaller memory footprint than recursing using the system stack since each stack frame has to contain the return address and the link pointer for the previous stack frame, as well as space to save local variables.

      I'm not advocating avoiding recursion but there are advantages to not using it when you expect a lot of levels of recursion.

      --
      All I want is a secure system where it's easy to do anything I want. Is that too much to ask ~~ Randall Munroe
    237. Re:Doing it wrong? by joboss · · Score: 1

      Perhaps they want you to just use a stack. It can be cheaper.

    238. Re:Doing it wrong? by holophrastic · · Score: 1

      I'm also stunned to see recursion in the list, but I can certainly agree that I almost-completely stopped using it about a decade ago.

      Now that we're discussing it, I can see why. Adding new functionality or debugging or even tracing recursive code is annoying. Like any really magical regular expression (which often gets executed recursively!) good recursion is tight-code that really blocks out a lot of diagnostics. For example, it's really annoying to dump your structure mid-recursion and understand what's happened and what's still to happen.

      It would seem that I replaced most of my recursion with task queues -- which basically just flattens recursion into iteration -- so each subtask can be done incrementally, making tracing and adding subtasks natural efforts.

      I'm in the business-application world, business-logic is rarely recursive because human tasks are rarely recursive. I'm sure it's different in a more science-application world.

    239. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      hint: "call" followed by "ret" can be replaced with "jmp".

    240. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      The thing is, embedded c is more like assembler with squiggly braces. There can be a zillion other restrictions too, like not being able to use floats or static variables being readonly.

    241. Re: Doing it wrong? by david_thornley · · Score: 1

      Hey, I was congratulating myself for not writing "GIFs at 11". Thing about getting with the times is that it never stops, I guess.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    242. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      there's nothing you can do recursively that you can't do non-recursively.

      While true, it's bit of a brain-twister to eg. write a generic n-level nested loop without recursion. Now, add a subtle bug to your manual stack-handling there and let your friend debug it.

    243. Re: Doing it wrong? by petervandervos · · Score: 1

      Also embedded software engineer and don't like to use dynamic memory allocation.

      The only time to use recursion is when I have to print (to serial or something) a number in binary form and you can not use printf because your system is to small.

    244. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      Stack frame allocation costs exactly: nothing.

      How the fuck does this get modded up?

      Implement the same algorithm using loops and again using recursion. Which one will run much faster?

      Hint: Not recursion.

      Fucking moron.

      The advantage of recursion over loops is that is massively simplifies the code. What could take 1000 lines in a loop version might take 15 with recursion.

      Not all recursion can be optimized like that and fewer languages support it.

    245. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      "software engineer" is a bullshit term.

      There is no engineering to be found in the software field.

    246. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      Dumbass, 99% of the times it is predictible

    247. Re:Doing it wrong? by Anonymous Coward · · Score: 0

      You can easily use recursion for any type of search on a tree or graph. It is a simple matter of rearranging code.

      Morons

    248. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      What exactly is engineering, in your view?

    249. Re:Doing it wrong? by Anonymous Coward · · Score: 0

      I have implemented O(n!) algorithms and never got a stack overflow.

      Yes, I could have done it iteratively, but it would have required 50x amount of code, a stack in the heap and would have been impossible to debug and maintain.

      Instead I just wrote 20 lines of clear and simple code. But, go ahead and be stupid and spend a week when it took me 15 minutes.

      With good strategy, those algorithms run pretty quickly.

      It is called being educated something that 99.9% of "programmers" lack.

    250. Re: Doing it wrong? by JoeDuncan · · Score: 1

      it doesn't scale - you run out of stack pretty quickly

      LOL - Clearly you skipped out on the "Algorithms 101" lecture on "Tail Recursion"!!!

    251. Re:Doing it wrong? by geoskd · · Score: 1

      Computers tend to be bigger and more powerful than we actually need, and sacrificing raw efficiency for things like readability, maintainability, etc., is completely standard in most cases.

      That is absolutely not true. The difference between a 50 mips processsor and a 100 mips processor is about $0.50. If you are shipping a million units a year, that is half a million dollars a year you just wasted. I've worked places where co-workers were fired for wasting less money. I get paid *very* good money because I don't waste money. That "processor power is cheap" mentality is the reason why I have a desktop CPU that is 75x faster than the one I had 15 years ago, and everything runs *slower* today than ever as measured in the time it takes to perform basic tasks. Programmers need to get it through their heads that CPU cycles cost money, and wasting other peoples money is not a good way to run a business and by extension produce code for one. Some small degree of waste is acceptable, but wasting cycles by using a programming construct that is not as good, for reasons touching on ignorance is simply unacceptable, especially when there are any number of standards groups that have condemned recursion.

      --
      I wish I had a good sig, but all the good ones are copyrighted
    252. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      That's a toy program though. There's a lot of ways to screw up so that your recursive function is not eligible for tail recursion optimization.

      You should avoid recursion when you can imho. It can be ok to use it for tree traversing and such, but you should still take precautions to make sure that you terminate if you recurse too much/deep.

      I've seen several examples where a programmer wrote a recursive function that sufficed then, but the data it recursed over increased over the years until stack space was exhausted or the code was reused somewhere where it had recurse deeper and just blew the stack.

      Or maybe I'm wrong and Gcc and/or Clang has actually improved quite a lot the last couple of years in this regard, I wouldn't bet money on it though.

    253. Re: Doing it wrong? by phantomfive · · Score: 1

      That's a toy program though. There's a lot of ways to screw up so that your recursive function is not eligible for tail recursion optimization.

      Show a program that screws it up, then.

      You should avoid recursion when you can imho.

      That's a really dumb rule, tbh. Make recursion your friend, get good at it, and then you won't be afraid of it anymore.

      --
      "First they came for the slanderers and i said nothing."
    254. Re: Doing it wrong? by spongman · · Score: 1

      if you're running out of stack on a 64-bit machine, then your OS's addressing scheme sucks.

      "8.1 exabytes should be enough for anyone" -- Bill Gates

    255. Re:Doing it wrong? by tender-matser · · Score: 1

      On newer browsers, you can sleep in a loop, or more generally, "return" from an asynchronous API.
      All you have to do is to wrap your code in a generator.

      function sleep(f, ms){ setTimeout(j=>f.next(), ms) }
      function wget(f, url){
              fetch(url).then(r => r.ok ? r.text().then(t => f.next(t)) : f.next())
      }
      var frame = function*(){
              for(var url in url_list){
                      code...
                      var text = yield wget(frame, url);
                      more code...
                      yield sleep(frame, 500);
                      more code...
              }
      }(); frame.next()

      It's a pity they managed to make it so awkward -- I don't understand why they have to take simple concepts from scheme or smalltalk and wrap them in obtuse abstractions (generators, iterators, factories, whatever).

    256. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      In particular, every problem whose solution requires recursion will recursive calls which cannot be tail-call optimised.
      (However, sometimes performance can increase when you do fake recursion, keeping all state in one frame or on the heap.)

    257. Re:Doing it wrong? by syntotic · · Score: 1

      Pardon me but: 1) GOTO is IRREPLACEABLE in the original BASIC; 2) GOTO is deemed harmful because it makes some compiler emission code and optimizations inefficient; 3) exception handling provides a GOTO mechanism where it was most useful, ie, bailing out of deep code unable to continue; and 4) following GOTO is less stylistically elegant and much less aesthetic MOST OF THE TIME than a full fledged deep branching-looping algorithm, including the mostly arbitrary goto tags, which usually go better into comments. Those are the reasons why GOTO is better avoided and why it is still included in parsing. I have used code twice to completely bail out of a complex algorithm in the meanwhile while I could come out of the mind boggling effort of producing the same code with branch exhaustion. Only temporarily to make ends meet, waiting for a further optimization effort, or for the other case, to test deep branches before engaging in code clutter by programming other deeply inner branches and calculating their foldings to become a one-time-pass algorithm. As for recursion... the problem with recursion is that you relinquish control of the execution stack to the language compilation and maybe OS support, so you DO lose control of your process while it is recursing. IT is more than OK for functions you know will execute short, like in Fibonacci you know will not be called beyond the tenth level. I have counted 200 recursions start becoming problematic, for instance... But the solution is simple, just implement recursion using your own pair of stacks, which can be encapsulated in a nice recursion class framework for total transparency.

    258. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      Who the fuck wrote the libraries, elves?

      Numbnuts

    259. Re: Doing it wrong? by mcswell · · Score: 1

      I used it all the time in Prolog, it's really the only way to program in that language.

      Oh, yeah, I guess that was nearly two decades ago... Time flies when I'm having fun.

    260. Re: Doing it wrong? by mcswell · · Score: 1

      That's true of a tree, but it's not necessarily true of a Direct Acyclic Graph (DAG). In particular, it's not true of a DAG which is not a tree.

    261. Re: Doing it wrong? by mcswell · · Score: 1

      Smart compiler. What does it do to a program that calculates 64 (say) digits of pi?

    262. Re: Doing it wrong? by phantomfive · · Score: 1

      Don't know, do you have some sample source code I can try compiling?

      --
      "First they came for the slanderers and i said nothing."
    263. Re: Doing it wrong? by mcswell · · Score: 1

      It's sort of a joke. A *very* smart compiler would look at the code, determine that it was trying to calculate the digits of pi, and perform the optimization: substitute the value of pi to the requisite number of digits, calculated (if need be) at compile time. I'm sure I saw that somewhere, but a quick search didn't turn anything up. Just this:

      "Never put off until run time what you can do at compile time."

      - David Gries, in "Compiler Construction for Digital Computers", circa 1969.

    264. Re: Doing it wrong? by allo · · Score: 1

      Hmm, i think of the following algorithm:

      add a root node to a queue
      get an element from the queue
      when you visited the element, stop
      else process the element and add all linked elements to the queue
      mark all graph links (child directorys and symlinks) as visisted.

      complexity of a directory traversal O(n log n) where n is the tree depth
      complexity of "is marked": We use a tree. insertion is O(log m), lookup is O(log m) for the number of graph edges.
      The total complexity is then O(n log n + n log m) (which is another way to express n*log(max(n,m))), which is for normal directory structures (number of links proportional to number of directories) O(n log n)

      did i forget something in this algorithm? I did not test it, yet ;-).

    265. Re:Doing it wrong? by jellomizer · · Score: 1

      Still it is a recursive sleep algorithm just kinda hacked to give functionality of a normal sleep command.

      --
      If something is so important that you feel the need to post it on the internet... It probably isn't that important.
    266. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      Then you are doing it wrong. :)

      There are two kinds of recursion: Tail recursion and the more general non-tail recursive kind.

      Tail recursion is when you just return the result of the recursion and do no further computation on it in the function. Best example for this is searching in a binary tree. For the inner nodes you check if you need to go left or right, call the right node recursively and return the result. Tail recursion is basically just a goto to the start of the function and most compilers will compile it as such. Which also means the start space allocated for the first call of the function gets reused for the recursion and there is no limit to it.

      Non-tail recursion on the other hand needs to preserve the functions stack space and allocate a new stack frame for the next call. Because when that returns it needs to continue running the function. That is where things can go bad, as in don't scale. Still, in most languages you can easily do 1000-10000 recursions without any problem.

      And then there is Python. In Python recursion kills you before you can say "ups". In python recursion is so hated It doesn't even recognise tail recursion.

    267. Re: Doing it wrong? by Anonymous Coward · · Score: 0

      Tower of Hanoi is even easier solvable with: Move the smallest disk to the left (starting at the right again when you reached the end) or clockwise for a round setup of pegs. Then move any other disk.

      But overall I have to agree. loops, goto, recursion they are all universal. You can write any of them in form of the other. It's a matter of taste and how you see the problem that dictates what is best. And a matter of how stupid your compiler is (Python? recursion? are you insane? :)

    268. Re:Doing it wrong? by Anonymous Coward · · Score: 0

      How come? That does not recurse, unless you consider the example loop a kind of recursion. The yield statement is basically splitting a function into two (before and after), and returning from the former. A subsequent call to generator.next() will simply call the second (after) function, not recurse into the first.

      If the frame.next() calls are confusing you, go google for the new async/await keywords, which are more user friendly, but offer no new functionality (you still cannot simpy save the current continuation and then call back into it, as you can do in eg scheme).

    269. Re: Doing it wrong? by psmears · · Score: 1

      A non-recursive algorithm to walk a tree structure still requires memory space proportional to the maximum depth of the tree,

      Not always, no. For example, if the nodes in the tree all have a reference to their "parent" nodes (which they may already have for other reasons), you can traverse the tree in O(1) space. That doesn't help if the nodes don't have parent references (adding them would increase the size of the tree by O(n) which is usually much bigger than O(max depth)), but if the tree is sorted (as it typically is) you can find the parent of a node in O(1) space, albeit in O(max depth) time.

  2. Recursion is dead! by Anonymous Coward · · Score: 0

    Recursion is forgotten? More like essential, if you want to write readable code for some things like traversal. Multiple inheritance is also nowhere near the evil that Sun wanted you to think it was when they designed Java. Eval can be necessary in some shitty systems or circumstances, but we all know that it's naughty and should expect the spanking if we try to use it.

    But goto...? It's 2017, if your coworker inserts a goto into your codebase you should just resign now. If you're using gotos yourself then you might be more cut out for manual labor.

    1. Re:Recursion is dead! by Anonymous Coward · · Score: 0

      Depends on their usage of goto. Just like the example shown I find using goto's when used exclusively for error handling to jump to a function exit as a perfectly acceptable way to treat error handling and much preferred over either giant if nests or ridiculous refactoring. Of course i also only think its acceptable in languages without other forms of exception handlers, but in something like C it makes code much easier to follow.

      However using it to jump backwards, or make loops, or basically any other usage, yea, those should be stricken

    2. Re:Recursion is dead! by j_kenpo · · Score: 1

      I use JMP's if I'm messing around on some old micros, does that count?

    3. Re:Recursion is dead! by MichaelSmith · · Score: 1

      How is goto return better than just return?

    4. Re:Recursion is dead! by Anonymous Coward · · Score: 1

      IMHO just for cleanliness, and can help with debug later. It allows you to have a single exit point to a function, so in that case if you want extra debug/logging/whatever as to why its exiting at that point you can add it right in the goto instead of having to go to every return statement. Even though your most likely going to have logging at those error points anyway it provides one central location if you need to debug something

    5. Re:Recursion is dead! by Anonymous Coward · · Score: 3, Informative

      Also forgot to add to this, memory cleanup is another big one. Instead of having to free in every single possible 'if error return' block you can have it always do a check and free in the goto

    6. Re:Recursion is dead! by Anonymous Coward · · Score: 0

      How is goto return better than just return?

      It avoids memory and other resource leaks.

    7. Re:Recursion is dead! by Anonymous Coward · · Score: 4, Interesting

      History lesson.

      https://en.wikipedia.org/wiki/Considered_harmful

      GOTO considered harmful, raised out of a generation of BASIC programmers that knew only too well that they were horrible to deal with. Early micros had RENUM so you could move line numbers around and attempt to preserve GOTOs. They were awful, but only on 8-bit micros.

      Later C used them in local jump structures using LABEL: which wasn't even remotely as bad as BASIC. Everyone is allergic to GOTO from BASIC so the whole idea got canned along with it - baby out with the bath water. This is why we say "GOTO considered harmful, considered harmful". The idea that a code construct is so repulsive that we've condemned it to never be used again.

      GOTO is useful. Certain forms of C exception handling code benefit from GOTO immensely. They make the code both more readable and more performant. Unfortunately we can't submit this code because in a code review...."GOTO considered harmful" circa 1990. Brainless dogma has won over thought. I've seen generations of programmers that would never consider GOTO to be a valid keyword. They won't consider it on the basis of a decades-old argument that was meant for a different language in a different age. As much as I might be right I won't pass a code review, so I don't use it.

    8. Re:Recursion is dead! by Anonymous Coward · · Score: 0

      Yes, GOTO can be used badly, but declaring GOTO to be evil i s just ridiculous.

      "Switch" is just another way of saying "If . . . then goto"

      And any code, regardless of language gets turned into machine code eventually and it's filled with JMP instructions. Lots and lots of JMP instructions. Which is just another form of GOTO.

    9. Re:Recursion is dead! by _merlin · · Score: 1

      People seem happy to hate on goto while using other things that are goto in all but name (break, continue, return, throw). Throw/catch is particularly useful as a non-local goto in places where you want to catch some kind of condition (usually an error) that can be detected in lots of places. C++ RAII eliminates most of the need for local gotos though - you can make local classes with destructors for cleanup, with the added benefit that it's exception-safe.

    10. Re:Recursion is dead! by vux984 · · Score: 2, Insightful

      How is goto return better than just return?

      In C in particular, which is the ONLY place I'll use goto... i might have a pattern like something like...


      {
      a = malloc(something)
      if malloc failed goto e1
      b = malloc(something2)
      if malloc failed goto e2
      c = malloc(onemorething)
      if malloc failed goto e3 ...some code...
      open a file... if error happened goto e3 ...some code...
      some other error happened goto e3 ...some code... /*cleanup*/
      e3:
      free (a)
      e2:
      free(b)
      e3:
      return;
      }

      The goto sequence cleanly handles the memory free. Obviously you wouldn't want to just return after the 3rd malloc failed.

    11. Re:Recursion is dead! by sjames · · Score: 3, Informative

      It gives you a chance to unwind something (like taking a lock) before the return.

    12. Re:Recursion is dead! by Anonymous Coward · · Score: 0

      The errors in this code snippet seem to demonstrate the dangers of using GOTO.

    13. Re:Recursion is dead! by MichaelSmith · · Score: 1

      char *a = NULL;
      a = malloc(something);
      if (a) free(a);

      and so on.

    14. Re:Recursion is dead! by Anonymous Coward · · Score: 0

      That's only if you are going to a section of code that unwinds that.

    15. Re:Recursion is dead! by Dutch+Gun · · Score: 1

      Gotos in C are like operator overloading in C++. It's a handy mechanism when used judiciously, in very specific circumstances. If GOTO is abused, used to jump all over the place (which it can literally do), yeah, of course it's bad. But then again, you can always name a function:

      int AddTwoNumbers(int x, int y);

      when it actually multiplies two numbers. Does this mean named functions are bad, because they could be misused? Why would you purposefully abuse the language like that?

      Generally speaking, the rule of thumb with GOTO seems to be to use it in exceptional circumstances, such as error handling. I don't see anything wrong with that. Honestly, it would be better if there were a more specific and constrained mechanism for doing that, but you use the tools you have.

      --
      Irony: Agile development has too much intertia to be abandoned now.
    16. Re:Recursion is dead! by johannesg · · Score: 4, Interesting

      Just like Linus, you seem to fail to understand the problem. Dijkstra argued against *unstructured* jumping around, since this made programs very hard to understand (look up some source from that era to get an idea of what he was arguing against. It wasn't just a single goto here or there, it was 'using goto for everything we now use structured constructs for, like loops, switch-statements, etc.). Dijkstra argued for replacing those goto's with structured jumps as much as possible. And guess what? By and large, the software world has done so, and become much better for it.

      I very much doubt he meant for his statement to become dogma in the way it has, and he certainly wasn't arguing for the complete removal of all forms of flow control, structured or not (as you and Linus seem to think). Goto, like everything else, is a tool. It has its place. You should not use it if a better tool is available, but you should also feel free to use it if it is the best you have. And the fact that assembly _only_ has goto is immaterial. The whole point is to allow reasoning over the language in the language itself.

      Dijkstra always struck me as a sensible, practical man. He wrote about an argument he had about driving printers. In his era, printers could only accept a character once every so often (because they were slow, mechanical beasts, without much in the way of buffering), so his colleagues wanted to intersperse printing code with other processing. Dijkstra didn't like this, and wanted to print using an interrupt that would signal when the printer needed a new character. His colleagues fought against that: not only were interrupts more costly than just interleaving printer output with normal code, but Dijkstra was 'throwing away' valuable information about printer timing that could be used to improve efficiency!

      His colleagues were, of course, completely right - right up until the moment when the hardware changed, and their programs no longer worked, that is...

    17. Re:Recursion is dead! by vux984 · · Score: 2

      The point is that you have several mallocs to deal with, and more than one error condition (not just failing the malloc itself).

      So if you make 3 mallocs, and then there is an error opening the file... you still have to free all 3 mallocs.

      the use of 3 if(x) free(x) instead of multiple goto labels is fine, but you still need goto to get to the cleanup block from the various error points.

    18. Re:Recursion is dead! by vux984 · · Score: 1

      lol. on the upside it won't compile so no one will ever suffer them. :p

    19. Re:Recursion is dead! by james_gnz · · Score: 1

      GOTO is useful. Certain forms of C exception handling code benefit from GOTO immensely.

      Yes, goto is useful for exception handling, in languages that lack specific exception handling constructs, but have goto. This is a good reason to use goto in such languages, but I think it ultimately points to a deficiency in the language, rather than an argument in favour of goto as a language construct.

      IMHO, to argue for goto as a language construct, it is not enough to argue that there are a small number of specific well-defined ways in which it is reasonable to use goto in languages that lack control-flow constructs for particular purposes. This would better support an argument for the availability of suitable constructs for these purposes. Ultimately, to argue for goto as a language construct, I think it would be necessary to claim that is reasonable to use goto in ways that defy classification. AFAIK, this claim is seldom made.

    20. Re:Recursion is dead! by Reemi · · Score: 1

      > I very much doubt he meant for his statement to become dogma in the way it has

      The original title Dijkstra gave his paper is 'A Case Against the Goto Statement'. It was a CACM editor who came up with the Considered Harmful version.

    21. Re:Recursion is dead! by Spazmania · · Score: 0

      Goto is bad. That C could use a "finally" construct which runs upon reaching "return" does not make Goto less bad.

      --
      Moderating "-1, Disagree" is simple censorship. Have the guts to post your opinion.
    22. Re:Recursion is dead! by _merlin · · Score: 1

      You've missed my point. The people I have a problem with are people who will avoid a goto at all costs, even doing things like this so they can say they didn't use a goto:

      do { ...
              if (exit_cond) break; ...
      } while (0);

      I really have seen that done in a popular piece of open source software. If a goto really is the cleanest way to achieve what you need to do, then just use a goto. Don't write code that does a goto while using some convoluted means to avoid the goto keyword.

      That said, in C++ there are many situations where you can do better than use a goto. For example cleaning up on error is better done with destructors as it will be exception-safe, and exceptions provide a structured goto that only lets you jump out, but lets you do so across multiple frames.

    23. Re:Recursion is dead! by Anonymous Coward · · Score: 4, Insightful

      You should read "GOTO considered harmful" before you bash it.

      "Most programmers have heard the adage "Never use goto statements", but few of today's computer science students have the benefit of the historical context in which Dijkstra made his declaration against them. Modern programming dogma has embraced the myth that the goto statement is evil, but it is enlightening to read the original tract and realize that this dogmatic belief entirely misses the point."
      http://david.tribble.com/text/...

      In the bad old days, all you had was goto, and every program looked like spaghetti. Now that we have if...then...else, loops, switch-case statements,
      goto should only be used as a last resort (and every use should be justified). I've been a professional programmer for twenty years; last year I used goto *twice*.

      And never forget https://xkcd.com/292/

    24. Re:Recursion is dead! by Anonymous Coward · · Score: 0

      Why is 'goto' bad, then?

    25. Re:Recursion is dead! by Anonymous Coward · · Score: 0

      > in languages that lack specific exception handling constructs

      No, not just there. In quite a few cases it would be "in languages that lack efficient exception handling constructs". And that's almost all of them.
      You can't/shouldn't use exceptions to handle cases that occur regularly, while goto is quite fine for that. I.e. unless it is really exceptional, you should NOT use a finally block, but instead goto - if you have to.
      The "if you have to" is critical though.
      Manual resource management is usually the reason for needing "finally" or "goto".
      In C++ you just as much as possibly wrap every resource into a on-stack object (which you have to do anyway to not leak them in case of exceptions), and then your "goto" can be just a "return" instead.
      In Java (C# etc. as well I believe), they also added language features to handle this issue (memory is already handled, but files etc need it).

    26. Re:Recursion is dead! by Anonymous Coward · · Score: 0

      This is exactly how to NOT do it.
      You should have a single code block that handles ALL cleanup, if you have a different jump target for each state you have a unmaintainable mess that is just barely better than an explicit cleanup before each return (someone changing the order of things, adding a early free etc all break it, when the idea is to make cleanup robust against unrelated code changes).
      And for all those people writing "if (a) free(a);": Please stop living in the 1980s, everyone managed to implement free() correctly nowadays so that free(NULL) works the way the standard says.

    27. Re:Recursion is dead! by Dunbal · · Score: 1

      Try writing an assembly language program without using jump.... what is that, if not goto? Elevating the non use of GOTO to the level of a religion is just as crazy as any other religion. There's a right way and a wrong way to use it, just like there's a right way and a wrong way to use a pair of scissors. Safety scissors are smart in pre-school but an adult is expected to use regular scissors without killing themselves. Is your programming at infant or adult level?

      --
      Seven puppies were harmed during the making of this post.
    28. Re:Recursion is dead! by thegarbz · · Score: 1

      Goto is bad.

      Goto is bad for people who can't code and people who can't read code. To consider a construct bad is to not understand it.

    29. Re:Recursion is dead! by fisted · · Score: 2


      {
      char *a = NULL, *b = NULL, *c = NULL;
      FILE *f = NULL;

      if (!(a = malloc(something)))
          goto fail;
      if (!(b = malloc(something)))
          goto fail;
      if (!(c = malloc(something)))
          goto fail;

      if (!fopen(f))
              goto fail;

      some code

      return 0;

      fail:
      if (f)
              fclose(f);
      free(c);
      free(b);
      free(a);
      return -1;
      }

      FTFY. mkay?

    30. Re:Recursion is dead! by Anonymous Coward · · Score: 0

      Goto is useful even in languages with exception handling.
      Exceptions isn't really a good way to deal with errors. It encourages grouping several errors together with a single error handling routine for all of them.
      That is one of the reasons exceptions are frown upon in embedded and/or safety critical applications.

    31. Re:Recursion is dead! by rkww · · Score: 1

      yeah except you've got e3 twice so it wouldn't even compile

    32. Re:Recursion is dead! by jenningsthecat · · Score: 1

      Depends on their usage of goto... using it to jump backwards, or make loops, or basically any other usage, yea, those should be stricken

      So does that mean in C it's safe to use goto so long as I make sure I don't purposely or accidentally create recursion with it? ;-)

      --
      'The Economy' is a giant Ponzi scheme whose most pitiable suckers are the youngest among us and the yet-unborn.
    33. Re:Recursion is dead! by religionofpeas · · Score: 1

      C++ RAII eliminates most of the need for local gotos though - you can make local classes with destructors for cleanup, with the added benefit that it's exception-safe.

      But I wouldn't want throw exceptions in a linux kernel function. It introduces too many things going on behind the curtains that may not be safe in a particular situation.

    34. Re:Recursion is dead! by VernonNemitz · · Score: 1

      While a JMP is equivalent to a goto, keep in mind that conditional loops are a higher-level language construct than what is available to those early processors, which kind of means that JMP/goto had to be used everywhere on those systems. In my personal experience, having written spaghetti code with goto, and also having written vastly less tangled code without it, I'm quite aware of the software-maintenance benefits of avoiding goto whenever it is easy to avoid. But I'm also aware of situations, usually involving getting out from the inside of many nestings of conditions and loops, where goto is clearly the simplest and most elegant way to do that, and I will unhesitatingly use it for that purpose. Those situations are uncommon enough that its use need never be called "excessive".

    35. Re: Recursion is dead! by Anonymous Coward · · Score: 0

      If you malloc a then b, you should free b then a. Also c is a leak.

    36. Re:Recursion is dead! by Anonymous Coward · · Score: 0

      Using a goto (in C, e.g.) is good for error handling but it is very tricky otherwise, I agree.
      The biggest problem, that you rarely see discussed, is scope-jumping. You could "goto" a
      place past a variable's initialization in a code block, and use that variable with less than
      humorous and difficult to debug results.

      But having said that, I askew from religion in my code and use the best, trusted, and robust
      solution I can figure out at the time. OO people hate me; when did programming become a
      weapon and not a tool to a solution to make things easier. I guess my ideals solidified when
      I looked through (early versions) of the source for gcc. I can guarantee that I didn't understand
      20% of what I was looking at, but there were goto's in there. Then I looked at what it did.
      I figure I can bitch about style vs. functionality _after_ I match that achievement (so there's
      only a handful of people in the world who can honestly bitch about those gotos - notice
      their silence, though).

      Just my 2 cents.

      CAP === 'quaking'

    37. Re:Recursion is dead! by Anonymous Coward · · Score: 0

      char *const a = malloc(something);
      if (NULL != a) { /* code block that uses 'a' */
      }
      free(a);

      modern libraries always leave 'a' in a well-defined state.
      At least you didn't cast the return from malloc()!

      CAP === 'bimodal'

    38. Re:Recursion is dead! by Anonymous Coward · · Score: 0

      char *a = NULL;
      char *b = NULL;
      char *c = NULL;
      char *d = NULL;
      a = malloc(something);
      b = malloc(something);
      c = malloc(something);
      d = malloc(something);

      Do some shit here.

      if (d) free(d);
      if (c) free(c);
      if (b) free(b);
      if (a) free(a);

      So what you just put some if (a && b && c && d) around Do some shit here?
      What if it's not malloc? What if more complex steps have to happen in between each of those actions?
      This seems like a terrible idea.

    39. Re:Recursion is dead! by Rockoon · · Score: 1

      Do you understand that you are doing more work at runtime to solve an aversion to a source code construct?

      You understand how fucking dumb that is?

      --
      "His name was James Damore."
    40. Re:Recursion is dead! by lucasnate1 · · Score: 1

      If you are using gcc, you can also use the "cleanup" attribute to achieve something similar. I have a feeling that one day this will become part of the C standard.

    41. Re:Recursion is dead! by angel'o'sphere · · Score: 1

      There are much more errors, like fopen(f) :)

      --
      Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
    42. Re:Recursion is dead! by mysticgoat · · Score: 4, Informative

      I was there.

      Circa 1980, GOTOs in early BASIC and also 6502 Assembly were appropriately used to maximize the limited resources of early desktop computers. A particularly elegant technique on the Apple II was to POKE instruction codes into the keyboard buffer and GOTO it (the Lamb technique IIRC). While the KB buffer was only something like 128 bytes, it was long enough that a GOTO to a computed destination could be built in it and, wowsa, suddenly Applesoft BASIC had a very powerful CASE emulation.

      Naked GOTOs were no longer needed when disk drives replaced tape drives, and RAM grew from 4, 8, or 16 kilobytes to the incredible size of 640 kilobytes. We still used GOTOs that were clothed within Structured Programming constructs (IF-THEN, DO-UNTIL, WHILE-DO, etc) but those were tamed GOTOs. The wild, naked GOTOs became much more rare and good programmers charged with maintaining legacy software would savagely hunt them down and destroy them.

      Meanwhile, Gee-Whiz BASIC (arguably the only really good thing to ever come out of Microsoft) let us replace line numbers with labels and brought about the Business BASIC revolution circa 1985.

      Dijkstra first used the phrase "GOTO considered harmful" in 1968, only 3 years after BASIC was written and about 7 years before BASIC was widely used (the costs associated with moving from Big Iron using centralized card and tape readers to minicomputers with networks of remote terminals slowed BASIC's adoption.) He was talking about FORTRAN and COBOL practices. His work was part of the slowly dawning recognition that it was not sufficient to write a program that solved the problem; that you also had to write it in such a way that you could maintain it or repurpose it next month or next year. That was the dawning of what became known as structured programming practice.

      Bringing this back to the present, using recursion makes a great deal of sense when time to production, long term costs of code maintenance, or repurposing are things that need to be considered.

      Obviously if the code is one-off throw-away, like a tool that will be used in converting the accounting system database from warehouse inventory to just in time purchasing, then maintenance is not a consideration but neither is efficiency. Slap together whatever will work and get on to something else asap; don't take time to rework a recursion into something faster or more robust unless the software breaks on a pre-production trial run. And then look for a quick and dirty fix.

      But if the code is likely to still be in use five years in the future, then write it so the poor bastard whose got to maintain it can understand it as quickly as possible. That could well mean using recursion. The same goes if chunks of the code might be re-used in some other way, say for example taking chunks from an inventory application to build a library system for maintenance manuals.

      Also keep in mind that today's hardware limitations will not apply to tomorrow's problems. It is perfectly acceptable to use a recursion that you know will fail on the 20th iteration if you also are assured that there will never be a need for more than 19 iterations in the next 5 years. In other words, don't waste yourself trying to fix tomorrow's problem, which may no longer be a problem when tomorrow rolls around.

    43. Re:Recursion is dead! by alexo · · Score: 1

      Goto is for quiche eaters. Real men use setjmp/longjmp.

    44. Re:Recursion is dead! by OneSmartFellow · · Score: 1

      goto is for people who can't understand nested code.

    45. Re:Recursion is dead! by Anonymous Coward · · Score: 0

      Let me see if I understand this. If you fail to allocate a, then free a. If you fail to allocate b, then free b, but forget about a. Skip right over its deallocation. Same if c fails - fuck a and b, they stay allocated, but we now return. We don't even deallocate c. Not to mention that the first line, "if you fail to allocate a, then free a" depends on your code being wrong and the first e3 label actually being e1. So , in other words, despite your glaring logical failures and typographical errors, this might actually work to do something nobody would ever want, good job.

    46. Re:Recursion is dead! by TheRaven64 · · Score: 1

      In this example, you get much cleaner code from inverting your if conditions so that they're checking for success, not failure, and the proceed version is inside the next indentation level. You can then cleanly see what failure condition corresponds to which cleanup, in both directions, using the indentation level. Linux developers are allergic to this for two reasons. The first is that they set their tab width to 8 and have an 80-column maximum line width, so code written with this kind of structure quickly runs out of horizontal space. The second is that GCC 1.x generated much better code from the goto version (since 3.0, probably 2.x but I've not actually tested it) it will generate byte-for-byte identical code from both.

      --
      I am TheRaven on Soylent News
    47. Re:Recursion is dead! by TheRaven64 · · Score: 1
      There's a difference between the break and a goto: the break target can only go up an exact number of scoping depths. With goto, you can do horrible things like jump over the declaration of a variable. Consider this code:

      if (b)
      goto x;
      int y = 1;
      x:
      return y;

      Clang and GCC won't even warn when you do this, but if b is true then this code contains undefined behaviour (the initialisation of y is not reached - even though the initialisation is inline with the declaration). In contrast, the standard explicitly prohibits jumping over a declaration in other contexts. If you restructure the above example to use a switch statement to jump over the declaration of y, then you'll see the code rejected at compile time.

      --
      I am TheRaven on Soylent News
    48. Re:Recursion is dead! by colinrichardday · · Score: 1

      Maybe not better than return, but goto might be better for breaking out of deeply nested code.

    49. Re:Recursion is dead! by Spazmania · · Score: 1

      I've been coding in C professionally for a quarter of a century now. I still haven't run in to a situation where I thought, "Wow, that guy's use of goto makes things so much cleaner." Run in to plenty where I thought, "WTF is going on here?"

      Goto breaks the pattern for control flow through a program. When you need to debug the program, goto makes it needlessly hard to figure out how you reached that piece of code.

      And frankly, if you can't write a clean, efficient program without goto, you're not very good at programming.

      --
      Moderating "-1, Disagree" is simple censorship. Have the guts to post your opinion.
    50. Re:Recursion is dead! by Anonymous Coward · · Score: 0

      This wasn't a problem back when you (sensibly) had to declare all your variables before any executable function code...

    51. Re:Recursion is dead! by Anonymous Coward · · Score: 0

      Try writing an assembly language program without using jump.... what is that, if not goto?

      The point is that structured programming is better because it avoids the spaghetti.

      Even assembly adopted support for structured programming via macros, because it can get so bad otherwise.

    52. Re:Recursion is dead! by fahrbot-bot · · Score: 1

      History lesson.

      https://en.wikipedia.org/wiki/Considered_harmful

      Future history lesson: Mostly Harmless

      --
      It must have been something you assimilated. . . .
    53. Re:Recursion is dead! by Anonymous Coward · · Score: 0

      Back in the days when Jesus rode to work on the back of a dinosaur and I was taught programming some of those constructs didn't exist in the language I was being taught to program in.

      So they taught me how to build them correctly using if and gosub .

    54. Re:Recursion is dead! by TheRaven64 · · Score: 1
      You never had this constraint in standard C. You did, until C99, have to declare the variables at the start of a block, but this was still valid C even then:

      if (b)
      goto x;
      {
      int y = 1;
      x:
      return y;
      }

      Even without the corner cases related to declarations, being able to enter a block anywhere other than the start makes reasoning about control flow harder than it needs to be.

      --
      I am TheRaven on Soylent News
    55. Re:Recursion is dead! by Anonymous Coward · · Score: 0

      very good point sir. I never even used it in that context, very interesting.

    56. Re:Recursion is dead! by vux984 · · Score: 1

      Its not really cleaner though if you are doing a lot of operations that check for errors. You could be doing a bunch of file io, for example, and need to check for errors after pretty much every line.

      Nesting 50 levels deep for success checking is not 'cleaner' and it obscures any actual conditional logic and structuring you've got.

    57. Re:Recursion is dead! by david_thornley · · Score: 1

      Memory cleanup is a nonissue in many languages. A lot use GC to dispose of memory, and C++ uses destructors. Putting cleanup code at the end of a function is somewhat fragile, particularly in a language with exceptions.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    58. Re:Recursion is dead! by ChrisMaple · · Score: 1

      There are situations where multiple if(a) free(a); results in cleaner and more compact source code.

      --
      Contribute to civilization: ari.aynrand.org/donate
    59. Re:Recursion is dead! by david_thornley · · Score: 1

      You might want to free your memory and close your open file on success also. Now, if you were using C++ and unique_ptr, everything would automatically be freed and you wouldn't have a memory leak if you add an allocation and don't put the free() in at the end.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    60. Re:Recursion is dead! by ChrisMaple · · Score: 1

      Nested code is for people who can't understand goto.

      --
      Contribute to civilization: ari.aynrand.org/donate
    61. Re:Recursion is dead! by david_thornley · · Score: 1

      In C and C++, "break" usually replaces "goto" for leaving loops, but when you need to break out of multiple loops there's really nothing better than a goto with a nice descriptive target label.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    62. Re:Recursion is dead! by david_thornley · · Score: 1

      One of the reasons I use higher-level languages is that abstracting away the details works a lot better than paying attention to them. If I use a break; in a for loop, I know at a glance what it's doing. If I substitute a "goto", I have to pay attention to the target line. Switches work more like if...else constructs than gotos, unless you're using something like Duff's device.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    63. Re:Recursion is dead! by fisted · · Score: 1

      Sigh.

    64. Re:Recursion is dead! by david_thornley · · Score: 1

      That's twisted. My own instinctive way to do it would be the first ..., then if (!exit_cond) ....There's no reason to use a "goto" here.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    65. Re:Recursion is dead! by ChrisMaple · · Score: 1

      I designed an audio DSP processor that had to always run exactly 1024 instructions and then start again at instruction number 0. There was no jump instruction. Instead, when conditional operation was required, the next N instructions could be prohibited from writing or setting condition codes.

      --
      Contribute to civilization: ari.aynrand.org/donate
    66. Re:Recursion is dead! by Thanatiel · · Score: 1

      Please do not do this.

      Do one allocation of the sum of the 3, taking alignment into account (ie: 8) and divide the allocated block to the relevant objects.

      One NULL test.

      One free.

      I understand you were making a point, but we are speaking about "good ways" and this itches so much I had to reply -_-;;;

      --
      Irrelevant news and morons using moderation to mod down what they disagree on. 2018 resolution: so long.
    67. Re:Recursion is dead! by Anonymous Coward · · Score: 0

      That's about the rate at which I use goto statements. Some years I go without using any. I use them primarily for breaking out of deeply-nested loops where break or return aren't good alternatives. I've rarely used it for other uses, such as cleanup and error handling where exceptions didn't fit well.

      The only other use I can remember was in some parsing code where after it was mostly complete I found a condition where the algorithm had to start over with what it had just encountered. If I'd known from the start that could happen I'd likely have structured the code differently in the first place, but a single goto statement there saved me from possibly hours of reworking the code.

    68. Re:Recursion is dead! by fisted · · Score: 1

      No, I prefer things to be simple and portable.
      Besides, what you're doing is premature optimization, the well-known root of all evil in programming.

    69. Re:Recursion is dead! by Rockoon · · Score: 1

      Translation: Its best at least once! Therefore its always best!

      Both your lack of knowledge and lack of logic skills do not surprise me.

      --
      "His name was James Damore."
    70. Re:Recursion is dead! by vux984 · · Score: 1

      taking alignment into account (ie: 8)

      Full disclosure... I wrote the bug ridden sloppy pseudocode to make a point. Fisted cleaned up pretty nicely into something that essentially did what i was showing in a cleaner way.

      I kind of wish he'd preserved the multiple goto labels but they weren't needed in my example, although there are cases where they would be... where you want specific error handling for certain errors. Here is some hopefully less awful pseudocode.


      {

      /*allocate resources */

      if [allocate resources1] fails goto: errorhandler1
      if [allocate resources2] fails goto: errorhandler2

      /*do something */

      code to do something useful with the resources
      result = 0
      goto:cleanup

      /* error handling */

      errorhandling1:
      do something in response to 1
      result = -1
      goto: cleanup

      errorhandling 2:
      do something in response to 2
      result = -2
      goto: cleanup

      /*cleanup*/

      cleanup:
      if resource1 is allocated free it
      if resource2 is allocated free it

      return result;

      }

    71. Re:Recursion is dead! by james_gnz · · Score: 1

      Yes, goto is useful for exception handling, in languages that lack specific exception handling constructs, but have goto.

      No, not just there. In quite a few cases it would be "in languages that lack efficient exception handling constructs". And that's almost all of them.

      Okay, but I still think this points to a deficiency in the language with regard to error handling constructs, rather than being an argument in favour of goto as a language construct (other than as a stop-gap measure).

    72. Re:Recursion is dead! by fisted · · Score: 1

      I kind of wish he'd preserved the multiple goto labels

      But eliminating those was the whole point of the cleanup. Having to maintain (and get right) the per-failure jump targets is, IMO, more of a mess than just doing the cleanup right away without jumping.

      And if it's just about returning a failure-specific exit code, you could implement that without multiple labels by assigning to a variable before jumping.

    73. Re:Recursion is dead! by Anonymous Coward · · Score: 0

      The problems with GOTO are the reason statements like "switch" were invented. It's not equivalent, it's an abstraction that handles jump complexity for you. I suppose one could create an ISA that has special opcodes for such HLL features, but that just shifts the complexity to the hardware domain.

    74. Re:Recursion is dead! by Anonymous Coward · · Score: 0

      In many yes, not in C, which is still widely used in embedded programming, hence why I started this out by stating in languages that dont have other mechanisms including exceptions. Course that statement got sorta lost in the /. comments

    75. Re:Recursion is dead! by james_gnz · · Score: 1

      Yes, goto is useful for exception handling, in languages that lack specific exception handling constructs, but have goto.

      Goto is useful even in languages with exception handling. Exceptions isn't really a good way to deal with errors. It encourages grouping several errors together with a single error handling routine for all of them. That is one of the reasons exceptions are frown upon in embedded and/or safety critical applications.

      I didn't intend for "exception handling" to mean anything more specific than "some way of dealing with errors". I think the term can be used with this general meaning, although I suppose it is also commonly associated with a specific mechanism. In any case, if the mechanism for dealing with errors in a programming language is broken, I think the best solution would ultimately be to fix it, rather than forever working around the problem.

    76. Re:Recursion is dead! by david_thornley · · Score: 1

      Elevating anything in software development to the level of a religion (except vim over emacs) is as crazy as any other religion. Similarly, saying that a developer should use a language construct where inappropriate because it might be appropriate in another application is crazy. Obviously, you're going to use jumps in assembly code, but you need to examine them to make sure they're doing what they should. In C, most applications of goto should be replaced by appropriate control structures that make it obvious what they're doing and reduce the chance of mistakes.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    77. Re:Recursion is dead! by david_thornley · · Score: 1

      If a is a pointer, if(a) tests a against the null pointer. This is unnecessary because free(NULL) works. It's also deceptive since a non-null pointer doesn't have to point to anything useful, and free(a) doesn't set a to the null pointer. I've seen heavy use of macros in C, where the macro executes free(a);a = NULL;.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    78. Re:Recursion is dead! by michael_wojcik · · Score: 1

      Dijkstra first used the phrase "GOTO considered harmful" in 1968

      Not even then, actually. The title of the letter, as published in CACM, is "Go To Statement Considered Harmful"; and that title was added by the editor. I just skimmed through it again, and unless I missed it, he never even uses the word "harmful".

      He does say that "go to" (boldface in the original) is "too primitive", and refers to its "undesirability" and "disastrous effects" and "(logical) superfluousness".[1]

      But the passive construction "considered harmful" is, just as its most natural interpretation would have it, an indication that someone other than the writer considers it harmful. That someone was Dijkstra; and while he cites others in support of his position, it would have been rather unlike him to step back and crouch behind the passive voice. The man was a first-order curmudgeon, bless 'im.

      [1] Prolepsis: Dijkstra's "(logical)" here is meant to indicate that yes, he is perfectly aware that Von Neumann machines implement all branches with some form of "go to". That it must be available to the machine, and thus will typically be available in assembly language, does not mean it has to appear as an arbitrary branch construct in higher-level languages.

    79. Re:Recursion is dead! by Anonymous Coward · · Score: 0

      You will blow your cache dumbass.

      That is the most fucktarded solution available and you went to it because a lot of stupid fuckers mindlessly hate goto.

      Sure do more work and slow down your program so you can adhere to stupidity.

      Reason #1 why programming is not engineering.

    80. Re:Recursion is dead! by Anonymous Coward · · Score: 0

      "Circa 1980, GOTOs in early BASIC and also 6502 Assembly were appropriately used"

      I've never used GOTO in 6502 Assembly. Maybe I missed that opcode. But I always refused to JMP, because it almost looks like a GOTO, and GOTO is considered harmful, after all. Imagine the folly: just jumping around to some arbitrary memory location! pure evil, for sure.

    81. Re:Recursion is dead! by Anonymous Coward · · Score: 0

      Bullshit

      Goto's are local contructs. Bullshit like throw is not.

      There is more Java or Python spaghetti than C.

    82. Re:Recursion is dead! by Anonymous Coward · · Score: 0

      Should have just used the JNH (Jump Not Harmful) opcode.

  3. Intent by The+Evil+Atheist · · Score: 1

    Just use the one with the more clearer intent, unless it really affects performance.

    Just keep in mind that familiarity is not the same as clarity.

    --
    Those who do not learn from commit history are doomed to regress it.
  4. recursion is "forgotten" now? by Anonymous Coward · · Score: 0

    I seriously do not think I have ever worked on a code base of any significance that did not involve recursion.

    Little toy programs, sure.

    Or you can simulate it with a stack and a loop, but that's just recursion wearing a different hat.

    1. Re:recursion is "forgotten" now? by Anonymous Coward · · Score: 0

      > Or you can simulate it with a stack and a loop, but that's just recursion wearing a different hat.

      A hat that doesn't break you with stack overflows tho

    2. Re:recursion is "forgotten" now? by K.+S.+Kyosuke · · Score: 1

      Because non-hardware stacks on your computer use some special kind of physical or virtual memory that is somehow magically more plentiful than the memory your computer uses for hardware stacks?

      --
      Ezekiel 23:20
  5. Kernels should only be in assembler by Anonymous Coward · · Score: 0

    For the last few years I've been on a crusade. If your operating system's kernel contains anything other than architecture specific assembler, then someone has made a broken abstraction in your operating system and should probably scrap the whole thing. Portable kernels are a real plague in computing these days, it encourages way too much to be lumped into the kernel so that we have fat bloated abstractions that collapse under their own weight when any new concern must be supported.
    A kernel must sit at the lowest level, and provide enough of an abstraction for portable code to run on top but not necessarily provide every imaginable construct or service. What is important to remember is that no bit of high level code is an island, an operating system is a collection of services, libraries and programs that interact. Once you have a base kernel that permits binaries to run more than just the developer's own computer, you have an abstraction. From there you can extend the system, even if the extensions have bits of platform specific code, they primarily interact through the already established platform neutral interfaces and services.

    1. Re:Kernels should only be in assembler by MichaelSmith · · Score: 1

      Well yeah the complex stuff should be in user land, as with Minix. But C is just an assembler language. There can't be may things you need to do in a kernel which can't be done in C.

    2. Re:Kernels should only be in assembler by Anonymous Coward · · Score: 1

      Even if you have code that lives in the same address space as the kernel, it isn't necessarily part of the kernel. An optional set of modules is fine to load in the same address space if your architecture is one of the many that are bad at context switching between user and supervisor modes. Usually it's cache flushing related to page table updates that what burns you.

      C is definitely not assembler language. Maybe it was before ANSI got their hands on it. Most of the core routines that I consider important to kernel development cannot be done very effectively in C. The implementation is often long, tedious and inefficient when done in C. Saving and restoring contexts from an interrupt handler on ARM is a fine example, you need to embed some rather specific instructions to accomplish this. And sadly gcc still has subtle bugs when generating ISR returns if you do something silly like turn optimizations off.

      A small boot loader for a factory diags project took me about 1500 lines of C, but a little under 300 lines of assembler. That should be pretty shocking given that assembler tends to be pretty lengthy. The C had to do a lot of advanced gymnastics that my coworkers had trouble understanding and frequently would break, the assembler is nothing special and is pretty serviceable once there are sufficient comments. But full disclosure, my coworkers didn't bother modifying my assembler version of the boot loader. Because once it gets to a certain point it is able to load arbitrary binary blobs and execute those in a very DOS .COM file like way. The design was patterned more after CP/M than DOS, but on 64-bit ARMv8 instead of 16-bit x86 or 8-bit 8080.

    3. Re:Kernels should only be in assembler by Anonymous Coward · · Score: 0

      > There can't be may things you need to do in a kernel which can't be done in C.

      No fucking flag access fml

    4. Re:Kernels should only be in assembler by jbolden · · Score: 1

      You aren't going to win that debate easily. You are arguing for micro kernels. And of course you are right that micro kernels do allow for extensions much more easily. The problem is that they have notoriously horrible performance for operations that repeat too frequently because the wrapping and unwrapping of calls gets too expensive. Same thing that happens in user code at a high level. Linear efficiency matters. Speeding up every computer on the planet 20% is worth a lot of hassle to OS developers.

    5. Re:Kernels should only be in assembler by religionofpeas · · Score: 1

      The problem with microkernels is not the wrapping and unwrapping of calls, or the cost of switching, or copying memory. The real problem is that different tasks in the microkernel do not have a synchronized view of the system state. As soon as you pass a message where you copy parts of the state, you have two different copies of that state, and as one task changes their copy, the other becomes outdated. Managing all of this becomes more complex than having a big kernel where different tasks share the same memory structures.

    6. Re: Kernels should only be in assembler by MagicMerlin · · Score: 1

      This is an age old debate. It comes down to this: monolithic kernels tend to be faster so they are in common use.

    7. Re: Kernels should only be in assembler by religionofpeas · · Score: 1

      Not only faster, they are also simpler to get right, for everything except trivial cases.

    8. Re:Kernels should only be in assembler by fisted · · Score: 1

      While you're free to want your OS written in assembler, I prefer mine to be written in compiler.

    9. Re:Kernels should only be in assembler by jbolden · · Score: 0

      Excellent point. Either everything has to be fairly stateless (expensive) or there has to be a wrapper for state management. I'm thinking something like STM. Question for you is why not do that? Just pas a reference to the state manager and don't manage state within the modules at all?

    10. Re:Kernels should only be in assembler by ChrisMaple · · Score: 1

      Carry flag. Sign flag. Overflow flag. Zero flag. Fucking flag.
      if(fucking) goto fubar;

      --
      Contribute to civilization: ari.aynrand.org/donate
    11. Re:Kernels should only be in assembler by Anonymous Coward · · Score: 0

      > While you're free to want your OS written in assembler, I prefer mine to be written in compiler.

      You mean compiley language?

    12. Re:Kernels should only be in assembler by david_thornley · · Score: 1

      C is definitely not assembler language. Maybe it was before ANSI got their hands on it.

      The 1989 ANSI standard didn't remove any functionality, but made the language cleaner. If it would be awkward in C89, it would be awkward in K&R C.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
  6. Combining two of them by johnw · · Score: 1

    Not sure about the idea of recursion being forgotten, but I used to work on a system (GEC 4000 series) which had no stack, making recursion slightly more difficult. The neat way of achieving it was by using a goto, back to the beginning of the function.

    1. Re:Combining two of them by Anonymous Coward · · Score: 0

      There exists a similarish hack for clojure: since it is a language for the jvm which has no tail call optimization, an instruction was added called recur, which rebinds function arguments (or loop arguments) and basically gotos to the beginning of the function (or loop).

    2. Re:Combining two of them by Misagon · · Score: 1

      ... which is how compilers use to optimize a recursive function that calls itself at the end.

      --
      "We mustn't be caught by surprise by our own advancing technology" -- Aldous Huxley
    3. Re:Combining two of them by Anonymous Coward · · Score: 0

      I grew up programming on a system that effectively had no recursion (8 bit micro, 80s, had gosub but the stack was so small use was likely to crash the program so mostly you were better off avoiding it). It took me about a year to really "get" recursion when I went to uni - my default mode was to design and implement everything with spaghetti loops, gotos and other tricks that made my uni tutor go amusingly ranty.

      Very occasionally I find myself in positions (eg firmware design) where those creative tricks are extremely useful.

    4. Re:Combining two of them by david_thornley · · Score: 1

      Pascal was originally implemented on a CDC 6600, which had no call stack. (The way to call a subroutine was a Return Jump, which jumped to a particular memory word and wrote a jump back in the word before the subroutine, so the subroutine jumped to its own location - 1 a the end.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
  7. Poor article? by kwerle · · Score: 3, Informative

    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. There is often a way to use a loop that doesn't pile on the stack the way recursion can.

    That said, it doesn't seem like it belongs in this list.

    Frankly, it doesn't seem like a great article. Yup, those things can be misused. Yup, if something can be misused, it will be. I use ruby, so I have access to at least 3/4 of these dark techs. Whatever.

    1. 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?
    2. Re:Poor article? by Anonymous Coward · · Score: 0

      I salute you sir!

      CAP === 'whirls'

    3. Re:Poor article? by Anonymous Coward · · Score: 0

      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.

      Been a long time since college, but isn't this what quicksort does in C++? If the recursion depth gets to large, it bails out to the non-recursive form. I implemented it in my second year (it was a speed competition), but we still got killed because there was only one test case which excerpted this functionality. The people that won the speed competition did it by doing all sorts of low-level optimizations that didn't change the algorithmic complexity, which seemed to defeat the point of an algorithms speed competition.

    4. Re:Poor article? by TheRaven64 · · Score: 4, Informative

      Recursion used to be a lot faster on x86 then non-recursive solutions (to the extent that the Microsoft C++ compiler would turn iterative code into recursive) because stack pushes and pops were a lot cheaper than any other memory addressing mode (and are still single-byte instructions, so have good i-cache usage). On modern x86 chips, there's some fairly complex interaction between store forwarding and register rename logic that makes storing values relative to the stack pointer cheap, but manipulating the stack pointer expensive. Whether an iterative or recursive implementation will be faster depends a lot on the microarchitecture and it's generally not a big enough win to make the code less readable if one form is easier to understand than the other.

      --
      I am TheRaven on Soylent News
    5. Re:Poor article? by Anonymous Coward · · Score: 0

      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.

      I prefer the form "Write code that you can fix on a friday afternoon at 5pm and still be done in time for dinner."
      The wife expects nothing less of me ;-)

    6. Re:Poor article? by Lodragandraoidh · · Score: 1

      What if you get hit by a bus?

      --

      Lodragan Draoidh
      The more you explain it, the more I don't understand it. - Mark Twain
  8. Goto by Anonymous Coward · · Score: 0

    In recursive routines "goto" doesn't increase stack usage because you're not calling the parent function a bunch of times.

    I'm not sure what the issue is here, other than someone's sense of aesthetics --

    This seems like something from Pascal (or a professor) where there "should be" only be one exit point per function (says who??), and every function ends up looking the letter "V" with the point facing to the right (and subsequently runs past the 80th column in your editor).

    What am I missing?

    1. Re:Goto by MichaelSmith · · Score: 1

      The whole point of recursion is to use the stack. If not some sort of while loop is probably called for.

    2. Re:Goto by johannesg · · Score: 1

      I believe you are missing the greater-than character, which also looks a bit like a letter "V" with the point facing to the right. Here's one now: >

      Oh, and the last time I worked with an 80-column screen was probably 30 years ago. My current screen comfortably displays at least double that number. I really don't see why we stick with that tired old convention.

    3. Re:Goto by jbolden · · Score: 1

      You are wrong here. The whole point of recursion is to abstract away the details of how a loop executes and focus on what the loop does. Then later you use a recursion design pattern to abstract away the naive recursion. In a looping structure you end up having to decide immediately on bounds cases handling.

      Most languages that handle recursion well just translate most simple recursions into iterative loops during compilation anyway.

    4. Re:Goto by Anonymous Coward · · Score: 0

      Looooooong lines are not just a problem for small screens, it's a scientifically verified readability issue. Anyone who thinks 60+ characters on a line is a good idea is not only stupid, but deserves to be put on trial for crimes against humanity. Please stop.

    5. Re: Goto by Anonymous Coward · · Score: 0

      Some reasons you might still want to keep a limit on line widths:

      1. It's easier to read down than across. This is why newspapers use columns.
      2. Many programmers use portrait mode monitors to display more lines.
      3. Many of the ones using landscape display two files side by side - e.g. Class and tests, or caller and callee.
      4. It's often easier to see what's changed in a diff, even when the diff tool highlights parts of lines.
      5. Long lines are often a sign of poor structure. Indentation and cyclomatic complexity go hand in hand. If you have Long chains, you may want to consider Law of Demeter. Large expressions may be clearer if you name sub expressions or break into lines to show structure.

    6. Re:Goto by Rockoon · · Score: 1

      Most languages that handle recursion well just translate most simple recursions into iterative loops during compilation anyway.

      ...proving that recursion is inefficient.

      --
      "His name was James Damore."
    7. Re:Goto by religionofpeas · · Score: 1

      It's not inefficient if the compiler optimizes it away.

    8. Re:Goto by Anonymous Coward · · Score: 0

      Ohhhh, poor sensitive thing... triggered much? Suffering from microaggressions? Need a safe space?

    9. Re:Goto by david_thornley · · Score: 1

      You're missing the point of language abstractions. Ideally, we write our program in an easy-to-understand manner, and the compiler makes it run efficiently. In practice, this doesn't work as well as we'd like, but we're specifically talking here about a compiler that does what we really want.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    10. Re:Goto by Rockoon · · Score: 1

      You're missing the point of language abstractions.

      You mean like the "low level" C abstract machine?

      There is a reason the abstraction is similar to how hardware handles memory.

      Conclusion: We do not choose our abstractions based on human needs alone.

      --
      "His name was James Damore."
    11. Re:Goto by Anonymous Coward · · Score: 0

      There is a reason the abstraction is similar to how hardware handles memory.

      That hasn't been true for a long time. You're old enough to know about caches and PMMUs.

    12. Re:Goto by david_thornley · · Score: 1

      Something like a decade ago, I tried throwing out everything I'd been taught about program optimization and just optimizing for cache use. The speedup was remarkable.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
  9. Maintenance... by Anonymous Coward · · Score: 0

    "Creative" and "used with care by experienced programmer" are two things that don't work out very well in software that has to be maintained by less experienced developers. Of course creative solutions that are self evident in retrospec are not bad, as the difficult part is finding the solution. But creative solutions that require experience to understand what how they work mean it is possible for someone to break or make changes without understanding the consequences. They can still be used if necessary, if the gain in performance out weighs any of the consequences. But for most projects, robustness, prevention of bugs, and security far out weigh minor performance gains (getting the algorithm right will get you most of the way there for most projects, even without gotos and eval).

    1. Re:Maintenance... by bool2 · · Score: 1

      That's not a reason to outlaw their use. If all you have are mediocre developers then no amount of coding standards will help you.

      Less experienced developers can learn from good code. Sure they will get it wrong as they find their feet - we have code reviews to deal with that - but we shouldn't seek to handicap them by taking away tools they can use to express themselves.

  10. I am not a programmer but by Anonymous Coward · · Score: 0

    recursion is very elegant but I see how it could be used unnecessary.
    As a laymen I see the following problem:
    You write an algo, but you never expected it to be run a trillion times. In a loop this becomes a time problem. With a recursive algo this also may become a RAM problem.

  11. Obvious answer by aaribaud · · Score: 3, Insightful

    It depends.

    In some cases, you want to allow goto statements, for instance because they help manage failure handling without adding condition or exception constructs.

    In some case, you want none of these gotos, because you are using processes or tools which are (partly or entirely) not compatible with them, and you need these tools to work more than you need gotos.

    In some cases, you don't want recursivity because the contex does not favor them (think embedded SW with restricted stack size).

    In some cases you want recursion because it makes code simpler and closer to the principles behind it, thus more maintainable.

    In some cases, you want class-like constructs in C be don't want C++ because the legacy code, people involved, time alloted, or general context just does not allow you to rewrite the whole thing.

    Etc.

    1. Re:Obvious answer by Anonymous Coward · · Score: 0

      Almost anything is better than exceptions. If a goto makes you cringe, exceptions are far far worse.

      Recursion is only useful when the recursion depth can be guaranteed limited. It can be very useful then, but uncontrolled stack growth is a curse, particularly in libraries, particularly in threaded code. There's generally an iterative alternative which is near as elegant. I've had to remove recursion in my own code because of the stack use issues. ( A thousand threads or so and heavy stack use gets VERY expensive).

    2. Re:Obvious answer by Anonymous Coward · · Score: 0

      Unless you can rely on tail-recursion.

    3. Re:Obvious answer by jbolden · · Score: 1

      I don't agree with you. I use recursion all the time on infinite data structures where obviously the inner loops using recursion can't limit. That has to be handled by the out loops creating the evaluation context.

    4. Re:Obvious answer by Anonymous Coward · · Score: 0

      Interesting. Try working on an embedded system. BGP routing convergence needs to be fast and NOT use up all the available RAM.

    5. Re:Obvious answer by david_thornley · · Score: 1

      Exceptions are for exceptional situations, and make handling them easier. (If they don't, don't use exceptions.) If people used goto only in exceptional situations, or only where it was clearer than the alternatives, Dijkstra would never have written against it.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    6. Re:Obvious answer by Anonymous Coward · · Score: 0

      You aren't too bright.

      Dijkstra wrote against them in the context where goto's were being used to jump anywhere. He wrote it before C was created and his paper has zero relevance on C.

      Are there any languages these days(other than shitty basic) that allows unfettered goto's?

      Dumbasses like you think that continue and break aren't goto's or function calls, if, while, etc. They are all goto's

    7. Re:Obvious answer by Anonymous Coward · · Score: 0

      Just because it is dangerous is limited contexts it doesn't make it worthless for all.

      The programming world is much bigger than your tiny area.

  12. Recursion? Forgotten? by Anonymous Coward · · Score: 0

    It's only the first thing you learn to do in SICP.

    1. Re:Recursion? Forgotten? by lgw · · Score: 1

      It's only the first thing you learn to do in SICP.

      Not even MIT still uses SICP, sadly.

      --
      Socialism: a lie told by totalitarians and believed by fools.
    2. Re:Recursion? Forgotten? by K.+S.+Kyosuke · · Score: 1

      Technically, MIT does still use SICP. I believe the class is called "Advanced Symbolic Systems" or something like that.

      --
      Ezekiel 23:20
  13. Some things are better left alone by mridoni · · Score: 1

    Do what you want with your GOTOs, but do not bring ALTER back.

    1. Re:Some things are better left alone by tepples · · Score: 1

      We have ALTERable GOTOs in modern languages. They're called function pointers.

  14. I know what will happen one day. by LordHighExecutioner · · Score: 4, Insightful

    Somebody will publish a paper entitled: "Class statement considered harmful." and he will be applauded as the new IT guru!

    1. Re:I know what will happen one day. by johannesg · · Score: 3, Interesting

      That already happened; apparently some people now feel inheritance is bad. I've seen a few of their arguments (rants, really), and it seems to boil down to "you can get confused", "some inheritance trees are too deep", and a whole bunch of irrational ranting besides.

      I do agree that we've(*) suffered from an overload of policy factory manager producer singletons (which seems to be an important part of many of those rants), but actually inheritance is a tool that serves me well in many, many cases. It's certainly way better than having type-specific switch statements all over the place...

      (*) I say "we", but actually it seems like a fairly typical Java affliction, more than a general OO thing...

    2. Re:I know what will happen one day. by DrXym · · Score: 1
      Multiple inheritance of concrete classes generally is bad due to issues like diamond patterns. Single inheritance or multiple inheritance where only one class is concrete and the rest are interfaces is generally ok. That's assuming all the code resides in the same binary since fragile base classes can screw everything up.

      Stuff like virtual destructors, rule of three / five etc. in C++ demonstrate some pretty fundamental problems that can only be overcome with best practice. Inheritance in Java is much nicer.

    3. Re:I know what will happen one day. by Anonymous Coward · · Score: 0

      It's been done. Several times, by several people. Though, admittedly, under different titles. They were all, without question, correct. Classes were a mistake which lead to countless other disasters. They've set software development back decades. It'll be decades more before we recover.

      Unfortunately, your prediction didn't come true. Rather than being lauded for their genius, they were demonized as heretics.

      We're just now starting to see signs that the great class nightmare, or the development dark ages, is coming to an end. It won't be swift, but it will inevitably happen.

    4. Re:I know what will happen one day. by Anonymous Coward · · Score: 0

      That already happened; apparently some people now feel inheritance is bad. I've seen a few of their arguments (rants, really), and it seems to boil down to "you can get confused", "some inheritance trees are too deep", and a whole bunch of irrational ranting besides.

      The ones I've read are more like "unless you're programming a biology classification simulator, it doesn't really match your problem domain, so inheritance is a clumsy modelization", or "there are better ways to have code reuse (i.e. traits)". Both arguments seem very rational.

    5. Re:I know what will happen one day. by cheesybagel · · Score: 4, Insightful

      IMO class inheritance is useless. Interfaces and properties are a good idea though.

    6. Re:I know what will happen one day. by DrXym · · Score: 1
      I wouldn't say it's useless. I'm writing a lot of Rust at the moment and lack of inheritance can be a pain in the ass especially when implementing some UML that expresses inheritance.

      The workaround is use composition. Make the base class (struct) a member of the things that "derive" from it and a trait that allows callers to call the composite and map the calls onto the base. It's a pain though and for more than one "subclass" involves macros to generate the boiler plate. It would be nice if Rust had a #[derive_composite(base)] that generated this boiler plate automatically.

    7. Re: I know what will happen one day. by Anonymous Coward · · Score: 0

      Deep inheritance is as bad as huge IF chains or using LOOPs instead of GOTO.

      DI is just all kinds of headaches, is usually a massive waste of time abstracting in the design of said classes, and has no advantages in any inheritance tree I've ever seen.
      Over-abstraction just isn't efficient. It greats these stupidly simplistic classes for exactly one use-case, usually used infrequently, and has no use outside of the parent it spawned.

    8. Re:I know what will happen one day. by Anonymous Coward · · Score: 0

      My problem with inheritance is when it's misused. One guy I work with loves inheritance, and I've come up to objects that have something like 8 levels of inheritance. Fortunately it's java so he can't do multiple parents, but I'm sure if he could he would. But trying to figure out how anything works in his code just becomes a slog. It really kills maintainability. Do it where it makes sense, but don't do it for the sake of doing it.

    9. Re:I know what will happen one day. by Anonymous Coward · · Score: 0

      Classes & inheritance aren't the problem. Mutability of class objects and stupidly long/complex inheritance graphs are the biggest problems.

    10. Re:I know what will happen one day. by rock_climbing_guy · · Score: 1

      I will applaud when they say "class statement considered harmful in Javascript because it reinvents the wheel"

      --
      Wh47 d1d j00 541, 31337 15n't t3h r0xor5 ne m0r3???
    11. Re:I know what will happen one day. by david_thornley · · Score: 1

      Inheritance in Java is also more limited than inheritance in C++. One of the design goals of Java seems to have been to produce a safer C++ at the cost of expressive power.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    12. Re:I know what will happen one day. by david_thornley · · Score: 2

      As someone who has worked with complicated C++ software for something like fifteen years, inheritance is very valuable. It keeps some of our core concepts understandable. It can clearly be overused, of course, but that's true of all language constructs.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    13. Re:I know what will happen one day. by Anonymous Coward · · Score: 0

      I'll take a good abstract base class with a default or genericized implementation over a mostly-useless interface any day. Interfaces are good for making sure generics are applied only to certain classes, though. Perhaps things are different in Java-land, but in C#, Blah <T> where T : IWhatever is pretty nice when you need it. But always start with an abstract base class and a set of default (virtual, of course) functions for common processes.

      And if you need a factory method to generate concrete instances inherited from your abstract base, that abstract base class is a perfect place to put a static Create function. You can't do that with an interface.

    14. Re:I know what will happen one day. by david_thornley · · Score: 2

      Beware of arguments that seem rational and are not based on experience.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    15. Re:I know what will happen one day. by Anonymous Coward · · Score: 0

      I will applaud when they say "JavaScript considered harmful." :-P

    16. Re:I know what will happen one day. by Anonymous Coward · · Score: 0

      Inheritance is just a fancy if statement, isn't it? And it indeed can get confusing.

    17. Re:I know what will happen one day. by Anonymous Coward · · Score: 0

      The problem with class inheritance is that it's incompatible with mere interface-inheritance: whether x inherits the implementation from y isn't any more an x's own little implementation detail but becomes a part of the official interface contract between x and z,w,q,p,r and h while most likely none of them actually intended it that way.

    18. Re:I know what will happen one day. by david_thornley · · Score: 1

      There's other patterns that work with multiple inheritance, such as only one superclass having superclasses of its own. This allows "mixin" classes, which provide one specific behavior. We make extensive use of these, and don't have problems with them.

      What you're finding more awkward in C++ inheritance has nothing directly to do with inheritance, but with C++ resource management. There's no problem with including a virtual destructor on every class you don't mark "final". The rule of three/five exists because a class may own resources that have to be cleared out or dealt with on destruction, and the C++ lack of a reference type distinction. With garbage collection and no destructors (finalizers are not destructors), Java makes cleaning up memory a lot easier and cleaning up anything else more difficult, but by removing resource management from the class structure it does make inheritance easier to get right.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    19. Re:I know what will happen one day. by ebvwfbw · · Score: 1

      That already happened; apparently some people now feel inheritance is bad. I've seen a few of their arguments (rants, really), and it seems to boil down to "you can get confused", "some inheritance trees are too deep"...

      In other words, it's bad because they are too stupid and get confused. I've run into people like that. It's fun to ask them how they would do it. This is often an exercise in "how to keep an idiot busy."

    20. Re:I know what will happen one day. by Anonymous Coward · · Score: 0

      Beware of arguments that seem rational and are not based on experience.

      You have positive examples with direct multiple inheritance, not based on interfaces? I'd love to hear about that.

  15. Everything by Anonymous Coward · · Score: 0

    10 Everything Has Its Purpose
    20 Goto 10

  16. 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.

    1. Re:What the article says by geggibus · · Score: 1

      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.

      Can you please provide a proof for this?

    2. Re:What the article says by Anonymous Coward · · Score: 0

      Any recursive algorithm can be implemented as a loop + stack object.

      Nice feature of this approach when traversing data structures - to change from depth first to breadth first order you just swap the stack for a queue.

      I often prototype something as a recursive function (small, elegant), then convert it to the loop form later if it will have to work on larger data sets.

    3. Re:What the article says by Anonymous Coward · · Score: 0

      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.

      Take a look at Church-Turing theorem please. It's pretty much the opposite - any recursive algorithm can be implemented as an iterative algorithm in a system equivalent to Turing machine.

      Think of it this way - for any recursive function you can instead have a stack and a loop that instead of doing a function call uses stack to "fake" function calls.

      Unless of course we're talking of non-computable recursive functions - however, they are not computable in any of the OO or whichever languages we have available either.

    4. Re:What the article says by Anonymous Coward · · Score: 2, Informative
    5. Re:What the article says by Anonymous Coward · · Score: 0

      It is obviously wrong and no such proof can exist because a loop + array (to represent a stack) implements completely generic recursion.
      Of course in the mathematical sense, a fixed size array cannot work, since you might recurse beyond the size of that, but
      1) On real hardware, actual recursion is worse since your stack is never larger than your heap
      2) You can of course realloc
      Maybe he was thinking of the proof that you cannot implement it with a loop and O(1) memory usage, but that the loop needs at least O(n) (where n are the number of loop iterations) memory, but that is a completely different thing.

    6. Re:What the article says by cheesybagel · · Score: 1

      It then mentions that these things should be used to avoid complexity in certain situations.
      goto -- error handling

      Exceptions do this better if your language supports them.

      multiple inheritance -- is generally too useful to give up. implement with interfaces and be careful

      Languages like Java don't support class multiple inheritance only interface multiple inheritance yes. For a reason. Class multiple inheritance is bonkers.

      eval -- JSON, HTML, math...

      It has its uses but it's a security hazard.

      recursion -- trees, some list algorithms... recommend to implement imperative style mostly though (article assumes the language can't handle recursion)

      Recursion can provide an easier to read algorithm which is good for prototyping but typically it uses too much stack memory and its better to manually handle the stack yourself if you need one. On modern pervasively MT architectures you should minimize the amount of per thread memory to keep the program running inside the processor caches and typically recursive algorithms are a bad idea because of this.

    7. Re:What the article says by Anonymous Coward · · Score: 0

      they can't, as *all* recursive algorithms can be rewritten in iterative form

    8. Re:What the article says by jbolden · · Score: 2

      This is recursion theory. A tail recursive function f is expressible in loop form f' and visa versa (https://en.wikipedia.org/wiki/Tail_call#Relation_to_while_construct). Given any simple recursion that's not tail recursive you can use an explicit stack. So for example quick sort is much easier to implement recursively but it can be implemented with an explicit stack to make it into a loop. To get something that you can't avoid you need something for which the complexity / size of the explicit stack can't be computed.

      A church number (see link if you want more: https://en.wikipedia.org/wiki/...) is a function that takes two arguments one a function from a to a, the second of value of a.
      example three = f ( f ( f z ))) or f(f(f(z))) depending on notation

      three (+1) 0 == 3 as would expect.
      on the other hand
      if pred n = (\(a,b) -> b) (n (\(a,b) -> (succ a, a)) (zero, zero) where
      succ n f z = f (n f z)
      zero f z = z

      then you can define a subtraction function on church numbers.
      minus p q = q pred p
      with that definition for all church p,q and f, z.
      (minus (plus p q) q) f z == p f z

      That function minus is not expressible as a loop though it uses the recursive structure of the underlying church number q as you can see above.

    9. Re:What the article says by jbolden · · Score: 1

      See my response above. I mostly agree with you. Though you are over simplifying a bit. For full recursion to work you need infinite time and memory. There are functions which are computable in fixed time and memory recursively but not iteratively.

    10. Re:What the article says by jbolden · · Score: 1

      I'd actually say better still is to use a recursion pattern (map-reduce, more generic hylomorphism, paramorphisms....) which can then be optimized for the machine. There is no reason to believe a programmer is going to do a better job writing his own stack handling in most situations.

      As for multiple inheritance being bonkers. My car is a Honda and a vehicle registered in NJ. That's two hierarchies.

      As for exceptions I agree just citing the article.

    11. Re:What the article says by TheRaven64 · · Score: 2

      As for multiple inheritance being bonkers. My car is a Honda and a vehicle registered in NJ. That's two hierarchies.

      That's not an argument that multiple inheritance is needed, that's an argument that subtyping rarely fits real-world problem domains.

      --
      I am TheRaven on Soylent News
    12. Re:What the article says by Anonymous Coward · · Score: 0

      Inheritance isn't nearly as useful of as polymorphism and encapsulation (the other two OO tent poles). Where Java went "wrong" was in not providing more streamlined support for composition and delegation.

    13. Re:What the article says by Anonymous Coward · · Score: 0

      "As for multiple inheritance being bonkers. My car is a Honda and a vehicle registered in NJ. That's two hierarchies."

      If you're using multiple inheritance to model that, you're doing it wrong.

    14. Re:What the article says by Anonymous Coward · · Score: 0

      I would implement that as "car extends honda implements registered" and have it contain a "registration" member; in your case, it would contain an instance of NewJerseyRegistration. Otherwise you have to throw away your car if you move to New York.

    15. Re:What the article says by jbolden · · Score: 1

      That's a good rebuttal AC. However from the standpoint of NJ i do throw away the car (i.e. it becomes an out of state car) when I register in NY.

    16. Re:What the article says by jbolden · · Score: 1

      Isn't that sort of the point of OO to model?

    17. Re:What the article says by jbolden · · Score: 1

      That's an interesting way to handle the problem via. delegation. IMHO you've basically picked up the complexity of multiple inheritance and moved it to the methods. I'm not seeing how that changes things from pure multiple. If you are following I'd love you to expand.

    18. Re:What the article says by TheRaven64 · · Score: 1

      No, the point of the OO model is that you should decompose a problem into smaller problems and the only thing that is sufficiently expressive to be able to represent the parts of the problem is a simple model of a general-purpose computer, which communicates with other simple models of general-purpose computers by message passing. Everything else is a later addition.

      --
      I am TheRaven on Soylent News
    19. Re: What the article says by Anonymous Coward · · Score: 0

      There exist algorithms that are implementable via recursion, but not implementable as loops? Since when?

    20. Re:What the article says by david_thornley · · Score: 1

      There are recursive algorithms that are important and not implementable as loops without auxiliary stacks. The loop formulations of these algorithms tend to be harder to read.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    21. Re:What the article says by david_thornley · · Score: 1

      We use multiple inheritance on the basis that a certain size of block has specific processing, and different blocks can be made of different materials. It seems to do a great job of keeping the complexity under control in our particular use case.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    22. Re:What the article says by Anonymous Coward · · Score: 0

      Car-to-registration is clearly a "has a" relationship, not an "is a". Not a good candidate for inheritance.

    23. Re:What the article says by tepples · · Score: 1

      It has its uses but it's a security hazard.

      Is there a good way to feature-detect for ECMAScript 6 syntax support in a web browser without using eval, new Function, or anything treated as similarly unsafe by Content Security Policy?

    24. Re:What the article says by phantomfive · · Score: 1

      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.

      FWIW interfaces (like Java) plus "favor composition over inheritance" seems to solve this problem for most of my cases.

      --
      "First they came for the slanderers and i said nothing."
    25. Re:What the article says by TranquilVoid · · Score: 1

      As for multiple inheritance being bonkers. My car is a Honda and a vehicle registered in NJ. That's two hierarchies.

      Viewing inheritance via the 'is-a' model this does not work as strictly a car is not necessarily a Honda nor registered (although if your domain is a database of registered Hondas, rather than of generic cars, perhaps it is fine).

      In terms of class structure, having a base class of "thing made by Honda" isn't very useful. You're better off interpreting it as "has a manufacturer property whose value is Honda". The registration base class would fare a little better, assuming the system is a registration database, then you could inherit Car from RegisteredVehicle. Even so, such a database would be more concerned with RegisteredVehicle as the top-level object, not Car, and would probably want a VehicleType property rather than storing Car/Truck/Lorry objects that all inherit from RegisteredVehicle.

      This is why inhertiance has fallen out of favour to composition - composition is more flexible (if more verbose) as it effectively allows you inherit from an interface and change at runtime.

      That said, I do occasionally come across a situation where multiple inheritance makes sense, just can't remember at the moment :)

    26. Re:What the article says by Anonymous Coward · · Score: 0

      Recursion is obviously the best understood of the 4.

      If I tell someone to "go to hell" they'll immediately understand the task.

      If I tell someone to "recurse to hell" they might never even get there!

      captcha: explains

    27. Re:What the article says by jbolden · · Score: 0

      Yes. An interface of small programs and thus keeps design constraints reasonable. The big issue with that is when you have to do complex changes across the system and keep things in sync.

    28. Re:What the article says by Xest · · Score: 1

      Your car has a make, Honda, and a registration, that in turn has a registration state of New Jersey. Why do you need to inherit these things when you can just reference them?

      You're effectively saying that your car is a type of a brand (No. It has a brand, but it isn't a type of brand.) and that it's also a type of New Jersey (What?).

    29. Re:What the article says by jbolden · · Score: 1

      Yes of course my car is a type of Honda. "My car is an Accord" is a perfectly natural thing to say. Similarly among all registered entities in NJ my car is one particular type.

    30. Re:What the article says by Xest · · Score: 1

      But Honda is a brand, so by inheriting it you're saying it's a sub-brand of Honda, but a car isn't a brand, it's a car.

      You could say that Pepsi Max is a sub-brand of Pepsi, but not that a can of Pepsi Max is a sub-brand of Pepsi, it's not, it's a can, branded with the brand Pepsi Max.

      Time and time again most people that argue that we need multiple-inheritance from classes demonstrate that the real problem is that they're not that great at breaking down things into classes in a logically sound manner - you're falling into this trap here. I'm not trying to insult you with that, frankly there isn't an awfully high percentage of developers who are actually good at it - I've read your other comments here with interest, and you're genuinely knowledgeable on a whole lot of other stuff. No developer should feel defensive or embarrassed for not fully understanding absolutely everything because as soon as you go down that path you become immune to learning about anything, and that way lies redundancy in this fast moving market.

      You have to be quite pedantic about the English language to get it right, really when people say "My car is a type of Honda", what they're saying is merely shorthand for "My car is a type of vehicle made by the company with the brand Honda", because technically no, your car isn't a type of Honda, because Honda is a brand - your car has a brand, but it isn't a brand, again, it's a car. This pedantry is pointless and irrelevant when it comes to every day life because everyone looks at you like you're a dick when you make such pedantic statements about common usage of English, but it does help when you're trying to break some real world set of entities down into a high quality object oriented design.

      If you get good at that, then it rapidly becomes clear that multiple-class inheritance is entirely unnecessary, and that multiple interface inheritance is sufficient. I do personally believe that single class inheritance is helpful though as it can drastically decrease duplicate code - whilst I accept that the interface only approach has it's benefits in terms of implementing a clean design on paper, it doesn't in terms of code maintainability IMO.

    31. Re:What the article says by jbolden · · Score: 0

      Interesting point Xest. And phrased politely for a correction as well. I guess it comes down to fundamentally do you view Honda as a collection of cars or do you view Honda as a brand that is applied to cars. I was thinking the former you were thinking the later. I do agree that under the later no reason that brand shouldn't be a property is-a relationship.

      Let me ask you the classic GUI examples: button inheriting from rectangle and clickable. How would you unwrap that?

    32. Re:What the article says by phantomfive · · Score: 1

      The big issue with that is when you have to do complex changes across the system and keep things in sync.

      I'm not sure how that relates to multiple inheritance at all, tbh. Complex changes across a large system are always going to be problematic.

      --
      "First they came for the slanderers and i said nothing."
    33. Re:What the article says by ebvwfbw · · Score: 1

      If I tell someone to "go to hell" they'll immediately understand the task.

      If I tell someone to "recurse to hell" they might never even get there!

      captcha: explains

      The stack would kill them first. The question is when they goto hell, would you send them with a Handbasket(small)?

    34. Re:What the article says by jbolden · · Score: 0

      Inheritance / linking in gives you finer grained control for upgrades. The recompile / link can do abstractions. Think about how Linux applications upgrade with libraries piecemeal.

    35. Re:What the article says by phantomfive · · Score: 1

      ok, so let me see if I understand what you're trying to say. Basically, if you have an API (which is basically a class with some public methods), then it's easier to modify the class without breaking the API when you have multiple inheritance?

      --
      "First they came for the slanderers and i said nothing."
    36. Re:What the article says by Xest · · Score: 1

      There's obviously quite a few ways of resolving that such as simply allowing a button to have a shape (i.e. a rectangle) which in turn allows it to be swapped out for a circle if you want round buttons for example. The danger with inheritance is that you're effectively fixing that behaviour.

      Clickable I'd argue is more suited to an interface, interfaces are quite good at representing behaviour.

      But in modern GUIs it's obviously become a lot more complex than all that, but in a good way - it means we have a steeper learning curve, but much more maintainable and testable code. We typically try to separate these things to a much greater degree now, as we really don't want visual design to impact on business logic. If you look at something like WPF you'll see that you basically have a button that inherits from a control, which in turn inherits from UI element (because not all UI elements need to be controls). The base UI element class has members that define how the element should be rendered - because in WPF you're not limited to rectangles, you may want a star shaped button or god knows what else if you're creating some weird UI for a game or something. It also has properties for things like size, width, font, colour, fade in/fade out effects and so on and so forth. Effectively the UI element class allows anything inheriting to look like anything, so an inheriting button class might implement some default behaviour, such as a rectangle, which in turn can be further overridden by a user, but ultimately it means that how the button looks slots in in a number of has-a relationships - has a colour, has a font, has a shape, has a size and so on and so forth.

      Things like clickable are simply exposed via events - a Control (which inherits from the above mentioned UIElement for display) will expose a number of common events such as OnClick and so forth, in C# events are basically just a form of callback, so effectively once you create a button you just assign callback handlers to those events which are again present in has-a relationships, so that a button has an on click event, a button has a resize event, and so on and so forth.

      What this means is that a button is really just an abstract concept for the most part - how that looks is really about how you set it's look and feel properties, how it behaves is really just defined by whatever you hook up to none, some, or all of it's many events.

      Now I'm not arguing that WPF is some example of perfect OO design, not by any measure, I'm citing it as an example of one way to design a GUI library without needing multiple inheritance. I believe that WPF's composition is actually quite messy - personally I think a UIElement should have a "visual style" and that in turn that visual style should encapsulate all the visual elements - if you look at the interface it's massive and messy, though to be fair a lot of this is because Windows is still dragging a fuck ton of legacy along behind it:

      https://msdn.microsoft.com/en-...

      For more simplistic designs you may just determine that all UI elements are in fact controls and just merge UI element and control into one base class (which is basically what you have in WinForms). Essentially the goal of WPF is to separate concerns - you don't have to worry about someone having checked the button out to write code defining how it looks whilst someone else wants to check it out to define what it does, because the button is just abstract - someone can define how it looks in one file, and someone else can define what it does in another. Only one of them has to wire it up without being concerned about the implementation details, and it kind of works. WPF has an XML GUI definition called XAML not too different to the way websites have their visual elements defined in HTML with the idea being that the whole interface can be defined by someone who doesn't even know code, whilst developers write the business logic behi

    37. Re:What the article says by jbolden · · Score: 1

      That's a very good answer. I'm going to digest it for a day or two and think about it. This forum doesn't lend itself to long conversations. But I'll see if it is still open for a response. My initial thinking is your argument seems strong.

      I guess the question then is, given your attitude above why do you think even single inheritance is useful? How does the above not argument equally apply in that case? In other words why not do what functional languages do and have polymorphic methods not tied to classes and get rid of base / parent classes entirely?

    38. Re:What the article says by Xest · · Score: 1

      On a conceptual level when talking about object oriented analysis I think the argument for single inheritance makes sense - I believe it's always the case that a thing is a sub-type of another thing and that remains true until you boil down to the fundamental building blocks of the universe - the base particles, which would, if you were building the entire universe in code presumably be our base classes (I'm not a physicist, I'm sure one might correct me :)).

      The difficulty with it is again in the mapping of figuring out what that parent type is, as we've seen it can be difficult when mapping casual English to an object oriented design that we run into problems, and so we have to be very careful about determining what that parent type actually is, rather than what we initially think it is, sometimes that parent type can be an entirely abstract concept - I would argue this is what we have in the case of Honda, it's a brand, but a brand in itself is just an abstract concept defined by a series of other items such as a trademark, a name, a logo and so forth. If we really wanted to get theoretical though we might choose to argue that a brand is actually just, say, an idea, and create an "Idea" parent type which is in turn just an organised set of thoughts, which are in turn just an organised set of electrical impulses in the brain and so on and so forth, so there nearly always seems to be something deeper you can parent type to that is individual. Even if we go back to the idea of particles, one might argue that element A is made of particle X and particle Y, so we just inherit those particles with multiple inheritance, but I think even here it's not an ideal solution because there's more to it than that, we probably need a more abstract concept of a class to inherit from instead such as a ParticleSystem, that defines not just the elements that comprise the element but their relation, the number of each (what if it's made up of two of particle X for example? - we can't inherit it twice).

      That's not to say there aren't examples where maybe multiple inheritance does make sense - if we invent a Car Plane then is it not reasonable to inherit from Car and Plane? That's probably a reasonable argument conceptually, practically this may cause issues though - the behaviour of wheels on the car, and wheels on the plane when taxiing may be completely different and confuse each other, so even here you'd probably be better off just implementing a new CarPlane type that inherits from vehicle. It of course gets messy if some of your planes are water planes and land on floats.

      Of course you're right though, there are other ways to solve these sorts of problems rather than single inheritance, and I don't want to make it sound like I'm pretending single inheritance is a magic bullet, it gets misused every day and junior devs still often struggle to properly understand it's use and associated keywords, especially when you're having to explain the difference between abstract and virtual and so on and so forth - they certainly don't follow that sort of thing conceptually as easy as something like the humble if statement.

      The real benefit of inheritance is that it allows encapsulation of reusable code, we're effectively saying that this code in the parent class is reusable, but only by certain other types - it's not relevant to everything, just these few things. This means we only have to write that code once, but it also means that it's not floating around for people who just don't care about those methods in that part of the application to see. It's of course not just methods we capture in this way, but properties/fields also.

      I have tried a no class inheritance route, using only interface as some profess is the ultimate clean design, and I inevitably find it just ends up resulting in more code duplication. In part this is probably more a limitation of various languages (C#, Java etc.) than it is an inherently intractable problem. So whilst I'm not inherently against the concept in principal, I

  17. Fuck ppl who hate goto but love exceptions by Anonymous Coward · · Score: 1

    People who hate goto but love exceptions drive me up the wall. You hate the cute little goto with the well defined label you can instantly fly to in any IDE from vi on up, but you love the goto that jumps across any number of functions and puts you in some code (std:terminate if you fucked up!) ? And don't forget that in C++ (and others I think), you aren't even sure if a given function can throw an exception except by inspection.

    Worst. Flow control. Evar.

    1. Re:Fuck ppl who hate goto but love exceptions by david_thornley · · Score: 1

      Exceptions do things that are hard to do without them. Most uses of goto can be better written as something else.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
    2. Re:Fuck ppl who hate goto but love exceptions by K.+S.+Kyosuke · · Score: 1

      Some languages have somewhat smarter exceptions. Common Lisp and Smalltalk come to mind. But yeah, in C++, it's complicated.

      --
      Ezekiel 23:20
  18. Eval is a Beginners' Trap and a Huge Security Hole by mcpublic · · Score: 1

    Eval has been part of the Lisp programming language since the dawn of computing, but few experienced Lisp programmers ever used it outside of read-eval-print loops and software development tools (where its existence is a totally awesome gift). Eval is widely considered a beginner's trap. It is rarely "the right thing," typically because it is super inefficient. But my biggest concern is that it is a huge security hole, especially when the expression to be evaluated comes from the user. Think SQL injection attack. It is wise to require some sort of security credentials and/or filters to make sure the expression is within a "safe subset" of the language... at which point you might as well write the mini-interpreter you really need, instead of making the entire, underlying language and the application's entire data environment available for anyone to use or misuse.

  19. Avoid as a rule, apply with good reasoning by SpaghettiPattern · · Score: 1

    Any "dirty" style should be avoided as a rule and applied with good reasoning.

    My guilty pleasure is to return multiple return statements. The reasoning behind this is that it sometimes makes code better readable. Less nesting/fewer methods. Translating "avoid multiple return statements" to loops would result in avoiding break and continue statements.

    If one's self-critical enough, code will be cleaned up eventually. Cleanly avoiding multiple return statements -and too many avoiding break and continue statements- usually comes with a breakthrough in the functional decomposition of the problem at hand.

    --

    I hadn't the slightest objection to his spending his time planning massacres for the bourgeoisie... (P.G. Wodehouse)
    1. Re:Avoid as a rule, apply with good reasoning by swilver · · Score: 2

      There's absolutely nothing wrong with multiple returns, continue and breaks. Don't let some purist that got this added to your favourite "code checker" tool fool you that just because the rule is there, it must be good.

  20. forgotten constructs? idiots rule this world by l3v1 · · Score: 0

    "Are you using these "forgotten code constructs" -- and should you be?">

    I honestly think sometimes these newgen coders are just crazy ass stupid. Forgotten constructs meaning recursion, multiple inheritance or evals? Seriously? Flamethrower? And this written by some "senior" developer? You just have to stop wondering why lots of current software are so idioticlally written, since if there are more than one of such ignorant preachers behind them, instead of some real programmers, it's a real wonder how any software of value can be produced anywehere.

    It's bad enough such people are part of the sw industry at all, letting them spread their wisdom is a disgrace to everyone invlved.

    --
    I am putting myself to the fullest possible use, which is all I can think that any conscious entity can ever hope to do.
  21. C is shorthand for assembly by Anonymous Coward · · Score: 0

    goto is perfectly fine and should be used as often as you need it. It will cause a branch/jump just as you expect it to.

    1. Re:C is shorthand for assembly by Anonymous Coward · · Score: 0

      > C is shorthand for assembly

      No it isn't. No more so than any other HLL, anyway. C is full of abstractions.

  22. Nope by Anonymous Coward · · Score: 0

    But when the article describes recursion as "more forgotten than forbidden," it begs the inevitable question.

    No, it does not.

  23. Honest answer by gargleblast · · Score: 1

    Pretty sure you're doing a lot better than the jackass who came up with the phrase "Forgotten code construct".

  24. Don't miss them. by MouseTheLuckyDog · · Score: 1

    Recursion is either so easy it is more of a trick than a useful tool, or it is more complex in which case it is generally much harder to get the terminal conditions right then it is to avoid recursion.

    I remember when I learned C, digging through K&R to find how to do goto. I also remember learning ruby and not even thinking about whether or not goto was supported. It really isn't needed and as Dikstra pointed out is mostly used for creating sloppy code.

  25. yea by AchiestDragon · · Score: 1

    it depends on the system environment , if your writing code to be used by a multi-thread o/s environment where use is discuraged as fearlessly as when you writing stand alone code for a embeded stand alone system where use of such can be expected , the other is the use of global vars

  26. Re:Eval is a Beginners' Trap and a Huge Security H by Anonymous Coward · · Score: 0

    > at which point you might as well write the mini-interpreter you really need, instead of making the entire,

    Greenspun's tenth rule:
    Any sufficiently complicated C or Fortran program contains an ad-hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.

  27. Goto has its uses by DrXym · · Score: 2

    Sometimes code has to do multiple things and if any of those things fail, the whole lot has to be cleaned up. Using a "goto cleanup" is usually a lot more preferable way of cleaning up that nesting the code in conditionals rendering it unreadable or duplicating the cleanup in several places.

    1. Re:Goto has its uses by Anonymous Coward · · Score: 0

      I usually use a do {} while (0); construct for those sorts of things. Where I use goto is typically if there's an error inside nested loops.

    2. Re:Goto has its uses by Anonymous Coward · · Score: 0

      depends on the language. Some languages, yes, goto cleanup is wonderful. Some languages you can avoid it.

      There was a multi-malloc example above. What I'd do in Java for a similar situation would be to use try-with-resources. Sure, the compiler will probably wind up turning it into some flavor of "goto cleanup" but the guy who just got pulled into my team and doesn't know the problem domain so well yet doesn't have to deal with it.

    3. Re:Goto has its uses by Anonymous Coward · · Score: 0

      I think python does that pretty well with the "with" operator.

      Admittedly, this requires that the cleanup be a property of a class, but that usually isn't a problem.

    4. Re:Goto has its uses by david_thornley · · Score: 1

      This is what destructors do in C++. Some languages have try...finally. In most modern languages, if your cleanup is freeing memory, you just leave it for the garbage collector.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
  28. Be aware, not compulsive by Anonymous Coward · · Score: 0

    There is no such thing as an inherently bad code construct. Sometimes it comes down to picking the solution that is least bad, buta good solution is always contextual. Unfortunately, some people believe in a 'one true way' of programming and will compulsively repeat the same algorithm/syntax/language every, single time. Not only that, they often vocally (and not very politely) tell everyone else they are wrong when they don't follow that pattern. This is not the same as being aware of the pitfalls of a given solution. Awareness allows you to weight up the pros and cons effectively –but even then, there may be multiple solutions that would be roughly equal.

  29. Goto alive and well... by Anonymous Coward · · Score: 0

    Just out of curiosity, checking against a codebase that is generally of very high quality...

    $ find go/src -name \*.go -exec grep goto {} \; | wc -l
              793

    Then again, they are mostly found in compiler and networking code, and not the packages. They are useful, and can be used well to make code clearer and faster. Honestly, I'd like to hear the experiences of someone implementing such code that doesn't use goto. Anyone?

  30. No. by Anonymous Coward · · Score: 0

    Linus' argument leans on the readability of the code.
    Do we _need_ goto to produce readable code?
    No, in fact it tends to produce less readable code (depending on the skills of the programmer)

    There is a good reason we are forgetting these contructs ; (and that goes for eval doubly so) they encourage bad ideas.
    We don't need them, and they're dangerous.

  31. Points off assignments by Anonymous Coward · · Score: 0

    I had a CS Prof in 1991 that would take points off assigments if one used GOTO and aven rejected them.

  32. goto is useful in some situations by nateman1352 · · Score: 2

    When writing C code where exceptions are not available, I'll often use goto statements to perform error handling. Its useful because you only have to write any necessary memory de-allocation code once. Its pretty easy to simulate a try/finally block using them and its a way better and more readable way to write that sort of code then the other alternatives you have in C. All that said, I prefer exceptions, they more or less get the same job done, its easier to nest them, and IMHO are a bit more readable than the goto method. Only downside of exceptions is the execution overhead is often very bad compared to a goto.

  33. slashcrap by Anonymous Coward · · Score: 0

    eval is very, very, very useful.

  34. Devil is in the details by grumbel5969 · · Score: 1

    The problem with eval() is that it's incredible power can't be used safely in most languages, as whatever you eval() becomes part of the main program. If you could eval() code in a sandbox and apply memory and CPU cycle limits to it, it would be very useful, but most languages don't have such features making eval() little more than a dangerous toy that sometimes becomes useful for debugging.

    As for goto, the Linux kernel is full of it and quite readable because of it. But outside of C you tend to have other mechanism to deal with resource cleanup that make it no longer necessary (RAII in C++, 'with' statements in Python).

    Recursion again depends heavily on the details. In Python you quickly run into stack overflows when you use recursion to much (1000 is the default), so it's best avoided. In Haskell or Scheme it's the normal way of doing things, thanks to tail recursion support.

    Multi-inheritance I never found very useful, even single-inheritance is rarely a good solution and you are better of doing composition most of the time.

    1. Re:Devil is in the details by david_thornley · · Score: 1

      The problem with eval() is that it's incredible power can't be used safely in most languages,

      There are language constructs that should be used only in limited contexts. I'd look at an "eval" in application code as suspiciously as I'd look at "delete" in C++ application code. Both are commonly done by programmers who don't quite know how to use the language.

      Multi-inheritance I never found very useful, even single-inheritance is rarely a good solution and you are better of doing composition most of the time.

      Not in my experience, which may well be different from yours. There are situations where inheritance is exactly what you want (typically if you have a definite IS-A relationship with no gotchas which would violate the Liskov substitution principle*). Faking it with composition would be clumsy and unnecessary. You do need to have a good idea where inheritance is appropriate and where composition is. If most of your classes use other classes through inheritance, you're probably doing it wrong.

      *The Liskov Substitution Principle is a little technical, but the general idea is that, if B inherits from A, members of A have to be expressible as members of B. For example, a square is a rectangle, but you can't represent a 2x4 rectangle as a square, so having Square inherit from Rectangle would violate the LSP.

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
  35. Recursion by mrthoughtful · · Score: 1

    Recursion has never been dead.
    Tail recursion is an essential part of all modern efficiency in compilation.
    Many languages, especially functional languages, cannot really even begin without recursion.

    If you haven't got what I am saying, read this comment from the beginning.

    --
    This comment was written with the intention to opt out of advertising.
  36. GOTO is useful ... when you have nothing else by Misagon · · Score: 2

    In my opinion there are valid uses of GOTO where it could be used, but nowhere else, especially in C.
    Modern languages should preferably have constructs especially for those cases so that you wouldn't have to use GOTO, but many languages don't.

    The article already mentions error handling in languages without RAII or exceptions, where resources have to be deallocated. Note also that not all resources are objects on the heap: The function may need to close a file or a network connection etc.

    I find goto most useful for for breaking out of loops. Many languages have constructs especially for breaking out of nested loops to a scope that encloses the enclosing loop but there is one class of loop that is rarely supported: Loops for looking up an item in a data structure, you want to take a different code paths for when an item has been found to when the loop has run its course without a result.
    The only major language I know of that supports this with its own construct is Python in the form: for: ... break ... else: ..., where the else-block is taken only if you did not break out of the loop.
    In languages that allow nested break statements you could emulate that by enclosing the loop within an outer loop and breaking out of that but IMHO that would be even less readable than using GOTOs.

    --
    "We mustn't be caught by surprise by our own advancing technology" -- Aldous Huxley
    1. Re:GOTO is useful ... when you have nothing else by Goragoth · · Score: 1

      But there's nothing inherently unreadable about goto. In fact it is really obvious what it does and how it works, and I think a lot of code would be more readable if goto wasn't so demonised. The problem with goto is that it is easy to abuse, you can replace most other constructs (functions, loops, etc...) with creative goto usage and then you end up with unreadable spaghetti code. Using it to break out of a nested loop or to handle an error condition is perfectly fine and more readable than alternatives.

    2. Re:GOTO is useful ... when you have nothing else by Anonymous Coward · · Score: 0

      If you can write a flowchart or process chart, then you are competent enough to use gotos properly. However, very few programmers have the empotional maturity to realize that branching is an inherent structure in nature and machine code, and are so woefully ignorant of microprocessors that they truly believe that object oriented programming is inherently better, and blissfully miss that billions of dollars of development have gone into making compilers unfuck their programs.

  37. GoTo = ok if it goes down & out 1 direction by Anonymous Coward · · Score: 0

    Function APKMacLikeTrashCan(ProcName: ShortString): SmallInt; register;
    var
      APKTest42: ShortInt;
    Label
      WeOuttie;
    begin
      APKSizeCheck();
      Screen.Cursor:=crHourGlass;
      if ProcName = 'ConvertAndFilter' then
      begin
          APKTest42:= APKFileScrub(Trim('tempfile.txt'));
          end;
        GoTo WeOuttie;
      if ProcName = 'BuildFinalHostsFileClick' then
      begin
        APKTest42:= APKFileScrub(Trim('tempfile.txt'));
        GoTo WeOuttie;
    WeOuttie:
      Screen.Cursor:=crDefault;
      Application.ProcessMessages;
      Result:=1;
    end;

    * No "spaghetti code" going up & backward - Linus Torvalds IS correct, goto IS ok!

    APK

    P.S.=> Take a look @ that - only goes "down & out" 1 direction (another example is Microsoft's use of it in errtrapping in VBScript/VB too) - as long as you don't make your code go jumping back up & then DOWN again using goto? It only goes 1 way based on conditions (down to the EXITING label)... apk

  38. Re:Eval is a Beginners' Trap and a Huge Security H by K.+S.+Kyosuke · · Score: 2

    It is rarely "the right thing," typically because it is super inefficient.

    In compiling implementations of programming languages, it's anything but inefficient.

    But my biggest concern is that it is a huge security hole, especially when the expression to be evaluated comes from the user.

    One of my favourite quotes in programming: "If you don't want to do something, just don't do that."

    at which point you might as well write the mini-interpreter you really need,

    Will you also rewrite the compiler, and the memory manager, and write a set of interfaces between your two separate kingdoms?

    --
    Ezekiel 23:20
  39. Addendum: A poke @ Mr. Torvalds use of C by Anonymous Coward · · Score: 0

    "Of course, in stupid languages like Pascal, where labels cannot be descriptive, goto's can be bad. But that's not the fault of the goto, that's the braindamage of the language designer. Linus"

    - by Linus Torvalds from http://koblents.com/Ches/Links/Month-Mar-2013/20-Using-Goto-in-Linux-Kernel-Code/

    Mr. Torvalds, @ least Pascal/Object Pascal/Delphi, what I used in my code example in the post I replied to here, have length built-in to their strings, unlike null-terminated C you use (that creates exploitable code possibles & YOU USE IT IN A KERNEL of an OS)!

    * Also - I could also make my label in my post I replied (with a partial excerpt, edited out some bulk to fit in here, from a program of mine for file cleanups based on what's going on so it can do repeated runs & NOT buildup excess bulk in files it works on & @ shutdown so those files are also cleared to not take space on disk as they are temporary only) to MUCH longer & more descriptive than I did IF I wanted but it describes exactly what I said - 1 way out 1 direction clean!

    APK

    P.S.=> @ least we agree on GoTo being ok... apk

  40. Eval by Tangential · · Score: 1

    Eval, properly used, can be extremely valuable and reduce a lot of code bulk. Improperly used it presents various nightmare scenarios for security and stability.

    In reality though, I don't see much more than a slightly nuanced difference between using eval and dynamically constructing any portion of a SQL statement for execution at runtime.

    Use it, but use it carefully.

    --
    Suppose you were an idiot. And suppose you were a member of congress. But then I repeat myself. -- Mark Twain
  41. Some of these things are not like the others by bradley13 · · Score: 2

    Goto: A way to enable lousy programmers to write impenetrable code. Are there extremely unusual circumstances, where a superstar might use a Goto in a good way? Yes, but the price - encouraging use by the incompetent - is not worth it.

    Multiple inheritance: Middle ground. In a few circumstances useful, but the conceptual complexity is too high for many programmers. On the other hand, those will not be the ones designing your architecture. Mixed feelings about this one.

    Recursion: Many algorithms can be implemented more cleanly with recursion than with iteration. If recursion were better supported, it would be more widely used. Unfortunately, the most widely used languages have poor implementations (C# and Java, to name two), making recursion horribly inefficient. Optimizing for tail-recursion is not hard (Scala does it on the JVM), so it's weird that this isn't done in all modern languages.

    --
    Enjoy life! This is not a dress rehearsal.
    1. Re:Some of these things are not like the others by religionofpeas · · Score: 1

      Goto: A way to enable lousy programmers to write impenetrable code

      I don't let lousy programmers touch my code. Problem solved.

    2. Re:Some of these things are not like the others by bradley13 · · Score: 3, Informative

      "I don't let lousy programmers touch my code. Problem solved."

      Nice thought, but that's not real life. As a cynical estimate, at least half of the people working as programmers are lousy. Companies hire them, because they're cheap, or because the company can't find anyone better, or because the company has no clue about programmer quality. There's more code to write than there are good programmers to write them, and that's not going to change any time soon.

      --
      Enjoy life! This is not a dress rehearsal.
    3. Re:Some of these things are not like the others by lgw · · Score: 3, Insightful

      goto is vital to safe C code. You want to be able to jump to your clean-up code from each place something might go wrong. The alternative is to add another layer of indentation under an "if" for each place something might go wrong, the stuff of nightmares.

      --
      Socialism: a lie told by totalitarians and believed by fools.
    4. Re:Some of these things are not like the others by Anonymous Coward · · Score: 0

      Multiple inheritance: Middle ground. In a few circumstances useful, but the conceptual complexity is too high for many programmers. On the other hand, those will not be the ones designing your architecture. Mixed feelings about this one.

      Unfortunately they quite likely will be the ones maintaining and extending it for new features. Most folks can understand things they wouldn't be able to invent, so if your maintenance guys are at that stage, that's fine. If they're not, quite, you got trouble.

    5. Re:Some of these things are not like the others by R3d+M3rcury · · Score: 1

      As a cynical estimate, at least half of the people working as programmers are lousy.

      Well, by definition, 50% of programmers have below average skills. Of course, 50% have above average skills.

  42. You're probably using GOTO every day by scdeimos · · Score: 2

    Most language compilers are using goto constructs under the covers already. Disassemble some MSIL, for example, and you'll see how there are some in every single if-else or switch-case block.

    1. Re:You're probably using GOTO every day by Anonymous Coward · · Score: 3, Insightful

      Goto is considered harmful for humans. Who cares what happens under the covers. Hot liquids are harmful for humans. The fact that there are hot liquids under the covers when you drive your car is irrelevant.

    2. Re:You're probably using GOTO every day by angel'o'sphere · · Score: 1

      Wow, how insightful.
      How else should a compiler generate machine or byte code?

      --
      Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
    3. Re:You're probably using GOTO every day by Anonymous Coward · · Score: 0

      > Goto is considered harmful for humans.

      A Goto killed my father. :(

  43. Stay away from the Knives, and the Stove too! by Anonymous Coward · · Score: 3, Insightful

    I'm tired of this mentality. I'd rather we favored those with skill rather than those with a lack of it. We as a people would go much farther.

    Do you cripple the use of bicycles by forcing everyone to ride with training wheels? Or do we in fact favor those who can ride and instead burden the new-comer with the difficulties around obtaining and installing training wheels on very poor low-end bicycles?

    Why should coding be any different? Sometimes people craft very complex and difficult pieces of software that tie together more than 20 libraries all which have their own quirks. I need the ability to share raw pointers, I need the ability to avoid ref-counting or shared_ptrs. I need to sometimes work with systems that have their own scheduler (Erlang, cough) and then bind C libraries into that ecosystem which doesn't allow blocking for more than 1ms. So I need crazy thread logic sometimes and odd code to support linking two separate mutex idioms from 2 different libraries so the lock works across the boundry....

    Sometimes I just wish to be left alone in a complex space where another soul's mere presence is essentially proof of their abilities and understanding of logic. Similar to how adults sometimes wish to leave behind children and mingle only with other mature adults, I desire this of a programming language. Something to scare away all the posers and poor misguided (but righteous and well meaning) individuals.... It's not elitist thinking just like Adults aren't really being rude when trying to mingle with other like-minded adults.... it's more of a time-saver for people who find that many "adults" are actually children in disguise and only after 30 minutes of talking can you determine they are fake. I grow tired of wasting my time and eventually wish to move to a place where it's harder for the fake to blend in. It was amazing going from finding 1-2 good people every 50 to instead finding 1-2 good every 10.

    For me that language has been C++ and simply put it's the most amazing thing I've ever discovered in my programming career. I also love how everyone still is scared to death of it and clamoring for it's deprecation while simultaneously using programs written in C++ to post these complaints.

  44. ShIt coders by Anonymous Coward · · Score: 1

    If you think a certain construct is somehow inherently bad, you are a shit coder. There is NOTHING wrong with goto, multiple inheritance, etc. They all have there uses. If you think they are bad. STOP. I deal with idiots like you all the god damned day, and I'm sick of it.

  45. The Recursion Cult by Zobeid · · Score: 2

    I think some time in the misty past (1970s?) recursion went through a fad phase, and it was hailed as the solution to every programming woe, not to mention the secret key to artificial intelligence. I can remember studying Logo (which is a variant of LISP) at one time. Logo composed every function call recursively: when it hit a key word that required arguments, then it would put that on hold and go looking for those arguments, some of which might be keywords that required their own arguments, etc. That's not unique among programming languages, but the syntax provided no clues or organization: no parenthesis, no brackets, no braces, just a string of words, and the only way to figure out which was an argument to what was if you already knew (or stopped to look up!) how many arguments each word takes. But supposedly you wouldn't need help reading it because it's recursive, and recursion is wonderful magic.

    Incidentally, Forth suffered from a similar readability problem, but at least it executed way way way faster.

    The other thing I remember about Logo and recursion was the textbooks and tutorials trying to teach me how every loop could be done using recursion -- and should be! Why would you do that? Because it's the Logo Way, of course. And because recursion is wonderful magic.

    It was overly complex and inefficient, to be sure. However. . . I happily use recursion for actually recursive tasks, such as traversing various kinds of tree structures.

    1. Re:The Recursion Cult by david_thornley · · Score: 1

      Incidentally, Forth suffered from a similar readability problem

      I always found well-written and reasonably documented Forth readable. By documented, I mean each word has an inline comment showing what it does to the stack, and everything has meaningful names. I thought Forth was a lot of fun, and where else do you find ": ? . ! ;" to be part of a language definition?

      --
      "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
  46. Iffy resources by fyngyrz · · Score: 2

    Here's a much better pattern for you, in a c-ish form:

    How to manage iffy resources in a structured manner

    You can generalize that pattern into almost any situation and it will work well. If you need details, then instead of true/false, pass can be a value or a bit mask, etc. and then the check at the end can be verbose about what exactly went wrong. Essentially still the same pattern.

    --
    I've fallen off your lawn, and I can't get up.
    1. Re:Iffy resources by vux984 · · Score: 1

      The thing I don't like about that pattern is that

      1) the nesting can get pretty deep. imagine you had to do a bunch of file operations and had to check for errors after each of them. You could easily be nesting 20+ deep.

      2) the nesting for the basic error checking totally obscures the logical structure of the actual code.

      You can't assume the resources are allocated at the front, and unwound at the end as you might only need some resources in certain conditions. So now you've got the real program logic mixed in with the success-test nesting. And the actual flow control logic becomes invisible, lost in a mess of library call 'success test' nesting.

    2. Re:Iffy resources by fyngyrz · · Score: 1

      It's only a basic pattern for the example case provided (which was, you will observe, all resources required up front.) You adjust as needed, or use something else as needed. It's programming, not rote behavior. :)

      --
      I've fallen off your lawn, and I can't get up.
  47. Absolutism is a problem by fyngyrz · · Score: 1

    You do realize there are CPUs with user stack pointer(s), right?

    You do realize there are cases where the recursion is limited in depth based on the nature of the problem, rather than the size of the data, right?

    You do realize there are languages where the amount of data involved in the levels of the recursion can be precisely controlled, right?

    It's not as black and white as "recursion bad, mkay?"

    --
    I've fallen off your lawn, and I can't get up.
  48. GOTO and the Wild West by Zobeid · · Score: 2

    To understand the revulsion some hold toward GOTO, you have to mentally turn back the clock to a time when it was used for almost everything. Back in the wild west days of computering, there were no conventions for organizing program code. There was no Structured Programming. Early languages provided simple branching tools (like IF-GOTO) but no guidance. A good programmer would soon figure out his own way of organizing his code, and he could become quite productive. The problem was, everyone had their own individual, eccentric methods, and looking at somebody else's code was often confusing. Then structured programming came along, and it provided (or some might say imposed at sword point) a common organizational methodology and a common vocabulary. Two programmers who were trained in the doctrine of structured programming could read one another's code much more easily.

    If you see the keywords and indentation of a WHILE-REPEAT loop, or a REPEAT-UNTIL loop, or an IF-THEN-ELSE condition, then you already have a clue, you already have a starting point to understand what the code is doing. If you see GOTO, then it communicates almost nothing. Then you have to look at the context. There may also be some code comments. It may not be a problem, and in today's environments there's no reason why it should be. This isn't the wild west anymore, and we don't use GOTO for everything. If it's there, somebody presumably had some reason for it.

  49. I miss multiple inheritance in Java .... by Anonymous Coward · · Score: 0

    regularly. About every other month. It's kind of eerie how reglarly it happens that I'm saying 'this is an A and a B with some new stuff but I can't do this can I" to my java IDE.

    1. Re:I miss multiple inheritance in Java .... by lgw · · Score: 1

      regularly. About every other month. It's kind of eerie how reglarly it happens that I'm saying 'this is an A and a B with some new stuff but I can't do this can I" to my java IDE.

      Java added back multiple inheritance via "default implementation of interface methods". It's awkward, but that's java for you.

      --
      Socialism: a lie told by totalitarians and believed by fools.
  50. Before "nitpickers" catch it? by Anonymous Coward · · Score: 0

    See my subject: Missing an "end" after 2nd block (not really needed though, can just use then & statement) & not using APKTest42 var (I do both in my real code that's yet to have a bug or security issue found in it 4++ yrs. after public release & it's proven safe/clean by many security pros on audit + antivirus tests) using an IF statement in those blocks to spit an abend/error IF it doesn't return 1/clean (vs. 0 dirty/bad).

    Plus, some indenting took a beating on paste (I just posted what my code has outta the Delphi XE4 IDE - /. seems to disagree on it).

    APK

    P.S.=> Yes, I just HAVE to do that, or I'd never hear the end of it from 'nitpickers' & trolls - this IS the price of editing on Slashdot (especially for us AC posters - our postlength is SEVERELY limited vs. registered 'lusers') & yes, the price of my being in a hurry this a.m. too admittedly (I should've used preview 1st)... apk

    1. Re:Before "nitpickers" catch it? by Anonymous Coward · · Score: 0

      Stop sperging you dumbfuck

    2. Re:Before "nitpickers" catch it? by Anonymous Coward · · Score: 0

      Apk is obviously more intelligent and useful around here than you are unidentifiable troll. Get on topic, offer something useful and concrete as apk did and quit stalking and trolling apk you lunatic whacko.

    3. Re:Before "nitpickers" catch it? by Anonymous Coward · · Score: 0

      I don't know what is sadder, APK assburgers or his psychotic need to defend himself by pretending to be a fan.

      Both are fucking retarded.

    4. Re:Before "nitpickers" catch it? by Anonymous Coward · · Score: 0
    5. Re:Before "nitpickers" catch it? by Anonymous Coward · · Score: 0

      wtf

      APK is a sperging asswipe and he posts AC to defend himself.

      You have never posted anything intelligent or on-topic. If you aren't careful you fuckstain, you will end up on encyclopedia dramatica as its newest lolcow and assburger.

    6. Re:Before "nitpickers" catch it? by Anonymous Coward · · Score: 0
  51. Re:Eval is a Beginners' Trap and a Huge Security H by willy_me · · Score: 1

    Same for MATLAB. In fact, the MATLAB documentation indicates that eval should be avoided.

  52. Begs the question by chuckugly · · Score: 1

    In what way does it beg the question?

    1. Re:Begs the question by Skidge · · Score: 1

      I'm disappointed in you Slashdot readers. I had to scroll nearly all the way through the comment to find the first "Begs the question" complaint.

    2. Re:Begs the question by chuckugly · · Score: 1

      It was supposed to my day off watching for this stuff. Sorry.

    3. Re:Begs the question by Godwin+O'Hitler · · Score: 1

      To be fair, "to beg the question" is a particulary stupid way in this day and age of saying "to reason in a circle".
      And to be fair to both sides, "to beg" is a particularly stupid way of saying "to raise".
      Beg someone for something -- food, mercy -- yeah sure. Beg a question for something -- no, I'm not that desperate.

      --
      No, your children are not the special ones. Nor are your pets.
    4. Re:Begs the question by Anonymous Coward · · Score: 0

      I'm disappointed in you Slashdot readers. I had to scroll nearly all the way through the comment to find the first "Begs the question" complaint.

      Seems you missed this comment.

  53. Nerd dumbasses. by Anonymous Coward · · Score: 0

    I can sum this up as, "ONLY A SITH DEALS IN ABSOLUTES HURRRRR!"

    It's a stupid nerdy soundbyte that doesn't even make fucking sense at face value. Just like, "RECURSION IS BAD HURR".

    1. Re:Nerd dumbasses. by Anonymous Coward · · Score: 0

      "Is recursion more powerful, Master Yoda?"

      "Hmph. No. Simpler; easier, more seductive."

  54. Re: Doesn't care by hackwrench · · Score: 1

    Recursion isn't what allocates the stack frames. Limited compiler translate the recrsive algorithm into code that allocates the stack frames. I'm not sure, but I suspect that there is plenty of room for compiler optimization compared to what they are doing now, but I am not certain that they are still doing as you say they are.

  55. Re: Your own stack by hackwrench · · Score: 1

    And what are you doing with that stack if still not recursion. You don't just magically make it 'not recursion' by implementing one element that you didn't even change the name of differently

  56. Sorry, but "creative use" of any feature ... by Ihlosi · · Score: 2
    Sorry, but "creative use" of any feature of a programming language might impress your geek buddies, but it will also make your code utterly hard to comprehend and maintain for anyone - including yourself - in a matter of a few months.

    (And I'm not saying 'goto' is a bad thing. Using it to uncreatively break out of multiple nested loops or do error handling is easier to understand than the alternative. Also, in about every programming language, there are pretty much always several ways to achieve a certain behavior. The one that is easiest to understand should be chosen unless there are pressing reasons for one of the other ways.)

    Disregard my rant about maintainability if you code one-shot things that no one - including you - will look at again once you're done.

  57. Re: What reason by hackwrench · · Score: 1

    Internal company politics, probably.

  58. GOTO and the arguments for it by angel'o'sphere · · Score: 1

    I don't get why people defend the usage of GOTOs with claws and teeth.

    In modern languages, and that includes C, the question if to use or not to use a GOTO never was an issue!

    The phrase 'GOTO considered harmful' comes from times where the predominate language was FORTRAN!!!

    In FORTRAN you easily see a 1000 lines program with 1 or 2 dozens of GOTOs, where the same program written in proper C or Pascal (and any other modern language) has zero.

    Furthermore, the example of 'good use of goto' given in the linked article is bollocks. I would fire (or educate) a programmer giving me code like that.

    --
    Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
    1. Re:GOTO and the arguments for it by lgw · · Score: 1

      How on earth would you write "safe C" without goto? Deeply, deeply nested if blocks, adding a layer of indentation below every function call? That's the stuff of nightmares. Heck, the MS compiler added the goofy __try, __leave, and __finally statement just to encourage proper use of goto in C code, by calling goto something different.

      --
      Socialism: a lie told by totalitarians and believed by fools.
    2. Re:GOTO and the arguments for it by __aaclcg7560 · · Score: 1

      In FORTRAN you easily see a 1000 lines program with 1 or 2 dozens of GOTOs, where the same program written in proper C or Pascal (and any other modern language) has zero.

      For a while I was converting old BASIC games that I never got to work as a kid in the 1980's into Python scripts. Some BASIC games had an elaborate "fall through" decision structure at the end of the program that made it difficult to trace all the GOTOs going in and out. The behavior was in some ways similar to a SWITCH statement. Of course, Python has no SWITCH statement. Rewriting these GOTOs into function calls was an education in itself.

    3. Re:GOTO and the arguments for it by angel'o'sphere · · Score: 1

      I don't know.
      I never needed to write such code.

      I doubt it exists :D

      And that was not the point anyway.

      Neither Djikstra no any one else is arguing against "proper use" of GOTOs but against ABUSE, perhaps you want to reread my post you answered to.

      --
      Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
    4. Re:GOTO and the arguments for it by angel'o'sphere · · Score: 1

      Interesting. Did not know about the lack of a switch in Python.
      This is interesting: http://stackoverflow.com/quest...

      --
      Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
    5. Re:GOTO and the arguments for it by lgw · · Score: 1

      Well, your claim of "I don't get why people defend the usage of GOTOs with claws and teeth." was rather broad. People defend proper use of goto in C fiercely, because of the constant stream of idiots who've never worked with that sort of code, but are sure it must be wrong, because they read that somewhere.

      --
      Socialism: a lie told by totalitarians and believed by fools.
    6. Re:GOTO and the arguments for it by angel'o'sphere · · Score: 1

      People defend proper use of goto in C fiercely
      Then reread my post.

      The defend it fiercely because they don't understand the meaning of "GOTO considered harmfull".

      Again: the resonating phrase was coined in a context where roughly every 20th statement was a GOTO. It never was meant to abolish GOTOs in situations where it is the straight forward solution.

      because of the constant stream of idiots who've never worked with that sort of code, but are sure it must be wrong
      I don't think such idiots exist. I never met one and I definitely did not meet one in this discussion on /.

      Or to close the circle: I would not distinguish between "those idiots" and the "idiots who immediately jump on the bandwagon of pointing out rare situations where a GOTO is appropriated" ... both are the same idiots for me. Both don't grasp the historical context of the phrase.

      --
      Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
    7. Re:GOTO and the arguments for it by lgw · · Score: 1

      Again: the resonating phrase was coined in a context where roughly every 20th statement was a GOTO. It never was meant to abolish GOTOs in situations where it is the straight forward solution.

      Almost no one in the industry today understands that context. C programming standards around the world ban goto thoughtlessly. That's about like demanding all your devs use VI - of course there's a fierce holy war as a result.

      --
      Socialism: a lie told by totalitarians and believed by fools.
    8. Re:GOTO and the arguments for it by Anonymous Coward · · Score: 0

      Guido is a dumbfuck.

      The self exists because Python used to not have any type of scoping, he explains it away as "explicit is better than implicit". Moron!

      People who use Python are as retarded as the imbeciles who use PHP.

    9. Re:GOTO and the arguments for it by angel'o'sphere · · Score: 1

      In my over 30 years of software development:
      1) I never had a coding standard where gotos were banned
      2) I never saw a goto in any C or C++ code ... except on internet forums where it was attempted to be justified (usually very bad examples)

      But again: I'm not a zealot against gotos.
      I'm rather a zealot against discussing gotos ... sounds like a waste of time, seeing 1) and 2)

      --
      Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
  59. Re: Doesn't make it not recursion by hackwrench · · Score: 1

    Using your own stack doesn't make it 'not recursion'.

  60. GOTO is dead.We live in COMEFROM age. by 140Mandak262Jamuna · · Score: 3, Insightful
    I wonder what Djikstra would say about the modern development API and the GUI. He railed against unstructured GOTO statements, back in 1968.

    But the entire modern GUI API is based on "event driven" programming. Replete with "OnRightButtonDown()" , "OnWindowClose()" ... . These are nothing but COMEFROM statements. COMEFROM could be as harmful or even more harmful than GOTO. With a good design based on a valid state machines and object oriented code we not only handle these with east, we are successfully developing incredibly complex code.

    So, no. We did not forget GOTO just because some authority figure railed against it. We replaced it with a better concepts like event loop, event dispatching, object orientation.

    --
    sed -e 's/Chuck Norris/Rajnikant/g' joke > fact
    1. Re:GOTO is dead.We live in COMEFROM age. by phantomfive · · Score: 1

      He wasn't rigidly against GOTO. He liked programs to be structured in a way that they can be proven correct if necessary.

      --
      "First they came for the slanderers and i said nothing."
    2. Re:GOTO is dead.We live in COMEFROM age. by ChrisMaple · · Score: 1

      Typical GUI code is write-only. They are mostly indecipherable messes, although this may be due to the way libraries like Gtk and Qt are put together.

      Anyway, "comefrom" is useful for GUI and interrupt handling, but is inapplicable to the areas where the real work is done - any sort of complicated math or data analysis. There, goto can be useful.

      Object Orientation is related to goto the same way balloons are related to spiders - that is, there's no relation.

      --
      Contribute to civilization: ari.aynrand.org/donate
    3. Re:GOTO is dead.We live in COMEFROM age. by Anonymous Coward · · Score: 0

      A cardinal sin of programmers with imperative mindset is that they concentrate on changes instead of what is supposed to not change. Y needs to change when x changes so lets signal y to update itself etc, repeat ad infinitum. This leads to madness(*) when there's a large enough number of x's and y's. The number is typically somewhere between "toy project" and a "real project".

      Fuck that shit. If y is derived from x, it shouldn't be possible without going through extra hoops to NOT have it updated when x changes.

      *) init-order issues, leaky listenerlists, components fighting each other, inconsistent state..

  61. Really? by John.Banister · · Score: 1

    And, after this, we'll see and article titled "Developer argues for unilateral editor switch" that ends in "it begs the inevitable question. Are you ditching emacs in favor of vi -- and should you be?"

  62. Like Terry Pratchett said by chthon · · Score: 1

    "It's sometimes better to light up a flame thrower than to silently curse in the dark"

  63. Do *not* spider web with recursive function calls by raymorris · · Score: 1

    > Without recursion, data structures like trees or graphs are useless. Kind of a problem if you have a directory tree structure, or you want to follows URL links for web scraping.

    I would say web scraping is a good example of when you should NOT use a recursive function. My first web scraper looked like this:

    scrape_page(url) {
          links = get_links(url);
          foreach(link in links) {
                  scrape_page(link);
            }
    }

    On a site like Slashdot, which has many pages (on for eaxh comment posted), that fails wonderfully.

    My i improved version, which has been running successfully for many years, looks like this:

    scrape_page(url) {
          links = get_links(url);
          foreach(link in links) {
                  add_to_queue_database(link);
            }
    }

    Note scrape_page no longer calls itself, it's not a recursive function. It's driven by this main() function:

    while (url = get_url_from_queue_database() ) {
            scrape_page(url);
    }

    The queue is held in a database which can easily store hundreds of thousands or millions of urls, There is no recursive function and it doesn't die when spidering a forum. It also doesn't lose all its queue when stopped and restarted.

    Some people would point out this solves a recursive and say it's therefore a recursive algorithm. The algorithm isn't recursive by definition because no function calls itself, even indirectly.

  64. Limitations for bad programmers by bussdriver · · Score: 1

    Good programmers may not be commonplace and that in itself might be to reason to ban freedom and make everything as constrained and idiot proof as possible... I'm not one of those people... I am for formal language "modes" where you can specify your skill level. Then GOTOs can be forbidden except for those who have an approved skill level.

    As we should all know, loop and if constructs are merely specialized use cases for GOTO. Not every situation has been abstracted into a safe language construct. C lacks the ability to break out of nested loops, same with C++. One has to work around the language constraints adding complexity and performance loss. Now adding an argument maybe a label could have provided another abstraction for another GOTO use case for specifying the loop to jump to.

    Exception handling is another abstraction use case for GOTO. Along with the "come from" event model we use which is especially awkward in async and parallel situations. These continue to have poor abstractions that add complication trying to do things that a GOTO or an evolved GOTO would address. I'm saying we should leave power tools around for those who know how to use them so that better abstractions can be created for the lesser programmers. Exceptions being a great example which really couldn't be done without an evolved GOTO but behind the scenes language programmers did all the difficult work. For async event callback coding we currently have kind of a mess everywhere with Java 8 being an impressive hack but only to bring it into the same mess.

    How about call back closure situations where you flip the situation and have the code block until the async completes but it jumps to a function or up the call stack for the idle running code. Quite often you have the a where you just want to spawn async tasks and the response to the async task belongs right next to it (hence the popularity of closures.) So now you don't have closures, it just blocks and life is easier "the fork in execution" instead is jumping to the idle code instead of jumping to the callback code. Do I make myself clear? The OS does this already for processes-- your process blocks without any concerns and the OS shifts processing elsewhere.

  65. GOTO is fine! by Murdoch5 · · Score: 1

    Developers who speak out against GOTO, show their amateur or assumed armature level or experience. `I had a prof in University who spoke out strongly against it, even going to lengths such as costly loops and costly checks to get around using a simple GOTO, his code was made worse because he refused to use it. If you honestly feel GOTO is an unexceptionable statement in programming, then please write a program in ASM and NEVER use JMP!

  66. "a much better pattern" by bool2 · · Score: 1

    That's a bit subjective. I think I would call it an alternative pattern.

    I have seen it work well but more often than not I have seen create code that looks like an arrow. In real life, outside of trivial snippets, arrow code can be horrible to read and maintain. That's not always the case though hence I don't say it's a "worse" pattern - just an alternative.

  67. Forgotten? by allo · · Score: 1

    Maybe if you use some new hipster frameworks. Real programmers know their constructs and when to use them.

  68. Python is the wrong language by tepples · · Score: 2

    By your criteria, Python is the wrong language, and this is intentional. See Guido van Rossum's explanation: part 1 and part 2.

    1. Re:Python is the wrong language by Pseudonym · · Score: 1

      To be fair, Python is the wrong language.

      --
      sub f{($f)=@_;print"$f(q{$f});";}f(q{sub f{($f)=@_;print"$f(q{$f});";}f});
    2. Re:Python is the wrong language by Anonymous Coward · · Score: 0

      Guido is a dipshit on par with Rasmus.

      His "argument" boils down to 'It's hard to provide good stack traces" and "But but Jython!"

      What a moron.

      The fact that the Eve client runs on Stackless and not CPython is a testament to his idiocy.

      His cult drinks it up and spews the bullshit he says like it is godly.

  69. Re:Eval is a Beginners' Trap and a Huge Security H by david_thornley · · Score: 1

    Eval is not something to be used casually, but it's vital to how some languages work. My general rule is that, if you use it while writing application code, it's probably a mistake, but it can be very useful in libraries to do things and the like. Much like C++ template metaprogramming: very powerful, and most people should leave it for someone else to write.

    --
    "When you have eliminated the unacceptable, whatever is left, however improbable, must be the truthiness" - Holmes
  70. Re:Do *not* spider web with recursive function cal by Megol · · Score: 1

    I'd say that's still recursive however with a buffer.

    Map the data flow and you should see why I think it's still recursive...

  71. Re:Do *not* spider web with recursive function cal by JesseMcDonald · · Score: 1

    Some people would point out this solves a recursive and say it's therefore a recursive algorithm. The algorithm isn't recursive by definition because no function calls itself, even indirectly.

    The algorithm is still recursive; the recursion is just built in to the language in the form of predefined iteration constructs like "foreach" and "while". Any time you have an iterative program of the form "first do X, and then repeat the process for the remaining input", that's recursion: one of the steps in the process (the repetition) is defined in terms of the process itself.

    Some recursive algorithms can run in constant space, while others (such as most operations on trees) inherently require more space to process larger inputs—even when implemented "iteratively". The space used does not depend on whether the recursion is implemented with explicit function calls or loops, but rather on the quality of the compiler, including, but not limited to, tail-call optimization. Far from being complex wizardry, this optimization is really just the correction of a common implementation flaw wherein a function's stack frame remains allocated until the function returns, rather than being freed once it is no longer needed. This simplifies the compiler slightly at the cost of forcing the programmer to distinguish between implicit and explicit recursion, thus impairing the readability of naturally recursive algorithms and sparking endless debates over what ought to be a trivial difference of coding style with no runtime effect.

    --
    "The state is that great fiction by which everyone tries to live at the expense of everyone else." - Bastiat
  72. Re:Eval is a Beginners' Trap and a Huge Security H by K.+S.+Kyosuke · · Score: 1

    It may be very well advisable for Matlab's eval, especially since Matlab itself is better avoided. In other languages, you can often use COMPILE instead of EVAL anyway. (Chances are that this is what you actually want to do in many cases.)

    --
    Ezekiel 23:20
  73. Idiots by Anonymous Coward · · Score: 0

    People who adhere to taboos only restrict their view of what is possible, i call such people idiots.

  74. Re:Do *not* spider web with recursive function cal by raymorris · · Score: 1

    Arguments might be avoided by saying it's not a recursive FUNCTION - no function calls itself, can't run out of stack space. It *is* a lot like what happens when you start with a tail-call recursion then remove(?) the recursion. If somebody wants to call it a recursive algorithm I feel no need to really argue about it, though I will ask you a question or two.

    > Any time you have an iterative program of the form "first do X, and then repeat the process for the remaining input", that's recursion: one of the steps in the process (the repetition) is defined in terms of the process itself.

    Care to point to which step "is defined in terms of the process itself"? I don't see that anywhere.

    It's very similar to recursion, but my understanding of the definition of recursion is that the definition/implementation of X must reference X. I don't see that in my code anywhere.

  75. Definition: X defined using X by raymorris · · Score: 1

    What's your definition of recursion? My informal definition:

    X is recursive if and only if X is defined / implemented by calling X, directly or indirectly.

    One dictionary definition is similar:
    A routine, function etc in which a part is defined in terms of the whole.

    Just because the output of a function X(a) may be, at some later time, be passed to another seperate instance of X(b) doesn't make it recursive, imho, if X(a) TERMINATES before X(b) begins, because X() makes no reference to itself.

  76. Alternative definition by raymorris · · Score: 1

    Here' s an alternative definition:

    A recursive algorithm is defined as any algorithm which is recursive. ;)

  77. Moderation by Anonymous Coward · · Score: 0

    In all cases, the answer is, it should be used sparingly, and after the question is asked "Is there a better way?".

    Recursion, I use rarely-- but the last case was enumerating all the members of an active directory group. It was the cleanest way to implement the function (if user object, insert into hash. If group, call function again).

    Similarly, while "goto" should be avoided as a general practice, sometimes, it's the only way to get your code where it needs to go-- but it should always be regarded with suspicion.

    "eval" is a fantastically useful function, but you need heavy validation on anything being handed to it, unless you want eval to be fantastically useful for hackers, or you enjoy debugging bizarre code behavior.

  78. ERLANG! by Anonymous Coward · · Score: 0

    As an Erlang programmer I endorse recursion

  79. Can't go without Recusion, needbe must goto recurs by manojkg · · Score: 1

    Goto does ease redability of complex logical jumps .. and would still be a prefer choice. Recursion bit difficult(or impossible) to replace -- it may change in syntax, and may be called something else, but at core recursion does exist -- whether in parser, far known leaf node traversal, email parts parsing etc etc.... They both are neat and clean ... I always support them, and use them as and when necessary.

  80. GoTo redux by Anonymous Coward · · Score: 0

    In days of yore, it was said that Niklaus Wirth, inventor of Pascal and GoTo hater supremo, had to use a single GoTo in his famous compiler found in old AppleII's with the Language Card.

    Fact or Fiction?

    1. Re:GoTo redux by Anonymous Coward · · Score: 0

      It's fiction that Wirth had anything to do with Apple's Pascal compiler. That was written by Bill Atkinson (though based on UCSD Pascal, which was based on Urs Ammann's paper - and he was a student of Wirth's.

  81. "GOTO considered harmful" considered harmful by DutchUncle · · Score: 1

    A chainsaw don't know the difference between a log and a leg. But sometimes it's the right tool.

    http://web.archive.org/web/200...

  82. Y2K overstated by hawk · · Score: 1

    What most people miss on Y2K is that given the constraints at the time most of those programs were written, the cost of avoiding the problem would have been roughly triple (in real terms, discounted dollars, etc.) as ultimately fixing it was.

    Yes, economists went back and actually measured, estimated, etc. Also, most of the code from the era did not, in fact, make it to Y2K, and would have incurred the costs without receiving a benefit.

    Although the resources would be negligible today, we are talking about the extra labor to punch two more digits on each and every 72 column card, the limited number of digits on those punch cards, memory for which it was a break thought when the *rental* price dropped down to a buck a byte a month, the extra processing time to handle three or four digits, etc.

    It also didn't help that so many (a strong majority?) coded in the year ending in 00 exception to leap years without including the divisible by 400 exception to the exception . . . other attempts to accommodate 2000 might have had similar blunders.

    hawk

  83. Re:Eval is a Beginners' Trap and a Huge Security H by tepples · · Score: 1

    It is rarely "the right thing," typically because it is super inefficient.

    In compiling implementations of programming languages, it's anything but inefficient.

    More and more platforms have begun to establish Data Execution Prevention (W^X) policies that give third-party applications no way to flip a page from writable to executable. These include iOS, Windows Runtime, and current-generation game consoles and gaming handhelds. Thus all compilation to native code must be either done ahead of time before packaging or done by an operating system component, such as WebKit JavaScript in iOS.

  84. Dijskstra and Algol by Anonymous Coward · · Score: 0

    Decades ago there was a programming language called Algol. It was the basis for the Burroughs computers. Look up in a history book. But Edgar Dijkstra ran much of the Burroughs corporate research and one of his papers (buried somewhere one of my in those vertical file cabinets) was a look at how recursion was actually used in production programs. It turned out that five levels of nesting was enough to handle 95+ percent of actual code. That is really nothing! So I would not feel bad about using recursion. If you want to have some fun, code the Ackerman function and try running it :-)

  85. Forgotten? Forbidden? by drolli · · Score: 1

    (Exclude recursion here - i think he talks about the examples given in school for recursion, which often are not good in terms of resource usage)

    About the rest: Bullshit. These are not forgotten, and they are forbidden in most coding guidelines for a reason. His musing about that goto is only bad if you jump "backwards" is borderline funny.

    There is a reason that goto should only be used in extremely rare occasions (and i would agree that some of these *may* be for kernel programming). The examples of this "programmer" are excellent examples why for people like him these should be forbidden. Any of his examples are better off without goto, and if you don't see a more efficient, clearer and safer solution without his shit, you should not program any high-level language.

    Eval is another piece of cake (I exclude python here because it seems to get eval right). My practical experience is that i is rather overused by inexperienced programmers. Filtering a string that should be evaled in a way that it has a predictable outcome is as difficult as writing an eval. Typically my recommendation would be that evals need to be a) sanctioned by a senior developer (just to make sure nobody uses these out of pure incompetence) b) encapsulated in a function (e.g. for the dection of a laguange feature/level) c) filtered carefully if they accept user input.

  86. It doesn't "beg" the question... by Anonymous Coward · · Score: 0

    ...it "raises" it.

  87. I've used them by Stubbyfingers · · Score: 1

    GOTO was kinda special...It was to either completely exit a procedure when the input conditions were just TOO F'd up.
    Quite often the jump was to the equivalent of a "Halt and Catch Fire" sorta error processing.

    GOD, I LOVED recursion. Of course, I slung a boat load of LISP code in my younger days.

  88. How about infinite loops? by lbates_35476 · · Score: 1

    Some would say this is bad programming, but if you are programming a pacemaker, heart monitor or the like, an infinite loop is EXACTLY the construct you want. I've written some pretty ugly code (breaking out of deeply nested loops) when a simple GOTO would have cleaned things up a lot. They are all tools that have a place and time to be used.

  89. Re:Do *not* spider web with recursive function cal by JesseMcDonald · · Score: 1

    Care to point to which step "is defined in terms of the process itself"? I don't see that anywhere.

    It's part of the compiler's internal definition of the loop construct, and does not appear in the source code. In the object code it can be identified as the opcode that branches back to the beginning of the loop.

    This becomes more obvious if you consider programming languages where iteration is not a built-in construct, and loops are written in terms of explicit recursion. In Haskell, for example, a simplified C "while" keyword (disregarding "break", "continue", etc.) could be implemented as the following recursive function:

    while :: Monad m => m Bool -> m () -> m ()
    while cond body = cond >>= \c -> when c (body >> while cond body)

    Or using the fixpoint operator, without referencing the current definition by name:

    while cond body = fix (\loop -> cond >>= \c -> when c (body >> loop))

    Building on the fixpoint example above, would you call this a recursive function?

    void f(void (*g)(), int c) {
    if (c < 10) g(g, c + 1);
    }

    Sometimes it isn't so simple. The body of f() does not refer to f(). However, what happens if you call f(f, 0)? The function might be recursive, or it might not be, depending on the arguments. It all depends on that function pointer.

    Arguments might be avoided by saying it's not a recursive FUNCTION - no function calls itself, can't run out of stack space.

    It's not a recursive function, since it's not the entire function that's repeated. It would be more accurate to say that it contains a recursive function, though that inner function is hidden behind the loop construct. Barring the use of alloca() or similar it won't run out of space on the function-call stack, since alloca() / variable-length arrays and function calls are the only ways to allocate from the function-call stack, but the iterative version of the function still needs to track the same data and can still run out of memory given large enough inputs—just not stack memory. Sometimes that distinction is important, but more often it isn't, especially given the stack sizes available to programs running on most virtual memory based operating systems, ranging from several megabytes to "malloc() would fail first". (After all, some languages allocate stack frames from the heap.)

    Anyway, the fact that (unoptimized) tail calls use stack space while iteration constructs ordinarily do not is nothing but an artifact of poor compiler implementation, and easily corrected through tail-call optimization. It's really no different from the way some languages with simplistic garbage-collection algorithms (e.g. Perl) fail to collect sets of objects with cyclic references. You can either take pains to avoid cyclic references (tail recursion), or just switch to one of the many modern languages which don't cause arbitrary runtime errors when you write code in the most natural style. Given a reasonable guarantee of tail-call optimization, function calls in general may allocate additional function-call stack space, but a call in tail position won't, so tail recursion is exactly the same as iteration in terms of expected stack use.

    --
    "The state is that great fiction by which everyone tries to live at the expense of everyone else." - Bastiat
  90. Does not need to track parent, not 500 instances by raymorris · · Score: 1

    > but the iterative version of the function still needs to track the same data

    It seems to me that it does not. Looking at the actual state information of my program after running for three years appears to confirm that.

    In a moment, you may wish to refer to my code posted above, but we'll start by talking about the clearly recursive version.

    Some years ago, I pointed my spider at a large, deep directory of urls with many links. Imagine dmoz.org. Since then, it's followed links several million deep. Were it recursive (in the traditional sense), there would now be several million copies of the function *running*, each with a stack pointer to its parent. For the URL it's currently spidering, we'd have the full history of how it got there, the url that linked to it, all on the stack. Also any other variables local to the function would still be live in memory - millions of instances because millions of instances of the function are still running.

    Using the iterative algorithm I posted above, I think you can see that we do NOT track any data whatsoever about how we got to the current URL. All of the information about past pages, which would be on the stack in a recursive algorithm, do not exist in my program. So in fact it does *not* "track the same data" and your idea that it "can still run out of memory" is disproven by the fact that it's been running for years, millions and millions of iterations, and it's still using the same 3MB of RAM that it started with, plus a few MB for the queue.

    You are certainly correct that you *can* simulate iteration by using recursion. That doesn't mean you must.

    The key point, to me, is that at least what I mean by "recursive" is that there is a parent and a child. The parent doesn't return/exit until its child does - and its child, and its child, and its child, and its child ...
    With the iterative algorithm, one completes, and releases all of its memory, then another one starts. There is only one instance running at any given time, and therefore only one copy of the variables. There is no "parent", only "previous", which has no other relation to the currently running code - the previous URL isn't even the one that linked to the current url!

  91. Re:Does not need to track parent, not 500 instance by JesseMcDonald · · Score: 1

    Using the iterative algorithm I posted above, I think you can see that we do NOT track any data whatsoever about how we got to the current URL. All of the information about past pages, which would be on the stack in a recursive algorithm, do not exist in my program. So in fact it does *not* "track the same data"...

    You're comparing apples and oranges. The iterative version of your program is not using the same algorithm as the recursive version. You replaced a depth-first search with a breadth-first search, which makes your example completely irrelevant for comparing iterative vs. recursive implementations of the same algorithm. Among other things, the order in which your web crawler visits pages is very different in the iterative version. To maintain the original order you would need to restore the depth-first search algorithm, which would imply tracking the chain of pages you came from—exactly like the recursive implementation, though you could store that information on the heap or in a database rather than on the stack. (Note that a tail-recursive implementation would also store that information on the heap or in a database... this isn't a matter of recursion vs. iteration.)

    You are certainly correct that you *can* simulate iteration by using recursion.

    The tail-recursive implementation is not "simulating" iteration. It is iteration. Expressing the same algorithm with a loop construct rather than an explicit function call would not make it any less recursive; the loop implies a built-in fixpoint operator. If this trivial difference of style makes any difference in how much stack space your function uses, that's a bug in your toolchain.

    The key point, to me, is that at least what I mean by "recursive" is that there is a parent and a child. The parent doesn't return/exit until its child does - and its child, and its child, and its child, and its child ...

    That is not what "recursion" means. Moreover, how would that definition even account for something like tail-recursion, where the "parent" is replaced by the "child"? Logically, the "parent" still does not exit until the "child" does, but in the meantime it occupies no space on the stack and the return from the innermost "child" is also the return from all of the "parents". No matter how deep the tail-calls become, the stack use remains constant. Recursion only requires additional stack space when there is more for the function to do after the call, i.e. when it is not tail-recursion. Such cases cannot be converted to iteration (using the same algorithm) without shifting all the data required by the continuation from the function-call stack into some other data structure.

    --
    "The state is that great fiction by which everyone tries to live at the expense of everyone else." - Bastiat
  92. The web isn't a tree, it's a network by raymorris · · Score: 1

    When we started this discussion, that quote at the bottom of the Slashdot page was James Baldwin
    --
    Those who say it can't be done are usually interrupted by others doing it.
    --

    > The iterative version of your program is not using the same algorithm as the recursive version.

    Okay so you acknowledge there are iterative algorithms, there are recursive algorithms, and not all iterative algorithms are recursive, right? That's an important point.

    > You replaced a depth-first search with a breadth-first search

    In fact it's (mostly) depth-first.

    > the depth-first search algorithm would imply tracking the chain of pages you came from

    Let's try a little experiment. Clear your browser history, then try clicking a link. Amazingly, you can go forward (in depth) without knowing your full history of where you came from! This isn't theoretical, as I said, I've spidered millions and millions of pages, by roughly following the first unvisited link on each page. If I were in the mood, I'd give you a core dump from my spider and you'd notice that nowhere in the core does it have the starting page from several years ago. (Unlike a recursive tree walk, which would have that data.) "But how do you get back, to follow another branch?", you may ask.

    The first thing apparent is that once you've spidered a page, you're not going to spider the same page again, so you can forget all about it! There is no need to track all the parents. You need only remember some *unvisited* pages, none of the visited pages. So no, it's not correct to say "depth-first search algorithm would imply tracking the chain of pages you came from". Rather, you must track the head of the branch you did NOT come from. That'll be where you go next if you end up on http://hmpg.net/ (check out that page).

    Further, we're discussing spidering the web, which is first a network, not tree. You seem to be thinking in terms of a tree. More importantly, the web is a real practical, thing, for which I gave an algorithm that's actually been at work for many years, as opposed to walking some theoretical tree. Because of the nature of the web, as a real network, you can discard 99.999% of the information which you would need for a complete walk of a theoretical tree. No need to remember *every* link you didn't visit, you'll never spider every page on the web anyway, and if you wanted to try you could always start back at dmoz.org or *any* large list of links. The network (the actual www) is such that there are many nodes (sites) which connect indirectly to ~every other available site. So the actual working algorithm doesn't know where it came from. What it *does* remember is a list of 1,0000 URLs it can go TO next. That's all it needs to know - where to go next, not where it came from. It ends up being depth-first because I made the list of "next URLs" a 1,000 element LIFO. I've also run it breadth-first by simply working the other end of the list, FIFO.

  93. MySQL Requires Eval by brian.stinar · · Score: 1

    MySQL will not allow table names to be passed in as parameters to a stored procedure [1] [2] [3]. Without eval, there is no way to dynamically use a stored procedure to operate over multiple, different, tables without enumerating all the tables. The code needed for the "safe" approach is massively bigger, n * m, where m is the body of your stored procedure and n is the set of tables you want to operate over. It also requires such a massive degree of code duplication to make it significantly less safe.

    We have a reporting system called MyDBR that requires everything to be done in MySQL or JavaScript. Likely, a stored procedure isn't the best answer for my problems, but it's better than JavaScript. Probably the "safest" answer is to throw away MyDBR and use an actual programming environment to accomplish what I'd like (sane reporting.)

    The entire premise of this article seems odd to me. Who would forget these techniques, unless they never really learned them in the first place? And why would the author want to revisit them? I think because it was a slow news day.