From: Richard Heathfield on 10 May 2010 14:05 James Dow Allen wrote: <snip> > Well at least Heathfield and Seebs agree on *something*: > We seek human cognitive advantage. Actually, I think Seebs and I agree on a great deal. This happens to be something about which we mostly disagree, but even then we can find small but significant areas of agreement, if we look hard enough. <snip> > Mr. Heathfield, IIRC, hasn't actually deigned to post an alternative. I'm reasonably sure I did deign to post an alternative. But I may not have done. I may merely have posted an alternative. To save me finding it, however, I'll very quickly and no doubt erroneously reconstruct it: found = 0; for(x = 0; !found && x < xlim; x++) { for(y = 0; !found && y < ylim; y++) { for(z = 0; !found && z < zlim; z++) { if(haystack[x][y][z] == needle) { point_assign(p, x, y, z); found = 1; } } } } return found; Laugh away, sirrah! :-) <snip> > Hope this helps, Yup. Style arguments are always fun. -- Richard Heathfield <http://www.cpax.org.uk> Email: -http://www. +rjh@ "Usenet is a strange place" - dmr 29 July 1999 Sig line vacant - apply within
From: Willem on 10 May 2010 15:58 Let's take your example to make my point: Richard Heathfield wrote: ) found = 0; ) for(x = 0; !found && x < xlim; x++) ) { ) for(y = 0; !found && y < ylim; y++) ) { ) for(z = 0; !found && z < zlim; z++) ) { ) if(haystack[x][y][z] == needle) ) { ) point_assign(p, x, y, z); ) found = 1; ) } ) } ) } ) } ) return found; The benefit of your code, you say, is that you only need to look at the conditional in the for statement, to see when the loop will end, right ? If a return in the middle of the loops were used, then you not only have to look at the loop conditional, but also inside the body of the loop, correct ? Now, in your code, it ends when you reach the limit of the range, or when this 'found' variable becomes true. But, and here's the point, to find out what happens to this 'found' variable, you have to look *at the body of the code*. Exactly the same thing you have to do when you don't follow SESE. So, in fact, in *both* versions, you have to look in the body. So that would make them roughly equivalent. But, in the SESE version, you *first* have to look at the loop conditional *first*, and then in addition to that, you have to look at the loop body, and furthermore, you have to search for some arbitrary variable, instead of one of a few well-defined words (return, break, goto, longjmp). And, to top it off, any maintenance programmer worth his salt has seen loops of the form 'for (i = 0; i < N; i++) {...}', and can tell almost instantly that it's running i over the range [0..N), (just like the BASIC version FOR i = 0 TO N, as a matter of fact). Now, in SESE code, there are a lot of different ways to make it happen. One way is to use a boolean flag. Another is to manipulate the loop counters. Another is to use a temporary to hold the result and check for that, and I'm sure that plenty more versions exist. So that, in total, are _three_ reasons why the SESE version is more difficult to understand. PS: I saw that you acknowledged not having refuted any arguments, so feel free to ignore this as well. PPS: Yes, that 'PS' is baiting you. I very much dislike it when people stop arguing their side with a notion of "we're not going to agree", while there are sound, factual arguments on the table. SaSW, Willem -- Disclaimer: I am in no way responsible for any of the statements made in the above text. For all I know I might be drugged or something.. No I'm not paranoid. You all think I'm paranoid, don't you ! #EOT
From: Seebs on 10 May 2010 16:14 On 2010-05-10, Richard Heathfield <rjh(a)see.sig.invalid> wrote: > Actually, I think Seebs and I agree on a great deal. This happens to be > something about which we mostly disagree, but even then we can find > small but significant areas of agreement, if we look hard enough. Yes. > erroneously reconstruct it: > > found = 0; > for(x = 0; !found && x < xlim; x++) > { > for(y = 0; !found && y < ylim; y++) > { > for(z = 0; !found && z < zlim; z++) > { > if(haystack[x][y][z] == needle) > { > point_assign(p, x, y, z); > found = 1; > } > } > } > } > return found; > Laugh away, sirrah! :-) Okay, let's compare this with: for (x = 0; x < xlim; ++x) { for (y = 0; y < ylim; ++y) { for (z = 0; z < zlim; ++z) { if (haystack[x][y][z] == needle) { point_assign(p, x, y, z); return 1; } } } } return 0; I consider this much, much, easier to read. It gains even more if we use the original's "return &haystack[x][y][z]". In this case, I think yours is pretty close, because "!found && " is itself a bit of an idiom. However, I find the latter easier to understand because it's unambigously "loop over the entire array, doing { if you found a match, set something and return 1 }", while for yours, I have to model it cognitively as "loop until either something happens or we have covered this whole range, doing { loop either until something happens or we have covered this whole range, doing { loop either until something happens or we have covered this whole range, doing { if you found a match, set something, and set something else } } }". Because the test conditions aren't part of the standard "loop over array" idiom, I have to track both parts of the test condition separately, and doing that for three layers of looping chews up six short-term memory slots, and the index variables use up three more, leaving me solidly past my short-term memory budget without even looking at the inner loop. For the form using the pure idiom, I'm only using three slots -- I have x, y, and z as "the current indexes in the loop". -s -- Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam(a)seebs.net http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
From: Leigh Johnston on 10 May 2010 16:23 "Richard Heathfield" <rjh(a)see.sig.invalid> wrote in message news:qpSdnTKKs5xY13XWnZ2dnUVZ8uudnZ2d(a)bt.com... > To save me finding it, however, I'll very quickly and no doubt erroneously > reconstruct it: > > found = 0; > for(x = 0; !found && x < xlim; x++) > { > for(y = 0; !found && y < ylim; y++) > { > for(z = 0; !found && z < zlim; z++) > { > if(haystack[x][y][z] == needle) > { > point_assign(p, x, y, z); > found = 1; > } > } > } > } > return found; > > Laugh away, sirrah! :-) > > <snip> > >> Hope this helps, > > Yup. Style arguments are always fun. > It is not a matter of style, SESE is an anachronism, a relic of old programming languages. Your SESE compliant version is more complex (extra conditional variables and extra conditionals checking those extra conditional variables and extra CPU instructions to implement those extra conditionals) than using an early return with a SEME version. As Willem mentions elsewhere you do not gain anything from your SESE version as you have to read *both* the loop conditionals (all three of them) in addition to the code which changes the extra conditional variable making your SESE version harder to understand than an equivalent SEME version. It is time to stop using old fashioned programming languages with their baggage of old fashioned "idioms". /Leigh
From: Dave Harris on 10 May 2010 17:44
nathancbaker(a)gmail.com (Nathan) wrote (abridged): > > Specifically, you need to be aware that > > data[0][0].size() may be different to data[1][0].size() or > > data[0][1].size(), and that any of them may be zero meaning > > that (eg) data[0][0][0] does not exist and must not be accessed. > > [...] > Value_t* MyClass::findValue(const Value_t& value) > { > size_t xyzMax = data.size() + data[xInd].size() + data[xInd] > [yInd].size(); > for(size_t xInd = 0; xInd < xyzMax; ++xInd) > { > if(data[xInd] == value) > return &data[xInd]; > } > > return 0; > } But this does not do the same thing at all. You have done what I warned you against, which is suppose that data[0][0].size() is the same as data[0][1].size(). You also assume the values are contiguous in memory, which won't be true if the data[0] is a std::vector (and it is almost certainly some kind of data structure; given that it defines the size() method it won't be a plain array). And you've introduced additional bugs, for example adding the sizes when you need to multiply them. Your later code misses out some braces so that the loop always terminates after one iteration. You don't declare or initialise all your variables. Frankly, you are not gaining any credibility here. > [...] > So, > > 3 loop constructs are reduced to 1 > 4 conditionals are reduced to 2 > 2 exit points are reduced to 1 > > Simple, isn't it? When you can solve the original problem correctly, we can talk about whether your solution is simpler. -- Dave Harris, Nottingham, UK. |