digitalmars.D - goto
- Andrei Alexandrescu (19/19) Feb 05 2009 I was coding a simple Euclidean distance function with limit:
- Brad Roberts (19/43) Feb 05 2009 {
- BCS (3/26) Feb 05 2009 I think this is a good reason for more scope(*) versions
- Robert Fraser (5/35) Feb 05 2009 Which looks even worse. IMO, this is the perfect place for goto -- small...
- Brad Roberts (7/11) Feb 05 2009 Oh, I agree. I didn't say that in my response because he specifically
- Andrei Alexandrescu (10/20) Feb 05 2009 Yah, same here. I seem to finally have found one of the elusive cases
- Chris R Miller (2/10) Feb 05 2009 Enlighten those of us unfamiliar with this joke?
- Andrei Alexandrescu (18/30) Feb 05 2009 I found a variant of it on http://www.xs4all.nl/~jcdverha/scijokes/6.htm...
- Bill Baxter (6/18) Feb 05 2009 The math guy should just stop after putting the pot on the table, then
- Walter Bright (19/42) Feb 05 2009 double euclideanDistance(Range)(Range a, Range b, double limit)
- Andrei Alexandrescu (4/22) Feb 05 2009 Gotta give it to The Man!
- Bill Baxter (8/30) Feb 05 2009 Meh. I dislike seeing things like for(; 1; ) or while(true) in a loop
- Chris R Miller (3/32) Feb 06 2009 Wherever did the foreach(auto foo in bar) feature request go? Or did
- Don (3/29) Feb 06 2009 The irony is that's Walter's the biggest goto advocate I know, other
-
Walter Bright
(2/4)
Feb 06 2009
I don't mind being compared to Linus
. - Steven Schveighoffer (4/8) Feb 09 2009 If you like, I can name several not-so-spectacular coders that I know wh...
- Derek Parnell (36/56) Feb 05 2009 I'm not sure about the elegant part but ...
- Lionello Lunesu (5/23) Feb 05 2009 I would refactor the a/b.next and a/b.empty into a new range that does t...
- Daniel Keep (31/54) Feb 05 2009 The goto approach looks a bit messy because it isn't immediately clear
- Lionello Lunesu (1/1) Feb 06 2009 My hero! ;)
- bearophile (30/44) Feb 06 2009 That's closer to the way code is meant to be written :-)
- Nick Sabalausky (25/43) Feb 05 2009 I haven't looked at any of the replies yet, and euclidean distance and
- Christof Schardt (10/10) Feb 05 2009 In the web-source of hius adventure-game
- grauzone (18/18) Feb 05 2009 I'd prefer to have some kind of goto, which enforces structured
I was coding a simple Euclidean distance function with limit: double euclideanDistance(Range)(Range a, Range b, double limit) { limit *= limit; double result = 0; for (; !a.empty; a.next, b.next) { enforce(!b.empty); auto t = a.head - b.head; result += t * t; if (result >= limit) goto thatsit; } enforce(b.empty); thatsit: return sqrt(result); } How would an elegant goto-less approach look like? It should not duplicate code, e.g. the call to sqrt. Andrei
Feb 05 2009
Andrei Alexandrescu wrote:I was coding a simple Euclidean distance function with limit: double euclideanDistance(Range)(Range a, Range b, double limit) { limit *= limit; double result = 0; for (; !a.empty; a.next, b.next) { enforce(!b.empty); auto t = a.head - b.head; result += t * t; if (result >= limit) goto thatsit; } enforce(b.empty); thatsit: return sqrt(result); } How would an elegant goto-less approach look like? It should not duplicate code, e.g. the call to sqrt. AndreiHow about:double euclideanDistance(Range)(Range a, Range b, double limit){ limit *= limit; double result = 0; for (; !a.empty; a.next, b.next) { enforce(!b.empty); auto t = a.head - b.head; result += t * t; if (result >= limit) { b.clear; break; } } enforce(b.empty); return sqrt(result); }
Feb 05 2009
Hello Andrei,I was coding a simple Euclidean distance function with limit: double euclideanDistance(Range)(Range a, Range b, double limit) { limit *= limit; double result = 0; for (; !a.empty; a.next, b.next) { enforce(!b.empty); auto t = a.head - b.head; result += t * t; if (result >= limit) goto thatsit; } enforce(b.empty); thatsit: return sqrt(result); } How would an elegant goto-less approach look like? It should not duplicate code, e.g. the call to sqrt. AndreiI think this is a good reason for more scope(*) versions you could fake it withfor (; !a.empty; a.next || (enforce(b.empty), false), b.next)
Feb 05 2009
BCS wrote:Hello Andrei,Which looks even worse. IMO, this is the perfect place for goto -- small function, used only for an exit condition. There's no "spaghetti code" here at all. I know goto used to be abused back in the day, but it has its place.I was coding a simple Euclidean distance function with limit: double euclideanDistance(Range)(Range a, Range b, double limit) { limit *= limit; double result = 0; for (; !a.empty; a.next, b.next) { enforce(!b.empty); auto t = a.head - b.head; result += t * t; if (result >= limit) goto thatsit; } enforce(b.empty); thatsit: return sqrt(result); } How would an elegant goto-less approach look like? It should not duplicate code, e.g. the call to sqrt. AndreiI think this is a good reason for more scope(*) versions you could fake it withfor (; !a.empty; a.next || (enforce(b.empty), false), b.next)
Feb 05 2009
Robert Fraser wrote:Which looks even worse. IMO, this is the perfect place for goto -- small function, used only for an exit condition. There's no "spaghetti code" here at all. I know goto used to be abused back in the day, but it has its place.Oh, I agree. I didn't say that in my response because he specifically asked for other ways to write it. In this case, I see no reason to change it. That said, it can be nearly as clean without the goto for those that are religious about it. Later, Brad
Feb 05 2009
Brad Roberts wrote:Robert Fraser wrote:Yah, same here. I seem to finally have found one of the elusive cases when goto simplifies things. About Brad's variant - ranges don't define clear, but assigning b = b.init does the trick. (I personally still find the goto version marginally clearer. It's also marginally more efficient because it doesn't do one assignment and one vacuous check. Also the joke with the programmer who throws the water and then applies the known procedure to make coffee comes to mind.) AndreiWhich looks even worse. IMO, this is the perfect place for goto -- small function, used only for an exit condition. There's no "spaghetti code" here at all. I know goto used to be abused back in the day, but it has its place.Oh, I agree. I didn't say that in my response because he specifically asked for other ways to write it. In this case, I see no reason to change it. That said, it can be nearly as clean without the goto for those that are religious about it.
Feb 05 2009
Andrei Alexandrescu wrote:Yah, same here. I seem to finally have found one of the elusive cases when goto simplifies things. About Brad's variant - ranges don't define clear, but assigning b = b.init does the trick. (I personally still find the goto version marginally clearer. It's also marginally more efficient because it doesn't do one assignment and one vacuous check. Also the joke with the programmer who throws the water and then applies the known procedure to make coffee comes to mind.)Enlighten those of us unfamiliar with this joke?
Feb 05 2009
Chris R Miller wrote:Andrei Alexandrescu wrote:I found a variant of it on http://www.xs4all.nl/~jcdverha/scijokes/6.html: There were two men trying to decide what to do for a living. They went to see a counselor, and he decided that they had good problem solving skills. He tried a test to narrow the area of specialty. He put each man in a room with a stove, a table, and a pot of water on the table. He said "Boil the water". Both men moved the pot from the table to the stove and turned on the burner to boil the water. Next, he put them into a room with a stove, a table, and a pot of water on the floor. Again, he said "Boil the water". The first man put the pot on the stove and turned on the burner. The counselor told him to be an Engineer, because he could solve each problem individually. The second man moved the pot from the floor to the table, and then moved the pot from the table to the stove and turned on the burner. The counselor told him to be a mathematician because he reduced the problem to a previously solved problem. AndreiYah, same here. I seem to finally have found one of the elusive cases when goto simplifies things. About Brad's variant - ranges don't define clear, but assigning b = b.init does the trick. (I personally still find the goto version marginally clearer. It's also marginally more efficient because it doesn't do one assignment and one vacuous check. Also the joke with the programmer who throws the water and then applies the known procedure to make coffee comes to mind.)Enlighten those of us unfamiliar with this joke?
Feb 05 2009
On Fri, Feb 6, 2009 at 2:27 PM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:He tried a test to narrow the area of specialty. He put each man in a room with a stove, a table, and a pot of water on the table. He said "Boil the water". Both men moved the pot from the table to the stove and turned on the burner to boil the water. Next, he put them into a room with a stove, a table, and a pot of water on the floor. Again, he said "Boil the water". The first man put the pot on the stove and turned on the burner. The counselor told him to be an Engineer, because he could solve each problem individually. The second man moved the pot from the floor to the table, and then moved the pot from the table to the stove and turned on the burner. The counselor told him to be a mathematician because he reduced the problem to a previously solved problem.The math guy should just stop after putting the pot on the table, then when asked by the counselor why he stopped, then the math guy should refer him to his previous work. --bb
Feb 05 2009
Andrei Alexandrescu wrote:I was coding a simple Euclidean distance function with limit: double euclideanDistance(Range)(Range a, Range b, double limit) { limit *= limit; double result = 0; for (; !a.empty; a.next, b.next) { enforce(!b.empty); auto t = a.head - b.head; result += t * t; if (result >= limit) goto thatsit; } enforce(b.empty); thatsit: return sqrt(result); } How would an elegant goto-less approach look like? It should not duplicate code, e.g. the call to sqrt. Andreidouble euclideanDistance(Range)(Range a, Range b, double limit) { limit *= limit; double result = 0; for (; 1; a.next, b.next) { if (a.empty) { enforce(b.empty); break; } enforce(!b.empty); auto t = a.head - b.head; result += t * t; if (result >= limit) break; } return sqrt(result); }
Feb 05 2009
Walter Bright wrote:double euclideanDistance(Range)(Range a, Range b, double limit) { limit *= limit; double result = 0; for (; 1; a.next, b.next) { if (a.empty) { enforce(b.empty); break; } enforce(!b.empty); auto t = a.head - b.head; result += t * t; if (result >= limit) break; } return sqrt(result); }Gotta give it to The Man! So after all I couldn't find a good use for goto. Andrei
Feb 05 2009
On Fri, Feb 6, 2009 at 2:30 PM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Walter Bright wrote:Meh. I dislike seeing things like for(; 1; ) or while(true) in a loop (unless it's something like a top level message processing loop or such). At least in your goto version I know from a glance at the for() part that at most we're going to iterate till the thing is empty. --bbdouble euclideanDistance(Range)(Range a, Range b, double limit) { limit *= limit; double result = 0; for (; 1; a.next, b.next) { if (a.empty) { enforce(b.empty); break; } enforce(!b.empty); auto t = a.head - b.head; result += t * t; if (result >= limit) break; } return sqrt(result); }Gotta give it to The Man! So after all I couldn't find a good use for goto.
Feb 05 2009
Bill Baxter wrote:On Fri, Feb 6, 2009 at 2:30 PM, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Wherever did the foreach(auto foo in bar) feature request go? Or did that conflict with existing syntax?Walter Bright wrote:Meh. I dislike seeing things like for(; 1; ) or while(true) in a loop (unless it's something like a top level message processing loop or such). At least in your goto version I know from a glance at the for() part that at most we're going to iterate till the thing is empty.double euclideanDistance(Range)(Range a, Range b, double limit) { limit *= limit; double result = 0; for (; 1; a.next, b.next) { if (a.empty) { enforce(b.empty); break; } enforce(!b.empty); auto t = a.head - b.head; result += t * t; if (result>= limit) break; } return sqrt(result); }Gotta give it to The Man! So after all I couldn't find a good use for goto.
Feb 06 2009
Andrei Alexandrescu wrote:Walter Bright wrote:The irony is that's Walter's the biggest goto advocate I know, other than Linus Torvalds.double euclideanDistance(Range)(Range a, Range b, double limit) { limit *= limit; double result = 0; for (; 1; a.next, b.next) { if (a.empty) { enforce(b.empty); break; } enforce(!b.empty); auto t = a.head - b.head; result += t * t; if (result >= limit) break; } return sqrt(result); }Gotta give it to The Man! So after all I couldn't find a good use for goto. Andrei
Feb 06 2009
Don wrote:The irony is that's Walter's the biggest goto advocate I know, other than Linus Torvalds.I don't mind being compared to Linus <g>.
Feb 06 2009
"Walter Bright" wroteDon wrote:If you like, I can name several not-so-spectacular coders that I know who like to use goto ;) -SteveThe irony is that's Walter's the biggest goto advocate I know, other than Linus Torvalds.I don't mind being compared to Linus <g>.
Feb 09 2009
On Thu, 05 Feb 2009 19:37:35 -0800, Andrei Alexandrescu wrote:I was coding a simple Euclidean distance function with limit: double euclideanDistance(Range)(Range a, Range b, double limit) { limit *= limit; double result = 0; for (; !a.empty; a.next, b.next) { enforce(!b.empty); auto t = a.head - b.head; result += t * t; if (result >= limit) goto thatsit; } enforce(b.empty); thatsit: return sqrt(result); } How would an elegant goto-less approach look like? It should not duplicate code, e.g. the call to sqrt.I'm not sure about the elegant part but ... double euclideanDistance(Range)(Range a, Range b, double limit) { limit *= limit; double result = 0; do { -- Precondition for next iteration; 'a' ought not be empty. if (a.empty) { -- If it is empty then 'b' must also be empty. enforce(b.empty); -- No more work needs be done. break; } -- If 'a' isn't empty then 'b' must not be empty. enforce(!b.empty); -- Perform this iteration's work. auto t = a.head - b.head; result += t * t; -- If the limit has been reached then stop working. if (result >= limit) break; -- Move along to the next element pair. a.next; b.next; -- And repeat. } while (true); return sqrt(result); } -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
Feb 05 2009
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message news:gmgb9u$qkg$1 digitalmars.com...I was coding a simple Euclidean distance function with limit: double euclideanDistance(Range)(Range a, Range b, double limit) { limit *= limit; double result = 0; for (; !a.empty; a.next, b.next) { enforce(!b.empty); auto t = a.head - b.head; result += t * t; if (result >= limit) goto thatsit; } enforce(b.empty); thatsit: return sqrt(result); } How would an elegant goto-less approach look like? It should not duplicate code, e.g. the call to sqrt.I would refactor the a/b.next and a/b.empty into a new range that does the enforcing and then you can use break. L.
Feb 05 2009
Andrei Alexandrescu wrote:I was coding a simple Euclidean distance function with limit: double euclideanDistance(Range)(Range a, Range b, double limit) { limit *= limit; double result = 0; for (; !a.empty; a.next, b.next) { enforce(!b.empty); auto t = a.head - b.head; result += t * t; if (result >= limit) goto thatsit; } enforce(b.empty); thatsit: return sqrt(result); } How would an elegant goto-less approach look like? It should not duplicate code, e.g. the call to sqrt. AndreiThe goto approach looks a bit messy because it isn't immediately clear what the relationship between a and b's lengths are. Personally, I'd do it like this: double euclideanDistance(Range)(Range as, Range bs, double limit) { limit *= limit; double result = 0; foreach( ab ; zip(as, bs, ZipStyle.EnforceLength) ) { auto t = ab._0.head - ab._1.head; result += t * t; if (result >= limit) break; } return sqrt(result); } Of course, if we had foreach support for tuple unpacking... double euclideanDistance(Range)(Range as, Range bs, double limit) { limit *= limit; double result = 0; foreach( a, b ; zip(as, bs, ZipStyle.EnforceLength) ) { auto t = a.head - b.head; result += t * t; if (result >= limit) break; } return sqrt(result); } :D -- Daniel
Feb 05 2009
Daniel Keep:Of course, if we had foreach support for tuple unpacking... double euclideanDistance(Range)(Range as, Range bs, double limit) { limit *= limit; double result = 0; foreach( a, b ; zip(as, bs, ZipStyle.EnforceLength) ) { auto t = a.head - b.head; result += t * t; if (result >= limit) break; } return sqrt(result); }That's closer to the way code is meant to be written :-) Few other details: auto t = a.head - b.head; result += t * t; May become: result += (a.head - b.head) ** 2; This isn's nice looking (you also may want to zip many iterables): zip(as, bs, ZipStyle.EnforceLength) How many zip behaviours are useful? Among the possible ones there are: 1) stop as soon as the shorter iterable ends; 2) stop when the longest iterable ends, yielding item.init items to fill blanks. 3) assert that they are all of the same length, as you ask for. A simpler solution is to make zip support only (1), avoid ugly constants. To support (2) you it can be invented an iterable wrapper that yields the constant you want when the given iterable ends, for example: xzip(iter1, xextend(iter2, 0.0)) And regarding (3) I don't have many ideas. But why the original code by Alex has those enforce() to be sure the iterables have the same length? Maybe the best thing is just to not enforce that. So this may be a readable version (no .heads): double limitedEuclideanDistance(Range)(Range iter2, Range iter2, double limit) { limit = limit ** 2; double sqr_dist = 0.0; foreach (x1, x2 in xzip(iter1, iter2)) { sqr_dist += (x1 - x2) ** 2; if (sqr_dist >= limit) break; } return sqrt(sqr_dist); } Bye, bearophile
Feb 06 2009
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message news:gmgb9u$qkg$1 digitalmars.com...I was coding a simple Euclidean distance function with limit: double euclideanDistance(Range)(Range a, Range b, double limit) { limit *= limit; double result = 0; for (; !a.empty; a.next, b.next) { enforce(!b.empty); auto t = a.head - b.head; result += t * t; if (result >= limit) goto thatsit; } enforce(b.empty); thatsit: return sqrt(result); } How would an elegant goto-less approach look like? It should not duplicate code, e.g. the call to sqrt.I haven't looked at any of the replies yet, and euclidean distance and Ranges are things I'd have to look up (I haven't actually had a chance to look at the Range docs), but I would do something like this: double euclideanDistance(Range)(Range a, Range b, double limit) { limit *= limit; double result = 0; bool foundIt=false; for (; !a.empty && !foundIt; a.next, b.next) { enforce(!b.empty); auto t = a.head - b.head; result += t * t; if (result >= limit) { foundIt = true; break; // This line needed? } } if(!foundIt) // This line needed? enforce(b.empty); return sqrt(result); }
Feb 05 2009
In the web-source of hius adventure-game http://www-cs-staff.stanford.edu/~uno/programs/advent.w.gz Knuth comments (resp. warns the reader): "By the way, if you don't like |goto| statements, don't read this. (And don't read any other programs that simulate multistate systems.)" Don Knuth, September 1998 This may be dated. But while I cannot judge the reasoning, I did not want to miss to post it here. At least for its subtle humor. Christof
Feb 05 2009
I'd prefer to have some kind of goto, which enforces structured programming. Something like: double euclideanDistance(Range)(Range a, Range b, double limit) { limit *= limit; double result = 0; foo: { for (; !a.empty; a.next, b.next) { enforce(!b.empty); auto t = a.head - b.head; result += t * t; if (result >= limit) break foo; } enforce(b.empty); } return sqrt(result); }
Feb 05 2009