goto thread (split)

Discussion of chess software programming and technical issues.

Moderators: hgm, Harvey Williamson, bob

Forum rules
This textbox is used to restore diagrams posted with the [d] tag before the upgrade.
User avatar
lucasart
Posts: 3030
Joined: Mon May 31, 2010 11:29 am
Full name: lucasart
Contact:

goto thread (split)

Post by lucasart » Wed Jul 31, 2013 8:06 pm

sje wrote:
Ajedrecista wrote:I made a Fortran parser with the help of Internet
"Dear Father, forgive me for I have sinned. Decades ago I taught the evil that is Fortran, just because I needed the money. I deeply regret this and promise never to do it again."

"My son, you are forgiven. You must say ten Our Fathers and ten Hail Marys as a penance. Further, you will never again use the Devil's goto statement no matter how alluring it might be. And if you fear the fires of Hell, you won't even consider the mortal sins of setjmp()/longjmp()."

Perhaps I'm mistaken, but does your program count promotion moves if there are more than one promotion move per text line?
Fortran is a bit outdated, to say the least...

But goto and setjmp()/longjmp() are not evil at all. They are extremely useful. However, in the hands of incompetent programmers, they lead to obscure and unmaintainable code. Then people put the blame on goto instead of the incompetent programmer who writes messy code...

In good quality code gotos are rare, but everytime they are present they simplify code and make it more readable (avoid complicated artificial crap to break out of nested loops for example). You will be surprised to see that even Stockfish has a few goto!

setjmp() and longjmp() are the C equivalent of C++ exceptions. For me they are exactly the same, and using C++ exceptions is not cleaner or prettier than doing these evil "cross function goto". The only difference is that C++ exceptions calls destructors of objects allocated on the stack before the throw statement (stack unwinding). But since destructors are an addition of C++ and do not exist in C, the C++ exception is exactly the same as setjmp() and longjmp(), only with a slight tweak to make it compatible with C++.

So it's neither goto, not setjmp()/longjmp() that are ugly. It's just code written by incompetent programmers that is ugly, and they can write ugly code with or without goto.
Last edited by lucasart on Wed Jul 31, 2013 8:08 pm, edited 1 time in total.
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.

User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 6:43 pm

Re: Some statistics about promotions and underpromotions.

Post by sje » Wed Jul 31, 2013 10:29 pm

A goto is ugly. A setjmp() is uglier. Even continue is bad. There are absolute standards which do not depend on the skill of a coder.

From Symbolic's source directory:

Code: Select all

gail:Symbolic sje$ cat * | wc
   14136   34345  326800
gail:Symbolic sje$ cat * | grep \; | wc
    5459   19596  192462
gail:Symbolic sje$ cat * | grep goto | wc
       0       0       0
gail:Symbolic sje$ cat * | grep setjmp | wc
       0       0       0
gail:Symbolic sje$ cat * | grep continue | wc
       0       0       0

User avatar
Don
Posts: 5106
Joined: Tue Apr 29, 2008 2:27 pm

Re: Some statistics about promotions and underpromotions.

Post by Don » Wed Jul 31, 2013 10:40 pm

sje wrote:A goto is ugly. A setjmp() is uglier. Even continue is bad. There are absolute standards which do not depend on the skill of a coder.

From Symbolic's source directory:

Code: Select all

gail:Symbolic sje$ cat * | wc
   14136   34345  326800
gail:Symbolic sje$ cat * | grep \; | wc
    5459   19596  192462
gail:Symbolic sje$ cat * | grep goto | wc
       0       0       0
gail:Symbolic sje$ cat * | grep setjmp | wc
       0       0       0
gail:Symbolic sje$ cat * | grep continue | wc
       0       0       0
I don't believe in having absolute rules - it's like arguing over indentation. Many people think that goto is acceptable in some circumstances. I use them occasionally when I feel it makes the code clearer, which is rare but not "never." You can always rearrange your code not to use them, but that doesn't always mean it's clearer. I never do a goto to go backwards in the code flow however as that feels very confusing to me.
Capital punishment would be more effective as a preventive measure if it were administered prior to the crime.

User avatar
lucasart
Posts: 3030
Joined: Mon May 31, 2010 11:29 am
Full name: lucasart
Contact:

Re: Some statistics about promotions and underpromotions.

Post by lucasart » Thu Aug 01, 2013 6:03 am

sje wrote:A goto is ugly. A setjmp() is uglier. Even continue is bad. There are absolute standards which do not depend on the skill of a coder.

From Symbolic's source directory:

Code: Select all

gail:Symbolic sje$ cat * | wc
   14136   34345  326800
gail:Symbolic sje$ cat * | grep \; | wc
    5459   19596  192462
gail:Symbolic sje$ cat * | grep goto | wc
       0       0       0
gail:Symbolic sje$ cat * | grep setjmp | wc
       0       0       0
gail:Symbolic sje$ cat * | grep continue | wc
       0       0       0
Eliminating goto is always possible, but not always desirable. No rule about coding standard should ever be an absolute rule. Clearly using goto to replace structured programming techniques (if, loop, functions, etc.) is stupid. But sometimes, structured programming gets in the way and forces you to write complex and messy code to do something that a goto would acheive easily and naturally. There you know that goto is the right choice.

So you can eliminate goto, but that is a religious choice, not a technical one. That's my point.

setjmp()/longjmp() is perfectly fine in C. It should be forbidden in C++ (instead use exceptions). A typical use is to abort the search instantly, without having to set a global variable like abort_search=true, and testing it after each and every recursive call to search() or qsearch(), which pollutes the code. As I explained already it the exact equivalent in the C world to a C++ exception, and C++ exceptions are considered (by some although controversial) as a good programming practice.

I use a C++ exception to abort the search, and it does it instantly and in a 100% reliable way without having to figure out where the "if (abort_search) return" could be missing as in some unreproductible situation my program lost on time... Using a flag became a real nightmare, and I still had time losses every now and then, even after messing up the code with this abort_search crap, so I opted for a setjmp()/longjmp(), then I learnt about C++ exceptions and used that instead.
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.

User avatar
lucasart
Posts: 3030
Joined: Mon May 31, 2010 11:29 am
Full name: lucasart
Contact:

Re: Some statistics about promotions and underpromotions.

Post by lucasart » Thu Aug 01, 2013 6:24 am

sje wrote:Even continue is bad.
With the same reasoning, break is also bad. After all continue and break are disguised goto statements, no?

Now just try to code around all your break statements, and see how ugly your code gets...

Nothing in the language is bad in an absolute sense and should be forbidden completely. Some things are rarely useful and often best avoided, but the only thing that is bad is to obide by rigid rules instead of using your own judgment to make a decision.

The people who designed the C language are clearly smarter than any of us here, and if they decided to include goto, setjmp(), longjmp(), continue, break, they had good reasons.

I think you should read the critique of Pascal by Brian Kerninghan. It would really change your mind on rigid coding rules. And you would understand why all these ugly things are sometimes necessary, and that's why languages like Pascal designed by psycho-rigid people eventually fail the reality test:
http://www.cs.virginia.edu/~cs655/readi ... ascal.html
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.

User avatar
michiguel
Posts: 6386
Joined: Thu Mar 09, 2006 7:30 pm
Location: Chicago, Illinois, USA
Contact:

Re: Some statistics about promotions and underpromotions.

Post by michiguel » Thu Aug 01, 2013 6:53 am

[MODERATION]
Branch was split from the "underpromotions" thread. These type of discussions tend to explode and it is not fair to drown the original topic started by Jesus. Better to separate the two topics.

Miguel

User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 6:43 pm

Re: Some statistics about promotions and underpromotions.

Post by sje » Thu Aug 01, 2013 7:19 am

lucasart wrote:
sje wrote:Even continue is bad.
With the same reasoning, break is also bad. After all continue and break are disguised goto statements, no?
Using break in any place else than as the last statement in a case body is ugly.

Similarly, having a return statement any place other than the last statement of a function is bad.

Symbolic's search has no recursion. There is the one routine Node() which has a big switch statement with each case being a different phase. The routine's main loop hits the switch each time through until the current phase is PhaseExit. At the top of the loop is is single check of a volatile boolean which, if triggered, sets the phase to PhaseExit. There is no unwinding as there is nothing to unwind. There is nothing hidden on the stack to deconstruct as there is no recursion. The search can be paused, and it can also be stopped and restarted at any phase at any depth.

A lot of chess programmers still use a recursive search because they've copied it out of a textbook or from someone else's program. If they would take the time to learn about the alternative of no recursion, then they just might a more elegant -- and possibly faster -- program.

I have not used a goto or the like in at least thirty years. There has never been any need.

User avatar
Don
Posts: 5106
Joined: Tue Apr 29, 2008 2:27 pm

Re: Some statistics about promotions and underpromotions.

Post by Don » Thu Aug 01, 2013 10:07 am

sje wrote:
lucasart wrote:
sje wrote:Even continue is bad.
With the same reasoning, break is also bad. After all continue and break are disguised goto statements, no?
Using break in any place else than as the last statement in a case body is ugly.

Similarly, having a return statement any place other than the last statement of a function is bad.
I don't believe in absolutes but it's a very good rule of thumb to avoid multiple returns. One exit point only is almost always a good policy for code readability. Sometimes it will happen that you need to do something just before returning from a function and if you have multiple exit points you must code this everywhere you do a return, a lot of code duplication and that is a generally a sign you are doing something wrong. Having said that I don't strictly adhere to this rule and it sometimes gets me into trouble.

Same principle with control statements but I'm a less strict about that as that never seems to get me into trouble so you will see break and continue statements in my code.

Symbolic's search has no recursion. There is the one routine Node() which has a big switch statement with each case being a different phase. The routine's main loop hits the switch each time through until the current phase is PhaseExit. At the top of the loop is is single check of a volatile boolean which, if triggered, sets the phase to PhaseExit. There is no unwinding as there is nothing to unwind. There is nothing hidden on the stack to deconstruct as there is no recursion. The search can be paused, and it can also be stopped and restarted at any phase at any depth.

A lot of chess programmers still use a recursive search because they've copied it out of a textbook or from someone else's program. If they would take the time to learn about the alternative of no recursion, then they just might a more elegant -- and possibly faster -- program.

I have not used a goto or the like in at least thirty years. There has never been any need.
There is no need for switch statements or while loops either and for that matter most of the language. They say most programmers use only a subset of the C language anyway so you are not alone.

I wrote a checkers program for the palm a while back and avoided recursion because the operating system requires that applications always maintain their running state on the fly and be capable of taking up where they left off. It was simple to do but I see no elegance whatsoever in switch statements. A switch statement is like admitting that you live in the real world and there is no elegant solution to something and you are reduced to a series of linear tests.

In my view switch is really ugly - but the alternative is uglier. How do you see a big switch as more elegant than recursion? I guess beauty is in the eye of the beholder.
Capital punishment would be more effective as a preventive measure if it were administered prior to the crime.

User avatar
lucasart
Posts: 3030
Joined: Mon May 31, 2010 11:29 am
Full name: lucasart
Contact:

Re: Some statistics about promotions and underpromotions.

Post by lucasart » Thu Aug 01, 2013 10:44 am

sje wrote:Symbolic's search has no recursion. There is the one routine Node() which has a big switch statement with each case being a different phase. The routine's main loop hits the switch each time through until the current phase is PhaseExit. At the top of the loop is is single check of a volatile boolean which, if triggered, sets the phase to PhaseExit. There is no unwinding as there is nothing to unwind. There is nothing hidden on the stack to deconstruct as there is no recursion. The search can be paused, and it can also be stopped and restarted at any phase at any depth.

A lot of chess programmers still use a recursive search because they've copied it out of a textbook or from someone else's program. If they would take the time to learn about the alternative of no recursion, then they just might a more elegant -- and possibly faster -- program.
So you use an iterative search, everything is done in one really big function, with a huge switch block. That means you have to handle the stack manually, and create your own stack (for alpha, beta, node_type, pv pointer, ply, etc.). How exactly is that better than a recursive search ?

And writing an iterative search while forcing yourself not to use goto and break or continue, is completely ridiculous. I can only imagine that your Node() function is an enormous pile of knots, with an extremely compolex control flow. For example, when I want to dive into the search (child node) recursively... Oh no wait! Recursion is forbiden, so I set the stack for the next ply manually, but then I cannot use goto, so I need to set a flag to tell all that mess of control structures to branch to the right point and search again the child node. How is that more readable than a neat recursive call ?

IMO an iterative search should use goto. That being said, I do not see the point of using an iterative search. When I think of alpha beta algorithm, I think of it recursively. I do not want to twist my brain into thinking how to "iterativize" something that is naturally recursive. It does not simplify code (quite the opposite) and it does not simplify readability because it makes the control flow much more complex, and forces the reader to think in counterintuitive way about the search.

Again you have decided not to use recursion, not to use goto, setjmp(), longjmp(), break or return in certain places only, etc. But behind these decisions there is only dogma, and no valid technical reason.

As for switch, I do not like the switch statement, and rarely use it. If I know that the compiler will generate a jump table, and the cost of branching is indeed critical to the overall execution time (very rare), then I will use it. Otherwise I often find if's more readable, and when you have long list of cases, you should redesign your code so that the need for switch is not necessary instead IMO (break functions into smaller ones for eg.)
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.

Gerd Isenberg
Posts: 2113
Joined: Wed Mar 08, 2006 7:47 pm
Location: Hattingen, Germany

Re: Some statistics about promotions and underpromotions.

Post by Gerd Isenberg » Thu Aug 01, 2013 11:41 am

sje wrote:A goto is ugly. A setjmp() is uglier. Even continue is bad. There are absolute standards which do not depend on the skill of a coder.
Too dogmatic for my taste - Dijkstra versus Knuth and Torvalds. I find it ugly if you introduce boolean variables only to avoid gotos, breaks or continues.

some links:
http://en.wikipedia.org/wiki/Goto
http://en.wikipedia.org/wiki/Considered_harmful
http://www.codinghorror.com/blog/2007/1 ... l-too.html
http://stevemcconnell.com/ccgoto.htm

Post Reply