|
|
on goto
[Xpost to: alt.comp.programming, alt.lang.asm,
comp.lang.c, comp.lang.c++, comp.programming]
the people that speak not good about "goto"
are uttled wrong; their code bug full etc
more distant is your code from goto
more your code is bug full and incompresible
the "goto" is the key word for programming;
all the remain, other than goto or jmp or jc or jz,
and the easy cpu layout
is the wrong way for programming
i advise all you
Good Morning
|
|
0
|
|
|
|
Reply
|
io_x
|
4/24/2010 10:05:17 AM |
|
I use goto to break nested for loops and I can't see a
reason to ban goto.
Ali
On 24 Nisan, 13:13, "io_x" <a...@b.c.invalid> wrote:
> [Xpost to: alt.comp.programming, alt.lang.asm,
> comp.lang.c, comp.lang.c++, comp.programming]
>
> the people that speak not good about "goto"
> are uttled wrong; their code bug full etc
>
> more distant is your code from goto
> more your code is bug full and incompresible
>
> the "goto" is the key word for programming;
> all the remain, other than goto or jmp or jc or jz,
> and the easy cpu layout
> is the wrong way for programming
>
> i advise all you
> Good Morning
|
|
0
|
|
|
|
Reply
|
Ali
|
4/24/2010 10:06:33 AM
|
|
On Apr 24, 3:13=A0am, "io_x" <a...@b.c.invalid> wrote:
> [Xpost to: alt.comp.programming, alt.lang.asm,
> comp.lang.c, comp.lang.c++, comp.programming]
>
> the people that speak not good about "goto"
> are uttled wrong; their code bug full etc
>
> more distant is your code from goto
> more your code is bug full and incompresible
>
> the "goto" is the key word for programming;
> all the remain, other than goto or jmp or jc or jz,
> and the easy cpu layout
> is the wrong way for programming
>
> i advise all you
> Good Morning
Everything may be used, misused and abused, goto included. There are
good and bad usage patterns and goto is not an exception here. I can
list a number of other things that may be just as bad as a poorly used
goto (or as good as a good goto). See?
Alex
|
|
0
|
|
|
|
Reply
|
Alexei
|
4/24/2010 10:35:09 AM
|
|
In article
<dda9d933-e9c1-418f-b62a-bc30bd1dd16c@r27g2000yqn.googlegroups.com>,
Ali Karaali <alicpp@gmail.com> wrote:
> I use goto to break nested for loops and I can't see a
> reason to ban goto.
>
> Ali
>
> On 24 Nisan, 13:13, "io_x" <a...@b.c.invalid> wrote:
> > [Xpost to: alt.comp.programming, alt.lang.asm,
> > comp.lang.c, comp.lang.c++, comp.programming]
> >
> > the people that speak not good about "goto"
> > are uttled wrong; their code bug full etc
> >
> > more distant is your code from goto
> > more your code is bug full and incompresible
> >
> > the "goto" is the key word for programming;
> > all the remain, other than goto or jmp or jc or jz,
> > and the easy cpu layout
> > is the wrong way for programming
> >
> > i advise all you
> > Good Morning
I haven't used a goto since 1978 (when I stopped writing FORTRAN).
--
Tim
"That excessive bail ought not to be required, nor excessive fines imposed,
nor cruel and unusual punishments inflicted" -- Bill of Rights 1689
|
|
0
|
|
|
|
Reply
|
Tim
|
4/24/2010 11:07:16 AM
|
|
On Apr 24, 5:13=A0am, "io_x" <a...@b.c.invalid> wrote:
> [Xpost to: alt.comp.programming, alt.lang.asm,
> comp.lang.c, comp.lang.c++, comp.programming]
>
> the people that speak not good about "goto"
> are uttled wrong; their code bug full etc
>
> more distant is your code from goto
> more your code is bug full and incompresible
>
> the "goto" is the key word for programming;
> all the remain, other than goto or jmp or jc or jz,
> and the easy cpu layout
> is the wrong way for programming
>
> i advise all you
> Good Morning
Yeah, there's nothing more fun than converting BASIC to Pascal.
Only to discover that goto was used to return from a sub-routine
without clearing the stack.
|
|
0
|
|
|
|
Reply
|
Mensanator
|
4/24/2010 12:06:40 PM
|
|
On Apr 24, 6:06=A0pm, Ali Karaali <ali...@gmail.com> wrote:
> I use goto to break nested for loops and I can't see a
> reason to ban goto.
Why not use break instead? Does the same thing, spares you from having
to define a label.
There are two senses in which a program can be structured.
The first is syntactical, and to be syntactically structured, the
source code of the program must be restricted to structured syntax, of
which neither goto nor break is a strict example. You'd have to
simulate the break logic:
broken =3D false;
for(!broken && condition)
{
.
.
.
if (exceptional condition) broken =3D true;
else
{
.
.
.
}
}
The second is semantic. To be structured in this way, the program must
be decomposable without change into blocks, each at most one entry and
at most one exit, and each of which is one of the Bohm-Jacopini
constructs process, if..then..else, or do while.
If the program is syntactically structured, it must be semantically
structured. But the reverse is not true; an assembler program using go
to can be semantically structured but it is not syntactically
structured, like this inefficient and contrived example
LOAD 0
STOR i
LBL1:
LOAD i
COMP limit
IFGE LBL19
..
..
..
IFEQ LBL12
LOAD j
STOR v
GOTO LBL129
LBL12:
LOAD k
STOR v2
LBL129:
..
..
..
LOAD i
ADD 1
STOR i
GOTO LBL1
LBL19:
Then, certain extensions are permitted including most famously case
without fallthrough, one trip do "until", and break, implemented
semantically with a go to to a label one past the end of the loop or
syntactically with break.
A breaking loop is a new structure relative to the three Bohm-Jacopini
structures, switch case and one trip do. And it "weakens" the
postconditions that must obtain on exit. Most famously, the index of a
breaking loop may not be one past the end of what was being processed.
>
> Ali
>
> On 24 Nisan, 13:13, "io_x" <a...@b.c.invalid> wrote:
>
>
>
> > [Xpost to: alt.comp.programming, alt.lang.asm,
> > comp.lang.c, comp.lang.c++, comp.programming]
>
> > the people that speak not good about "goto"
> > are uttled wrong; their code bug full etc
>
> > more distant is your code from goto
> > more your code is bug full and incompresible
>
> > the "goto" is the key word for programming;
> > all the remain, other than goto or jmp or jc or jz,
> > and the easy cpu layout
> > is the wrong way for programming
>
> > i advise all you
> > Good Morning
|
|
0
|
|
|
|
Reply
|
spinoza1111
|
4/24/2010 12:11:05 PM
|
|
"Alexei A. Frounze" <alexfrunews@gmail.com> writes:
> On Apr 24, 3:13�am, "io_x" <a...@b.c.invalid> wrote:
>> [Xpost to: alt.comp.programming, alt.lang.asm,
>> comp.lang.c, comp.lang.c++, comp.programming]
>>
>> the people that speak not good about "goto"
>> are uttled wrong; their code bug full etc
>>
>> more distant is your code from goto
>> more your code is bug full and incompresible
>>
>> the "goto" is the key word for programming;
>> all the remain, other than goto or jmp or jc or jz,
>> and the easy cpu layout
>> is the wrong way for programming
>>
>> i advise all you
>> Good Morning
>
> Everything may be used, misused and abused, goto included. There are
> good and bad usage patterns and goto is not an exception here. I can
> list a number of other things that may be just as bad as a poorly used
> goto (or as good as a good goto). See?
Indeed. For example, the Duff device is worse than most gotos I've
ever seen.
--
__Pascal Bourguignon__
|
|
0
|
|
|
|
Reply
|
pjb
|
4/24/2010 12:16:22 PM
|
|
"spinoza1111" <spinoza1111@yahoo.com> wrote in message
news:051fa27d-5cf8-4f7e-94c8-e9e5b26566b7@g34g2000pro.googlegroups.com...
> On Apr 24, 6:06 pm, Ali Karaali <ali...@gmail.com> wrote:
>> I use goto to break nested for loops and I can't see a
>> reason to ban goto.
>
> Why not use break instead? Does the same thing, spares you from having
> to define a label.
>
Because break only breaks out of the innermost loop, using goto to break out
of nested loops is one of the few sensible uses of goto.
/Leigh
|
|
0
|
|
|
|
Reply
|
Leigh
|
4/24/2010 12:20:10 PM
|
|
io_x wrote:
> [Xpost to: alt.comp.programming, alt.lang.asm,
> comp.lang.c, comp.lang.c++, comp.programming]
>
> the people that speak not good about "goto"
> are uttled wrong; their code bug full etc
>
> more distant is your code from goto
> more your code is bug full and incompresible
>
> the "goto" is the key word for programming;
> all the remain, other than goto or jmp or jc or jz,
> and the easy cpu layout
> is the wrong way for programming
>
> i advise all you
> Good Morning
I see there is a small misconception in this issue. The only nasty thing that is usually
said about goto is that it's use may end up generating code which isn't easy to read, to
interpret and to follow.
Adding to that, high level languages implement multiple flavors of conditionals and loops,
which end up performing the exact same tasks goto is used for but in a way which is
"cleaner", easier to read, to interpret and to follow.
Yet, loop/conditionals aren't and be all, end all solution. Some tasks, such as state
machines, can still be better implemented with the plain old goto, sometimes in a "cleaner"
way than with any mix of loop/conditionals which are available in any high level language.
So, in essence, goto isn't the problem nor is it a problem. It's just a way of performing
certain tasks. Sometimes it isn't the best tool and sometimes it isn't the worst tool.
Nonetheless, that doesn't make it bad.
On the other hand, popular misconceptions which are often cited but aren't based on any
objective reasoning can constitute a problem, and this appears to be one of those cases.
Rui Maciel
|
|
0
|
|
|
|
Reply
|
Rui
|
4/24/2010 12:20:28 PM
|
|
"io_x" <a@b.c.invalid> wrote:
> [Xpost to: alt.comp.programming, alt.lang.asm,
> comp.lang.c, comp.lang.c++, comp.programming]
>
> the people that speak not good about "goto" are uttled wrong; their
> code bug full etc
>
> more distant is your code from goto more your code is bug full and
> incompresible
>
> the "goto" is the key word for programming; all the remain, other than
> goto or jmp or jc or jz, and the easy cpu layout is the wrong way for
> programming
>
> i advise all you
> Good Morning
This is probably a troll, but it is a good opportunity to suggest to
everyone who is tempted to argue about this issue to start from
Dijkstra's paper rather than simply asserting that "goto is good"
without understanding the issues involved.
http://www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_
Harmful.html
|
|
0
|
|
|
|
Reply
|
Daniel
|
4/24/2010 2:10:34 PM
|
|
"Daniel T." <daniel_t@earthlink.net> wrote in message
news:daniel_t-623394.10103424042010@70-3-168-216.pools.spcsdns.net...
> "io_x" <a@b.c.invalid> wrote:
>> the "goto" is the key word for programming; all the remain, other than
>> goto or jmp or jc or jz, and the easy cpu layout is the wrong way for
>> programming
>>
>> i advise all you
>> Good Morning
>
> This is probably a troll,
If this actually is io_x, then he really believes this stuff.
> but it is a good opportunity to suggest to
> everyone who is tempted to argue about this issue to start from
> Dijkstra's paper rather than simply asserting that "goto is good"
> without understanding the issues involved.
>
> http://www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_
> Harmful.html
And then read Knuth's "Structured Programming with go to Statements" (a bad
scan is here:
http://pplab.snu.ac.kr/courses/adv_pl05/papers/p261-knuth.pdf)
"... programmers and language designers still feel the need for some
euphemism that 'goes to' without saying 'go to' ..."
--
Bartc
|
|
0
|
|
|
|
Reply
|
bartc
|
4/24/2010 2:38:36 PM
|
|
Ali Karaali <alicpp@gmail.com> wrote:
> I use goto to break nested for loops and I can't see a
> reason to ban goto.
I'll give you a reason to ban goto. This is a line of BASIC code:
90 x = 5
Now, I ask you, where is the line that was previously executed? Is it
directly above line 90, is it directly below it, or could it be anywhere
in the program? Because of the goto statement, simply because an
unstructured "goto" is possible in the language, you have to analyze the
entire program to know the answer. If we ban the use of "goto", we can
confidently know exactly what line of code comes before line 90.
|
|
0
|
|
|
|
Reply
|
Daniel
|
4/24/2010 3:14:10 PM
|
|
"bartc" <bartc@freeuk.com> writes:
> "Daniel T." <daniel_t@earthlink.net> wrote in message
> news:daniel_t-623394.10103424042010@70-3-168-216.pools.spcsdns.net...
>> "io_x" <a@b.c.invalid> wrote:
>
>>> the "goto" is the key word for programming; all the remain, other than
>>> goto or jmp or jc or jz, and the easy cpu layout is the wrong way for
>>> programming
>>>
>>> i advise all you
>>> Good Morning
>>
>> This is probably a troll,
>
> If this actually is io_x, then he really believes this stuff.
>
>> but it is a good opportunity to suggest to
>> everyone who is tempted to argue about this issue to start from
>> Dijkstra's paper rather than simply asserting that "goto is good"
>> without understanding the issues involved.
>>
>> http://www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_
>> Harmful.html
>
> And then read Knuth's "Structured Programming with go to Statements" (a bad
> scan is here:
> http://pplab.snu.ac.kr/courses/adv_pl05/papers/p261-knuth.pdf)
>
> "... programmers and language designers still feel the need for some
> euphemism that 'goes to' without saying 'go to' ..."
Recommending Knuth is like telling someone they need to qualify as a
NASA rocket scientist in order to fly a kite.
--
"Avoid hyperbole at all costs, its the most destructive argument on
the planet" - Mark McIntyre in comp.lang.c
|
|
0
|
|
|
|
Reply
|
Richard
|
4/24/2010 3:18:00 PM
|
|
"Daniel T." <daniel_t@earthlink.net> wrote in message
news:daniel_t-DBCC13.11141024042010@70-3-168-216.pools.spcsdns.net...
> Ali Karaali <alicpp@gmail.com> wrote:
>
>> I use goto to break nested for loops and I can't see a
>> reason to ban goto.
>
> I'll give you a reason to ban goto. This is a line of BASIC code:
>
> 90 x = 5
>
> Now, I ask you, where is the line that was previously executed? Is it
> directly above line 90, is it directly below it, or could it be anywhere
> in the program? Because of the goto statement, simply because an
> unstructured "goto" is possible in the language, you have to analyze the
> entire program to know the answer. If we ban the use of "goto", we can
> confidently know exactly what line of code comes before line 90.
Goto's at least are usually confined to the same function; if the function
is smallish, you don't have to look far to match a goto with a label.
Most languages will allow "x=5" inside a function; where is that function
called from? It could be from anywhere in hundreds of modules.
--
Bartc
|
|
0
|
|
|
|
Reply
|
bartc
|
4/24/2010 3:46:29 PM
|
|
"Daniel T." <daniel_t@earthlink.net> wrote in message
news:daniel_t-DBCC13.11141024042010@70-3-168-216.pools.spcsdns.net...
> Ali Karaali <alicpp@gmail.com> wrote:
>
>> I use goto to break nested for loops and I can't see a
>> reason to ban goto.
>
> I'll give you a reason to ban goto. This is a line of BASIC code:
>
> 90 x = 5
>
> Now, I ask you, where is the line that was previously executed? Is it
> directly above line 90, is it directly below it, or could it be anywhere
> in the program? Because of the goto statement, simply because an
> unstructured "goto" is possible in the language, you have to analyze the
> entire program to know the answer. If we ban the use of "goto", we can
> confidently know exactly what line of code comes before line 90.
This channel is about C++ not BASIC, you do not have to analyze the entire
program in C++ as goto can only jump within the same function so comparisons
with BASIC is silly.
/Leigh
|
|
0
|
|
|
|
Reply
|
Leigh
|
4/24/2010 3:48:30 PM
|
|
In article <EIOdnQHlmcFTj07WnZ2dnUVZ8h-dnZ2d@giganews.com>,
Leigh Johnston <leigh@i42.co.uk> wrote:
....
>This channel is about C++ not BASIC, you do not have to analyze the entire
>program in C++ as goto can only jump within the same function so comparisons
>with BASIC is silly.
(Channelling Kiki)
>This channel
channel???
>is about C++ not BASIC, you do not have to analyze the entire
C++ is not C (so says Kiki every chance he gets)
--
> No, I haven't, that's why I'm asking questions. If you won't help me,
> why don't you just go find your lost manhood elsewhere.
CLC in a nutshell.
|
|
0
|
|
|
|
Reply
|
gazelle
|
4/24/2010 3:50:45 PM
|
|
"Kenny McCormack" <gazelle@shell.xmission.com> wrote in message
news:hqv40l$oh$3@news.xmission.com...
> In article <EIOdnQHlmcFTj07WnZ2dnUVZ8h-dnZ2d@giganews.com>,
> Leigh Johnston <leigh@i42.co.uk> wrote:
> ...
>>This channel is about C++ not BASIC, you do not have to analyze the entire
>>program in C++ as goto can only jump within the same function so
>>comparisons
>>with BASIC is silly.
>
> (Channelling Kiki)
>
>>This channel
>
> channel???
>
>>is about C++ not BASIC, you do not have to analyze the entire
>
> C++ is not C (so says Kiki every chance he gets)
>
> --
>> No, I haven't, that's why I'm asking questions. If you won't help me,
>> why don't you just go find your lost manhood elsewhere.
>
> CLC in a nutshell.
>
Sorry non-C++ folks I didn't spot the cross-post, I hate it when people do
that. At least what I said also applies to C.
/Leigh
|
|
0
|
|
|
|
Reply
|
Leigh
|
4/24/2010 3:54:32 PM
|
|
"Leigh Johnston" <leigh@i42.co.uk> wrote:
> "Daniel T." <daniel_t@earthlink.net> wrote:
> > Ali Karaali <alicpp@gmail.com> wrote:
> >
> > > I use goto to break nested for loops and I can't see a
> > > reason to ban goto.
> >
> > I'll give you a reason to ban goto. This is a line of BASIC code:
> >
> > 90 x = 5
> >
> > Now, I ask you, where is the line that was previously executed? Is it
> > directly above line 90, is it directly below it, or could it be anywhere
> > in the program? Because of the goto statement, simply because an
> > unstructured "goto" is possible in the language, you have to analyze the
> > entire program to know the answer. If we ban the use of "goto", we can
> > confidently know exactly what line of code comes before line 90.
>
> This channel is about C++ not BASIC, you do not have to analyze the entire
> program in C++ as goto can only jump within the same function so comparisons
> with BASIC is silly.
I posted the message to the comp.programming and forgot to restrict the
groups.
In C and C++, goto is sufficiently restricted that as long as your
functions are small, it is largely harmless. In other words:
label:
x = 5
Where was the line previously executed? In C++ (and C) you don't need to
analyze the whole program to find the answer, you need only analyze the
function. As long as you keep functions small, the issue is minimized.
|
|
0
|
|
|
|
Reply
|
Daniel
|
4/24/2010 4:12:51 PM
|
|
"bartc" <bartc@freeuk.com> wrote:
> "Daniel T." <daniel_t@earthlink.net> wrote:
> > Ali Karaali <alicpp@gmail.com> wrote:
> >
> > > I use goto to break nested for loops and I can't see a reason to
> > > ban goto.
> >
> > I'll give you a reason to ban goto. This is a line of BASIC code:
> >
> > 90 x = 5
> >
> > Now, I ask you, where is the line that was previously executed? Is
> > it directly above line 90, is it directly below it, or could it be
> > anywhere in the program? Because of the goto statement, simply
> > because an unstructured "goto" is possible in the language, you have
> > to analyze the entire program to know the answer. If we ban the use
> > of "goto", we can confidently know exactly what line of code comes
> > before line 90.
>
> Goto's at least are usually confined to the same function; if the
> function is smallish, you don't have to look far to match a goto with
> a label.
>
> Most languages will allow "x=5" inside a function; where is that
> function called from? It could be from anywhere in hundreds of modules.
As Dijkstra pointed out in "Go To Statement Considered Harmful"
As soon as we include in our language procedures we must admit that
a single textual index is no longer sufficient. In the case that a
textual index points to the interior of a procedure body the dynamic
progress is only characterized when we also give to which call of
the procedure we refer. With the inclusion of procedures we can
characterize the progress of the process via a sequence of textual
indices, the length of this sequence being equal to the dynamic
depth of procedure calling.
...
The main point is that the values of these indices are outside
programmer's control; they are generated (either by the write-up of
his program or by the dynamic evolution of the process) whether he
wishes or not. They provide independent coordinates in which to
describe the progress of the process.
Why do we need such independent coordinates? The reason is - and
this seems to be inherent to sequential processes - that we can
interpret the value of a variable only with respect to the progress
of the process. If we wish to count the number, n say, of people in
an initially empty room, we can achieve this by increasing n by one
whenever we see someone entering the room. In the in-between moment
that we have observed someone entering the room but have not yet
performed the subsequent increase of n, its value equals the number
of people in the room minus one!
The unbridled use of the go to statement has an immediate
consequence that it becomes terribly hard to find a meaningful set
of coordinates in which to describe the process progress. Usually,
people take into account as well the values of some well chosen
variables, but this is out of the question because it is relative to
the progress that the meaning of these values is to be understood!
With the go to statement one can, of course, still describe the
progress uniquely by a counter counting the number of actions
performed since program start (viz. a kind of normalized clock). The
difficulty is that such a coordinate, although unique, is utterly
unhelpful. In such a coordinate system it becomes an extremely
complicated affair to define all those points of progress where,
say, n equals the number of persons in the room minus one!
Your comparison between functions and goto has already shown to be
unfounded.
|
|
0
|
|
|
|
Reply
|
Daniel
|
4/24/2010 4:27:27 PM
|
|
On Apr 24, 11:50=A0pm, gaze...@shell.xmission.com (Kenny McCormack)
wrote:
> In article <EIOdnQHlmcFTj07WnZ2dnUVZ8h-dn...@giganews.com>,Leigh Johnston=
<le...@i42.co.uk> wrote:
>
> ...
>
> >This channel is about C++ not BASIC, you do not have to analyze the enti=
re
> >program in C++ as goto can only jump within the same function so compari=
sons
> >with BASIC is silly.
>
> (Channelling Kiki)
Shouldn't that be Mr. Thompson?
>
> >This channel
>
> channel???
More like Cartoon Network's Scoobie Doo Weekend.
>
> >is about C++ not BASIC, you do not have to analyze the entire
>
> C++ is not C (so says Kiki every chance he gets)
Surely you're shittin' me
Surely you jest
C plus plus not C?
Omigod is that on the test?
Surely that ole Kiki
Is a real giant brain
If he knows shit like that 'bout C
And how to code, int main()
Surely I'm not worthy
Surely I'm scum
Gotta listen to Kiki
Ooooooohhhh he makes me...get all excited or something...
Kiki made a wiki
On wikipedi-AH
About a god named tiki
And how to code in C-ah
But then an egregious Troll
Thought it would be Droll
To not call him Thompson
So Kiki got his machine gun
And he kilt the guy, Spinoza Ed
He kilt him so he was dead dead dead
This story has no moral
This story has no end
This story just goes to show
That Kiki's gone round the bend
(Dissolve to burning tires and dancing trolls)
>
> --
>
> > No, I haven't, that's why I'm asking questions. If you won't help me,
> > why don't you just go find your lost manhood elsewhere.
>
> CLC in a nutshell.
|
|
0
|
|
|
|
Reply
|
spinoza1111
|
4/24/2010 4:31:40 PM
|
|
On Apr 24, 11:48=A0pm, "Leigh Johnston" <le...@i42.co.uk> wrote:
> "Daniel T." <danie...@earthlink.net> wrote in message
>
> news:daniel_t-DBCC13.11141024042010@70-3-168-216.pools.spcsdns.net...
>
> > Ali Karaali <ali...@gmail.com> wrote:
>
> >> I use goto to break nested for loops and I can't see a
> >> reason to ban goto.
>
> > I'll give you a reason to ban goto. This is a line of BASIC code:
>
> > 90 x =3D 5
>
> > Now, I ask you, where is the line that was previously executed? Is it
> > directly above line 90, is it directly below it, or could it be anywher=
e
> > in the program? Because of the goto statement, simply because an
> > unstructured "goto" is possible in the language, you have to analyze th=
e
> > entire program to know the answer. If we ban the use of "goto", we can
> > confidently know exactly what line of code comes before line 90.
>
> This channel is about C++ not BASIC, you do not have to analyze the entir=
e
> program in C++ as goto can only jump within the same function so comparis=
ons
> with BASIC is silly.
That's been UNTRUE about the only Basic left standing (Visual Basic)
for at least twenty years, pard. Basic programs can be written as a
single main() with go tos, but so can C programs. Either style of
coding is possible if one's an idiot savant, twisted sick freak,
moron, or down a quart or more on a couple of computer science
classes.
However, just like C, modern Basic includes Function and Sub
constructs and structured programming. Indeed, buy my book I need the
money; it is "Build Your Own .Net Language and Compiler" (Apress 2004)
and it includes a fully structured and OO compiler for much of Quick
Basic, organized into functions and written in Visual Basic 2003. I
don't recall using Go To at all.
(Anybody who writes a compiler in Basic, even modern, structured
Basic, should either have his head examined or win some sort of Geek O
Rama prize, but when I asked my technical editor if I could write it
in C Sharp he said no.)
>
> /Leigh
|
|
0
|
|
|
|
Reply
|
spinoza1111
|
4/24/2010 4:37:15 PM
|
|
On Apr 24, 11:46=A0pm, "bartc" <ba...@freeuk.com> wrote:
> "Daniel T." <danie...@earthlink.net> wrote in message
>
> news:daniel_t-DBCC13.11141024042010@70-3-168-216.pools.spcsdns.net...
>
> > Ali Karaali <ali...@gmail.com> wrote:
>
> >> I use goto to break nested for loops and I can't see a
> >> reason to ban goto.
>
> > I'll give you a reason to ban goto. This is a line of BASIC code:
>
> > 90 x =3D 5
>
> > Now, I ask you, where is the line that was previously executed? Is it
> > directly above line 90, is it directly below it, or could it be anywher=
e
> > in the program? Because of the goto statement, simply because an
> > unstructured "goto" is possible in the language, you have to analyze th=
e
> > entire program to know the answer. If we ban the use of "goto", we can
> > confidently know exactly what line of code comes before line 90.
>
> Goto's at least are usually confined to the same function; if the functio=
n
> is smallish, you don't have to look far to match a goto with a label.
It's not a question of how far you have to look. It is a question of
minimal preconditions. If you have a go to even in a small program,
the code that follows it has a larger set of preconditions.
>
> Most languages will allow "x=3D5" inside a function; where is that functi=
on
> called from? It could be from anywhere in hundreds of modules.
>
> --
> Bartc
|
|
0
|
|
|
|
Reply
|
spinoza1111
|
4/24/2010 4:38:45 PM
|
|
On Apr 25, 12:27=A0am, "Daniel T." <danie...@earthlink.net> wrote:
> "bartc" <ba...@freeuk.com> wrote:
> > "Daniel T." <danie...@earthlink.net> wrote:
> > > Ali Karaali <ali...@gmail.com> wrote:
>
> > > > I use goto to break nested for loops and I can't see a reason to
> > > > ban goto.
>
> > > I'll give you a reason to ban goto. This is a line of BASIC code:
>
> > > 90 x =3D 5
>
> > > Now, I ask you, where is the line that was previously executed? Is
> > > it directly above line 90, is it directly below it, or could it be
> > > anywhere in the program? Because of the goto statement, simply
> > > because an unstructured "goto" is possible in the language, you have
> > > to analyze the entire program to know the answer. If we ban the use
> > > of "goto", we can confidently know exactly what line of code comes
> > > before line 90.
>
> > Goto's at least are usually confined to the same function; if the
> > function is smallish, you don't have to look far to match a goto with
> > a label.
>
> > Most languages will allow "x=3D5" inside a function; where is that
> > function called from? It could be from anywhere in hundreds of modules.
>
> As Dijkstra pointed out in "Go To Statement Considered Harmful"
>
> =A0 =A0As soon as we include in our language procedures we must admit tha=
t
> =A0 =A0a single textual index is no longer sufficient. In the case that a
> =A0 =A0textual index points to the interior of a procedure body the dynam=
ic
> =A0 =A0progress is only characterized when we also give to which call of
> =A0 =A0the procedure we refer. With the inclusion of procedures we can
> =A0 =A0characterize the progress of the process via a sequence of textual
> =A0 =A0indices, the length of this sequence being equal to the dynamic
> =A0 =A0depth of procedure calling.
>
> =A0 =A0...
>
> =A0 =A0The main point is that the values of these indices are outside
> =A0 =A0programmer's control; they are generated (either by the write-up o=
f
> =A0 =A0his program or by the dynamic evolution of the process) whether he
> =A0 =A0wishes or not. They provide independent coordinates in which to
> =A0 =A0describe the progress of the process.
>
> =A0 =A0Why do we need such independent coordinates? The reason is - and
> =A0 =A0this seems to be inherent to sequential processes - that we can
> =A0 =A0interpret the value of a variable only with respect to the progres=
s
> =A0 =A0of the process. If we wish to count the number, n say, of people i=
n
> =A0 =A0an initially empty room, we can achieve this by increasing n by on=
e
> =A0 =A0whenever we see someone entering the room. In the in-between momen=
t
> =A0 =A0that we have observed someone entering the room but have not yet
> =A0 =A0performed the subsequent increase of n, its value equals the numbe=
r
> =A0 =A0of people in the room minus one!
>
> =A0 =A0The unbridled use of the go to statement has an immediate
> =A0 =A0consequence that it becomes terribly hard to find a meaningful set
> =A0 =A0of coordinates in which to describe the process progress. Usually,
> =A0 =A0people take into account as well the values of some well chosen
> =A0 =A0variables, but this is out of the question because it is relative =
to
> =A0 =A0the progress that the meaning of these values is to be understood!
> =A0 =A0With the go to statement one can, of course, still describe the
> =A0 =A0progress uniquely by a counter counting the number of actions
> =A0 =A0performed since program start (viz. a kind of normalized clock). T=
he
> =A0 =A0difficulty is that such a coordinate, although unique, is utterly
> =A0 =A0unhelpful. In such a coordinate system it becomes an extremely
> =A0 =A0complicated affair to define all those points of progress where,
> =A0 =A0say, n equals the number of persons in the room minus one!
>
> Your comparison between functions and goto has already shown to be
> unfounded.
Brilliant, couldn't say it any better.
Programming, and coding's laws lay hidden in night:
God said, let Dijkstra be! And all was Light.
DIJSTRA! thou shouldst be living at this hour:
CLC hath need of thee: she is a fen
Of stagnant waters: fighting about void main
Programmers, once proud of their might and power
Have forfeited their ancient English dower 5
Of simple competence. We are selfish men;
O raise us up, return to us again,
And give us manners, virtue, freedom, power!
Thy soul was like a Star, and dwelt apart;
Thou hadst a voice whose sound was like the sea: 10
Pure as the naked heavens, majestic, free,
So didst thou travel on life's common way,
In cheerful godliness; and yet thy heart
The lowliest duties on herself did lay:
Even business programming you deigned to address
And at assembling railway trains you were a success:
You showed us how to make sure the Loo
Was equidistant from each chap, in the choo choo. [1]
Come back into the building, Dijkstra, like a God
Returning to earth to redeem both wise man and Clod.
[1] EWD365: A Parable, at http://userweb.cs.utexas.edu/users/EWD/transcript=
ions/EWD03xx/EWD365.html
|
|
0
|
|
|
|
Reply
|
spinoza1111
|
4/24/2010 4:49:18 PM
|
|
spinoza1111 <spinoza1111@yahoo.com> wrote:
> On Apr 24, 11:46�pm, "bartc" <ba...@freeuk.com> wrote:
> > "Daniel T." <danie...@earthlink.net> wrote:
> > > Ali Karaali <ali...@gmail.com> wrote:
> >
> > > > I use goto to break nested for loops and I can't see a reason to
> > > > ban goto.
> > >
> > > I'll give you a reason to ban goto. This is a line of BASIC code:
> > >
> > > 90 x = 5
> > >
> > > Now, I ask you, where is the line that was previously executed? Is
> > > it directly above line 90, is it directly below it, or could it be
> > > anywhere in the program? Because of the goto statement, simply
> > > because an unstructured "goto" is possible in the language, you
> > > have to analyze the entire program to know the answer. If we ban
> > > the use of "goto", we can confidently know exactly what line of
> > > code comes before line 90.
> >
> > Goto's at least are usually confined to the same function; if the
> > function is smallish, you don't have to look far to match a goto
> > with a label.
>
> It's not a question of how far you have to look. It is a question of
> minimal preconditions. If you have a go to even in a small program,
> the code that follows it has a larger set of preconditions.
Could you go into more detail? Maybe with some examples?
|
|
0
|
|
|
|
Reply
|
Daniel
|
4/24/2010 5:06:44 PM
|
|
"Ali Karaali" ha scritto nel messaggio
news:dda9d933-e9c1-418f-b62a-bc30bd1dd16c@r27g2000yqn.googlegroups.com...
>I use goto to break nested for loops and I can't see a
> reason to ban goto.
i would use goto or the asm extentions (jz, jnz, jnc, jc)
for all the programming
> Ali
|
|
0
|
|
|
|
Reply
|
io_x
|
4/24/2010 5:45:45 PM
|
|
"spinoza1111" ha scritto
Sorry i not have a computer science degree, i have a degree only
in math; possible i not merit it too, so possible
i not thought enough or not have the instruction
for speak about this argument.
[for instruction i mean study CS, math, phisic, history,
languages, biology, etc etc read books etc etc]
Hope so not to be in the ones that not understand problems
and propose not good solutions due his lack of think
to the argument or for not enough instruction
yes there are many ways, where will be the right way?
i'm just lazy
i'm not like you, all you
i think in how i can write something in less words possible
or in how beauty something in one page can be;
you can tell to "Bohm-Jacopini"
that, is not important where there are the enters
and where are the exits in a piece of code
the important is that all this is readable and followable
the important is that the eye can see all the code paths
and follow well what happen
for
>LOAD 0
>STOR i
>LBL1:
>LOAD i
>COMP limit
>IFGE LBL19
..
..
..
>IFEQ LBL12
>LOAD j
<STOR v
>GOTO LBL129
>LBL12:
>LOAD k
>STOR v2
>LBL129:
..
..
..
>LOAD i
>ADD 1
>STOR i
>GOTO LBL1
>LBL19:
here the readability is near to 0 because there is no indentation
not multi-line instructions
and because the assembly instructions are little
they have not need of big words
but they have need little len words
somethig like
<i
LBL1:
>i|i>=*limit#LBL19
....
cold be better traslated
push i
LBL1:
pop i|cmp i, [limit]|jGE LBL19
..
"mov eax, 19"
is not a big operation
not has need of big words
so could write it just as "a=19"
Assembly have one vantage too,
when write "mov eax, 19"
we know eax is a 32 bit register
instead in C or C++
"int a=19;"
and don't know how many bit are in "int"
|
|
0
|
|
|
|
Reply
|
io_x
|
4/24/2010 5:45:45 PM
|
|
"Alexei A. Frounze" ha scritto nel messaggio
news:9aedd878-0ccc-4f4a-b522-7e80b96f5fc5@m25g2000prj.googlegroups.com...
>On Apr 24, 3:13 am, "io_x" <a...@b.c.invalid> wrote:
>> [Xpost to: alt.comp.programming, alt.lang.asm,
>> comp.lang.c, comp.lang.c++, comp.programming]
>>
>> the people that speak not good about "goto"
>> are uttled wrong; their code bug full etc
>>
>> more distant is your code from goto
>> more your code is bug full and incompresible
>>
>> the "goto" is the key word for programming;
>> all the remain, other than goto or jmp or jc or jz,
>> and the easy cpu layout
>> is the wrong way for programming
>>
>> i advise all you
>> Good Morning
>Everything may be used, misused and abused, goto included. There are
>good and bad usage patterns and goto is not an exception here. I can
>list a number of other things that may be just as bad as a poorly used
>goto (or as good as a good goto). See?
what does it mean "patterns"?
all programming is all about choose the right gotos
>Alex
|
|
0
|
|
|
|
Reply
|
io_x
|
4/24/2010 5:45:45 PM
|
|
"Mensanator" ha scritto nel messaggio
news:5fd893eb-9dda-4c70-bf56-614b0f721874@u34g2000yqu.googlegroups.com...
On Apr 24, 5:13 am, "io_x" <a...@b.c.invalid> wrote:
>> [Xpost to: alt.comp.programming, alt.lang.asm,
>> comp.lang.c, comp.lang.c++, comp.programming]
>>
>> the people that speak not good about "goto"
>> are uttled wrong; their code bug full etc
>>
>> more distant is your code from goto
>> more your code is bug full and incompresible
>>
>> the "goto" is the key word for programming;
>> all the remain, other than goto or jmp or jc or jz,
>> and the easy cpu layout
>> is the wrong way for programming
>>
>> i advise all you
>> Good Morning
>Yeah, there's nothing more fun than converting BASIC to Pascal.
>
>Only to discover that goto was used to return from a sub-routine
>without clearing the stack.
all programming is all about choose the right gotos
and how to write them in the page.
point, end of programming difficulies,
there is nothing to say
|
|
0
|
|
|
|
Reply
|
io_x
|
4/24/2010 5:45:45 PM
|
|
On Sat, 24 Apr 2010 13:06:44 -0400, Daniel T. wrote:
> spinoza1111 <spinoza1111@yahoo.com> wrote:
>> On Apr 24, 11:46 pm, "bartc" <ba...@freeuk.com> wrote:
>> > "Daniel T." <danie...@earthlink.net> wrote:
>> > > Ali Karaali <ali...@gmail.com> wrote:
>> >
>>
>> It's not a question of how far you have to look. It is a question of
>> minimal preconditions. If you have a go to even in a small program, the
>> code that follows it has a larger set of preconditions.
>
> Could you go into more detail? Maybe with some examples?
IMHO the *readability* of "goto cleanup;" is not basically different
from a function call "do_cleanup();".
A function does not check its preconditions either.
In both cases the programmer can choose a name for the function or label.
And that name may or may not reflect its purpose.
AvK
|
|
0
|
|
|
|
Reply
|
Moi
|
4/24/2010 6:00:49 PM
|
|
On 2010-04-24, Daniel T. <daniel_t@earthlink.net> wrote:
> I'll give you a reason to ban goto. This is a line of BASIC code:
>
> 90 x = 5
>
> Now, I ask you, where is the line that was previously executed? Is it
> directly above line 90, is it directly below it, or could it be anywhere
> in the program? Because of the goto statement, simply because an
> unstructured "goto" is possible in the language, you have to analyze the
> entire program to know the answer. If we ban the use of "goto", we can
> confidently know exactly what line of code comes before line 90.
That's a great reason, but it's got nothing to do with C. In C, only
other code within the same function can have gone to this line, and that
only if there is a label immediately before this line.
-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
|
|
0
|
|
|
|
Reply
|
Seebs
|
4/24/2010 6:26:43 PM
|
|
"Daniel T." <daniel_t@earthlink.net> writes:
> Ali Karaali <alicpp@gmail.com> wrote:
>
>> I use goto to break nested for loops and I can't see a
>> reason to ban goto.
>
> I'll give you a reason to ban goto. This is a line of BASIC code:
>
> 90 x = 5
>
> Now, I ask you, where is the line that was previously executed? Is it
> directly above line 90, is it directly below it, or could it be anywhere
> in the program? Because of the goto statement, simply because an
> unstructured "goto" is possible in the language, you have to analyze the
> entire program to know the answer. If we ban the use of "goto", we can
> confidently know exactly what line of code comes before line 90.
You have to EXECUTE the entire program before knowing where you came
from, thanks to computed GOTOs :-)
--
__Pascal Bourguignon__
|
|
0
|
|
|
|
Reply
|
pjb
|
4/24/2010 6:31:19 PM
|
|
Seebs <usenet-nospam@seebs.net> writes:
> On 2010-04-24, Daniel T. <daniel_t@earthlink.net> wrote:
>> I'll give you a reason to ban goto. This is a line of BASIC code:
>>
>> 90 x = 5
>>
>> Now, I ask you, where is the line that was previously executed? Is it
>> directly above line 90, is it directly below it, or could it be anywhere
>> in the program? Because of the goto statement, simply because an
>> unstructured "goto" is possible in the language, you have to analyze the
>> entire program to know the answer. If we ban the use of "goto", we can
>> confidently know exactly what line of code comes before line 90.
>
> That's a great reason, but it's got nothing to do with C. In C, only
It's a ridiculous reason. The search for the goto LABEL is trivial and a
goto is often a LOT more obvious that some convoluted condition based
branch using lots of nested brackets.
> other code within the same function can have gone to this line, and that
> only if there is a label immediately before this line.
>
> -s
There is nothing wrong with Gotos when used in a controlled and
intelligent manner. Like the bullshit about single return points the
idea that gotos should not be used is generally just from 3rd rate
students who think it proves they program "structured" ....
--
"Avoid hyperbole at all costs, its the most destructive argument on
the planet" - Mark McIntyre in comp.lang.c
|
|
0
|
|
|
|
Reply
|
Richard
|
4/24/2010 6:41:54 PM
|
|
On Apr 24, 10:48=A0am, "io_x" <a...@b.c.invalid> wrote:
> "Alexei A. Frounze" ha scritto nel messaggionews:9aedd878-0ccc-4f4a-b522-=
7e80b96f5fc5@m25g2000prj.googlegroups.com...
>
>
>
> >On Apr 24, 3:13 am, "io_x" <a...@b.c.invalid> wrote:
> >> [Xpost to: alt.comp.programming, alt.lang.asm,
> >> comp.lang.c, comp.lang.c++, comp.programming]
>
> >> the people that speak not good about "goto"
> >> are uttled wrong; their code bug full etc
>
> >> more distant is your code from goto
> >> more your code is bug full and incompresible
>
> >> the "goto" is the key word for programming;
> >> all the remain, other than goto or jmp or jc or jz,
> >> and the easy cpu layout
> >> is the wrong way for programming
>
> >> i advise all you
> >> Good Morning
> >Everything may be used, misused and abused, goto included. There are
> >good and bad usage patterns and goto is not an exception here. I can
> >list a number of other things that may be just as bad as a poorly used
> >goto (or as good as a good goto). See?
>
> what does it mean "patterns"?
Not sure what you mean here.
> all programming is all about choose the right gotos
If your programs consisted only of gotos (as I infer from the above),
they would be useless. Programming is not all about choosing the right
gotos. Less so all programming. It's about many more things.
Alex
|
|
0
|
|
|
|
Reply
|
Alexei
|
4/24/2010 7:00:44 PM
|
|
In article <kkqba7-tu6.ln1@news.eternal-september.org>,
Richard <rgrdev_@gmail.com> wrote:
> Seebs <usenet-nospam@seebs.net> writes:
>
> > On 2010-04-24, Daniel T. <daniel_t@earthlink.net> wrote:
> >> I'll give you a reason to ban goto. This is a line of BASIC code:
> >>
> >> 90 x = 5
> >>
> >> Now, I ask you, where is the line that was previously executed? Is it
> >> directly above line 90, is it directly below it, or could it be anywhere
> >> in the program? Because of the goto statement, simply because an
> >> unstructured "goto" is possible in the language, you have to analyze the
> >> entire program to know the answer. If we ban the use of "goto", we can
> >> confidently know exactly what line of code comes before line 90.
> >
> > That's a great reason, but it's got nothing to do with C. In C, only
>
> It's a ridiculous reason. The search for the goto LABEL is trivial and a
> goto is often a LOT more obvious that some convoluted condition based
> branch using lots of nested brackets.
>
> > other code within the same function can have gone to this line, and that
> > only if there is a label immediately before this line.
> >
> > -s
>
> There is nothing wrong with Gotos when used in a controlled and
> intelligent manner. Like the bullshit about single return points the
> idea that gotos should not be used is generally just from 3rd rate
> students who think it proves they program "structured" ....
Like Spinny, you mean, with his "structured switch" twaddle.
--
Tim
"That excessive bail ought not to be required, nor excessive fines imposed,
nor cruel and unusual punishments inflicted" -- Bill of Rights 1689
|
|
0
|
|
|
|
Reply
|
Tim
|
4/24/2010 9:22:10 PM
|
|
Tim Streater <timstreater@waitrose.com> writes:
> In article
> <dda9d933-e9c1-418f-b62a-bc30bd1dd16c@r27g2000yqn.googlegroups.com>,
> Ali Karaali <alicpp@gmail.com> wrote:
>
>> I use goto to break nested for loops and I can't see a
>> reason to ban goto.
>>
>> Ali
>>
>> On 24 Nisan, 13:13, "io_x" <a...@b.c.invalid> wrote:
>> > [Xpost to: alt.comp.programming, alt.lang.asm,
>> > comp.lang.c, comp.lang.c++, comp.programming]
>> >
>> > the people that speak not good about "goto"
>> > are uttled wrong; their code bug full etc
>> >
>> > more distant is your code from goto
>> > more your code is bug full and incompresible
>> >
>> > the "goto" is the key word for programming;
>> > all the remain, other than goto or jmp or jc or jz,
>> > and the easy cpu layout
>> > is the wrong way for programming
>> >
>> > i advise all you
>> > Good Morning
>
> I haven't used a goto since 1978 (when I stopped writing FORTRAN).
I'm with Knuth. I've reviewed patches and told the submitter to
just convert all his jumble of 'structure' into nice clean goto
statements many times this year. I don't use it for my own code,
but $DAYJOB has a clear coding style that recommends goto in
many situations. If goto has made your function unreadable, it
was probably too big and unreadable anyway.
Phil
--
I find the easiest thing to do is to k/f myself and just troll away
-- David Melville on r.a.s.f1
|
|
0
|
|
|
|
Reply
|
Phil
|
4/24/2010 9:26:22 PM
|
|
On Apr 24, 10:26 pm, Phil Carmody <thefatphil_demun...@yahoo.co.uk>
wrote:
> Tim Streater <timstrea...@waitrose.com> writes:
> > I haven't used a goto since 1978 (when I stopped writing
> > FORTRAN).
Me neither.
> I'm with Knuth.
In other words, if goto makes the code simpler, it means that
you haven't found the correct expression of the algorithm.
And of course, the problem isn't with goto, per se. It's with
the way it is used. But because it can be abused so badly,
modern languages (including C and C++) provide all of the
necessary structures (and then some) so you don't have to use
it.
> I've reviewed patches and told the submitter to just convert
> all his jumble of 'structure' into nice clean goto statements
> many times this year. I don't use it for my own code, but
> $DAYJOB has a clear coding style that recommends goto in many
> situations. If goto has made your function unreadable, it was
> probably too big and unreadable anyway.
If goto seems necessary, it's because your function is too big
and unreadable.
--
James Kanze
|
|
0
|
|
|
|
Reply
|
James
|
4/24/2010 10:33:52 PM
|
|
On Apr 24, 12:48=A0pm, "io_x" <a...@b.c.invalid> wrote:
> "Mensanator" ha scritto nel messaggionews:5fd893eb-9dda-4c70-bf56-614b0f7=
21874@u34g2000yqu.googlegroups.com...
> On Apr 24, 5:13 am, "io_x" <a...@b.c.invalid> wrote:
>
>
>
>
>
> >> [Xpost to: alt.comp.programming, alt.lang.asm,
> >> comp.lang.c, comp.lang.c++, comp.programming]
>
> >> the people that speak not good about "goto"
> >> are uttled wrong; their code bug full etc
>
> >> more distant is your code from goto
> >> more your code is bug full and incompresible
>
> >> the "goto" is the key word for programming;
> >> all the remain, other than goto or jmp or jc or jz,
> >> and the easy cpu layout
> >> is the wrong way for programming
>
> >> i advise all you
> >> Good Morning
> >Yeah, there's nothing more fun than converting BASIC to Pascal.
>
> >Only to discover that goto was used to return from a sub-routine
> >without clearing the stack.
>
> all programming is all about choose the right gotos
No, it's not.
> and how to write them in the page.
Bullshit.
> point, end of programming difficulies,
You wish.
> there is nothing to say
Then why don't you shut up and quit saying it.
No one is interested in your prattle.
|
|
0
|
|
|
|
Reply
|
Mensanator
|
4/24/2010 10:35:48 PM
|
|
On Apr 24, 1:20 pm, "Leigh Johnston" <le...@i42.co.uk> wrote:
> "spinoza1111" <spinoza1...@yahoo.com> wrote in message
> news:051fa27d-5cf8-4f7e-94c8-e9e5b26566b7@g34g2000pro.googlegroups.com...
> > On Apr 24, 6:06 pm, Ali Karaali <ali...@gmail.com> wrote:
> >> I use goto to break nested for loops and I can't see a
> >> reason to ban goto.
> > Why not use break instead? Does the same thing, spares you
> > from having to define a label.
> Because break only breaks out of the innermost loop, using
> goto to break out of nested loops is one of the few sensible
> uses of goto.
But when do you have to break out of a nested loop? (And of
course, the only valid use of break in C++ is to end a case in a
switch. Otherwise, it's just a goto in disguise.)
--
James Kanze
|
|
0
|
|
|
|
Reply
|
James
|
4/24/2010 10:35:54 PM
|
|
On Apr 24, 5:12 pm, "Daniel T." <danie...@earthlink.net> wrote:
> "Leigh Johnston" <le...@i42.co.uk> wrote:
[...]
> In C and C++, goto is sufficiently restricted that as long as
> your functions are small, it is largely harmless.
In C and C++, if your functions are small enough, goto is
largely harmless. And also useless. All of the examples I've
seen defending goto introduce excessively complex functions in
order to justify it.
--
James Kanze
|
|
0
|
|
|
|
Reply
|
James
|
4/24/2010 10:41:20 PM
|
|
On Apr 24, 1:16 pm, p...@informatimago.com (Pascal J. Bourguignon)
wrote:
> "Alexei A. Frounze" <alexfrun...@gmail.com> writes:
[...]
> > Everything may be used, misused and abused, goto included.
> > There are good and bad usage patterns and goto is not an
> > exception here. I can list a number of other things that may
> > be just as bad as a poorly used goto (or as good as a good
> > goto). See?
Except that we're talking about C and C++ here, and in C and in
C++, for all "good" uses of goto (and a number of bad ones), the
language has specialized structures which better express the
meaning.
> Indeed. For example, the Duff device is worse than most gotos
> I've ever seen.
And it's fully structured:-).
Seriously, Duff himself said that it was an argument concerning
the way C implemented switch, but he wasn't sure whether it was
an argument for or against. (And it should probably be pointed
out that Duff used it to solve one very special problem, with
one specific compiler---his code almost certainly wouldn't work
correctly with any modern compiler.)
--
James Kanze
|
|
0
|
|
|
|
Reply
|
James
|
4/24/2010 10:47:06 PM
|
|
James Kanze <james.kanze@gmail.com> writes:
> On Apr 24, 1:16 pm, p...@informatimago.com (Pascal J. Bourguignon)
> wrote:
>> "Alexei A. Frounze" <alexfrun...@gmail.com> writes:
>
> [...]
>> > Everything may be used, misused and abused, goto included.
>> > There are good and bad usage patterns and goto is not an
>> > exception here. I can list a number of other things that may
>> > be just as bad as a poorly used goto (or as good as a good
>> > goto). See?
>
> Except that we're talking about C and C++ here, and in C and in
> C++, for all "good" uses of goto (and a number of bad ones), the
> language has specialized structures which better express the
> meaning.
>
>> Indeed. For example, the Duff device is worse than most gotos
>> I've ever seen.
>
> And it's fully structured:-).
>
> Seriously, Duff himself said that it was an argument concerning
> the way C implemented switch, but he wasn't sure whether it was
> an argument for or against. (And it should probably be pointed
> out that Duff used it to solve one very special problem, with
> one specific compiler---his code almost certainly wouldn't work
> correctly with any modern compiler.)
Well, it would depend on the C standard (perhaps the later
specifications changed), but AFAIK, this is the way C is specified, and
the Duff device should work on all compliant compiler.
--
__Pascal Bourguignon__
|
|
0
|
|
|
|
Reply
|
pjb
|
4/24/2010 11:03:12 PM
|
|
"James Kanze" <james.kanze@gmail.com> wrote in message
news:c5482414-a28a-4bf9-9402-f1f2b242b15f@r27g2000yqn.googlegroups.com...
>
> Except that we're talking about C and C++ here, and in C and in
> C++, for all "good" uses of goto (and a number of bad ones), the
> language has specialized structures which better express the
> meaning.
>
The post was cross-posted to five groups. You're seeing posts from a.l.a
and elsewhere - people uninterested in or unaware of C/C++.
I've removed the non-C/C++ groups on this post, I don't care to hear from a
few people on c.l.c. BTW, I also won't see a reply...
> Seriously, Duff himself said that it was an argument concerning
> the way C implemented switch, but he wasn't sure whether it was
> an argument for or against. (And it should probably be pointed
> out that Duff used it to solve one very special problem, with
> one specific compiler---his code almost certainly wouldn't work
> correctly with any modern compiler.)
>
If it doesn't work for C, that C compiler is _broken_. Nothing has changed
in C regarding the syntax he used. It's possible that it doesn't work for
C++, but then various aspects of C don't work correctly in C++ either...
Rod Pemberton
|
|
0
|
|
|
|
Reply
|
Rod
|
4/24/2010 11:48:53 PM
|
|
"io_x" <a@b.c.invalid> wrote in message
news:4bd2c215$0$1136$4fafbaef@reader1.news.tin.it...
> [Xpost to: alt.comp.programming, alt.lang.asm,
> comp.lang.c, comp.lang.c++, comp.programming]
>
> the people that speak not good about "goto"
> are uttled wrong; their code bug full etc
>
I learned structured programming concepts, just prior learning how to
program in an unstructured language: BASIC. So, I never had a problem with
GOTO's in BASIC. But, I knew someone who programmed in BASIC without using
structured programming concepts. He could code very quickly. But, every
now and then, he made a mistake. When he did, it was nearly impossible for
him to locate the incorrect code, typically an errant GOTO. He usually had
to delete his program and start again. For C, which has GOTO and structured
loops, I've only used GOTO once, for clarity.
From a certain perspective, needing "goto" is true, but only partially true.
All loops, control flow, etc., must be reduced to "goto" or "gosub", since
assembly only implements branches, jumps, calls, not higher level structured
loops. (x86 assembly is an exception, but the structured loop constructs
still aren't used...) So, from the perspective of assembly, goto's are
used. But, from a different perspective, BASIC or C, GOTO's cause problems.
They are unstructured. That means that a GOTO can branch out of one loop
and into another, intentionally or accidentally. Since most loops have a
loop variable or counter, this causes problems with a misplaced GOTO. The
jumped into loop may not terminate correctly. Adding to the problem, early
unstructured languages were line oriented. You could delete, insert, and
renumber lines. But, you had to manually correct the changed line number in
your GOTO's. I.e., you inserted line 32, had a GOTO from line 100 to line
35, after renumbering line 32 is 35 and 35 is 40, the GOTO still points to
line 35, i.e., formerly 32, when it should point to 40. So, structured
programming languages generally eliminate lines and line numbering.
Code that is hard to follow or fix because of haphazard use of GOTO's is
called "spaghetti code". Structured concepts fix this problem. They impose
a few rules and hide the GOTO's behind other language constructs: FOR,
DO-WHILE, WHILE, etc. Hiding GOTO's behind other language constructs
makes sure the use of GOTO's follows the rules for structured programming.
Structured programming generally requires a single entry and single exit
from any procedure or loop. The C language usually allows multiple exits
from it's procedures and loops. It's an exception when it comes to
structured programming languages. C doesn't support multiple entry, but
that can be simulated with constructs such as DUFF's device. However, C
still has GOTO. This allows for easy porting of code from other languages.
It's not needed to program. Using GOTO's in C, makes it *very* difficult to
restructure the flow of the program. GOTO can be used for speed improvement
to exit with many nested loops, but if the code was well written, the C
compiler's optimizer will generate just as efficient code without GOTO's.
It seems you stirred up the comp.lang.c, comp.lang.c++, crowds... I've
removed them from this post. I'm not interested in hearing from them that
my experience and knowledge is wrong.
Rod Pemberton
|
|
0
|
|
|
|
Reply
|
do_not_have6088 (68)
|
4/25/2010 12:18:55 AM
|
|
spinoza1111 wrote:
> On Apr 25, 12:27 am, "Daniel T." <danie...@earthlink.net> wrote:
>> "bartc" <ba...@freeuk.com> wrote:
>>> "Daniel T." <danie...@earthlink.net> wrote:
>>>> Ali Karaali <ali...@gmail.com> wrote:
>>
>>>>> I use goto to break nested for loops and I can't see a reason to
>>>>> ban goto.
>>>> 90 x = 5
>>
>>>> Now, I ask you, where is the line that was previously executed? Is
>>> Goto's at least are usually confined to the same function
>>> Most languages will allow "x=5" inside a function; where is that
>>> function called from?
>> As Dijkstra pointed out in "Go To Statement Considered Harmful"
>> As soon as we include in our language procedures we must admit that
>> a single textual index is no longer sufficient. In the case that a
.....
>> Your comparison between functions and goto has already shown to be
>> unfounded.
>
> Brilliant, couldn't say it any better.
That's a shame, because I didn't understand a word of the Dijkstra extract.
--
Bartc
|
|
0
|
|
|
|
Reply
|
bartc
|
4/25/2010 12:32:32 AM
|
|
On 2010-04-24, James Kanze <james.kanze@gmail.com> wrote:
> On Apr 24, 1:20 pm, "Leigh Johnston" <le...@i42.co.uk> wrote:
>> "spinoza1111" <spinoza1...@yahoo.com> wrote in message
>
>> news:051fa27d-5cf8-4f7e-94c8-e9e5b26566b7@g34g2000pro.googlegroups.com...
>
>> > On Apr 24, 6:06 pm, Ali Karaali <ali...@gmail.com> wrote:
>> >> I use goto to break nested for loops and I can't see a
>> >> reason to ban goto.
>
>> > Why not use break instead? Does the same thing, spares you
>> > from having to define a label.
>
>> Because break only breaks out of the innermost loop, using
>> goto to break out of nested loops is one of the few sensible
>> uses of goto.
>
> But when do you have to break out of a nested loop? (And of
> course, the only valid use of break in C++ is to end a case in a
> switch. Otherwise, it's just a goto in disguise.)
>
[dropped alt.comp.programming and alt.lang.asm since my
newsserver rejects an egregious number of cross-posts.]
This is just as true in C, according to some people (myself
included). The only exception I can think of is when you are
looping only to set the loop index to something.
ie,
for(i = 0; i < 10; ++i)
if(arr[i].state = READY)
break;
/* now use arr[i], or if i is 10, indicate failure. */
The alternative here, using the loop structure, would be:
for(i = 0; i < 10 && arr[i].state != READY; ++i)
;
/* now use arr[i], or if i is 10, indicate failure. */
To me, the latter option looks horrific, plus if you
swap the operands of &&, you get a very hard-to-spot
overrun.
--
Andrew Poelstra
http://www.wpsoftware.net/andrew
|
|
0
|
|
|
|
Reply
|
Andrew
|
4/25/2010 12:54:45 AM
|
|
On 2010-04-24, James Kanze <james.kanze@gmail.com> wrote:
> On Apr 24, 5:12 pm, "Daniel T." <danie...@earthlink.net> wrote:
>> "Leigh Johnston" <le...@i42.co.uk> wrote:
>
> [...]
>> In C and C++, goto is sufficiently restricted that as long as
>> your functions are small, it is largely harmless.
>
> In C and C++, if your functions are small enough, goto is
> largely harmless. And also useless. All of the examples I've
> seen defending goto introduce excessively complex functions in
> order to justify it.
>
[dropped alt.comp.programming and alt.lang.asm since my
newsserver rejects an egregious number of cross-posts.]
I often see code like
if(setup1() == 0)
goto fail;
if(setup2() == 0)
goto fail;
if(setup3() == 0)
goto fail;
/* now do stuff */
return 0;
fail:
/* :( */
return 1;
Personally, I would do this as:
if(setup1() &&
setup2() &&
setup3()) {
/* now do stuff */
return 0;
}
else {
/* :( */
return 1;
}
But from a stylistic view, the first version doesn't seem all
that bad. I see it a lot and it doesn't bother me, anyway.
--
Andrew Poelstra
http://www.wpsoftware.net/andrew
|
|
0
|
|
|
|
Reply
|
Andrew
|
4/25/2010 12:59:34 AM
|
|
Andrew Poelstra <apoelstra@localhost.localdomain> wrote:
> On 2010-04-24, James Kanze <james.kanze@gmail.com> wrote:
> > On Apr 24, 1:20 pm, "Leigh Johnston" <le...@i42.co.uk> wrote:
> > > "spinoza1111" <spinoza1...@yahoo.com> wrote:
> > > > On Apr 24, 6:06 pm, Ali Karaali <ali...@gmail.com> wrote:
> > > >
> > > > > I use goto to break nested for loops and I can't see a reason
> > > > > to ban goto.
> > > >
> > > > Why not use break instead? Does the same thing, spares you from
> > > > having to define a label.
> > >
> > > Because break only breaks out of the innermost loop, using goto to
> > > break out of nested loops is one of the few sensible uses of goto.
> >
> > But when do you have to break out of a nested loop? (And of course,
> > the only valid use of break in C++ is to end a case in a switch.
> > Otherwise, it's just a goto in disguise.)
>
> This is just as true in C, according to some people (myself included).
> The only exception I can think of is when you are looping only to set
> the loop index to something.
>
> ie,
>
> for(i = 0; i < 10; ++i)
> if(arr[i].state = READY)
> break;
> /* now use arr[i], or if i is 10, indicate failure. */
>
> The alternative here, using the loop structure, would be:
>
> for(i = 0; i < 10 && arr[i].state != READY; ++i)
> ;
> /* now use arr[i], or if i is 10, indicate failure. */
>
> To me, the latter option looks horrific, plus if you swap the operands
> of &&, you get a very hard-to-spot overrun.
I agree that your for loop with an empty body "looks horrific." However:
int findReady(MyStruct* arr, int size) {
int result = 0;
for ( ; result < size; ++result)
if (arr[result].state == READY)
break;
return result;
}
The above also looks pretty "horrific" to me. (Because of the empty
initialization and the fact that there are two loop exit conditions that
are expressed on two different lines and exit from two different places.
All unnecessarily.)
I would be inclined to do something more like:
int findReady(MyStruct* arr, int size) {
int result = 0;
while (result < size && arr[result].state != READY)
++result;
return result;
}
This example better expresses the end condition of the loop, and doesn't
have any uninitialized variables or empty statement blocks.
Near the beginning of my career, I did code maintenance and I would
sometimes find loops with multiple breaks along with a continue or two.
I learned to fear such constructs even without formerly learning
structured programming.
|
|
0
|
|
|
|
Reply
|
Daniel
|
4/25/2010 1:46:43 AM
|
|
On 2010-04-24, James Kanze <james.kanze@gmail.com> wrote:
> In other words, if goto makes the code simpler, it means that
> you haven't found the correct expression of the algorithm.
I don't think that's necessarily the case.
> And of course, the problem isn't with goto, per se. It's with
> the way it is used. But because it can be abused so badly,
> modern languages (including C and C++) provide all of the
> necessary structures (and then some) so you don't have to use
> it.
Of course not. However, you may have to either use it, or use additional
time or storage to produce the same results.
> If goto seems necessary, it's because your function is too big
> and unreadable.
I don't agree. Nested cleanup, in C, often benefits a lot from goto.
It's not always the best choice, but it can dramatically simplify some
functions... And in many cases, breaking them out would require a great
deal of effort to duplicate/pass data which was previously just internal
to a given function.
-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
|
|
0
|
|
|
|
Reply
|
Seebs
|
4/25/2010 2:47:16 AM
|
|
On 2010-04-25, Andrew Poelstra <apoelstra@localhost.localdomain> wrote:
> I often see code like
> if(setup1() == 0)
> goto fail;
>
> if(setup2() == 0)
> goto fail;
>
> if(setup3() == 0)
> goto fail;
>
> /* now do stuff */
>
> return 0;
> fail:
> /* :( */
> return 1;
> Personally, I would do this as:
>
> if(setup1() &&
> setup2() &&
> setup3()) {
> /* now do stuff */
> return 0;
> }
> else {
> /* :( */
> return 1;
> }
> But from a stylistic view, the first version doesn't seem all
> that bad. I see it a lot and it doesn't bother me, anyway.
It gets worse when there's non-trivial work which needs to be done
between the various setup(), and/or they have to interact with more
than one or two local variables. There's also the fairly common
idiom:
if (setup1())
goto fail;
if (setup2())
goto teardown1;
if (setup3())
goto teardown2;
/* various stuff */
if (something_went_wrong)
goto teardown3;
/* more stuff */
teardown3:
teardown3();
teardown2:
teardown2();
teardown1:
teardown1();
fail:
return -1;
This has the advantage that, if later you need to add a setup2_5(), you don't
have to go to multiple different places later in the code and add a
teardown2_5().
In general, I find that overly dogmatic structuring tends to reduce
readability. The "obvious" alternative to the above:
if (!setup1()) {
if (!setup2()) {
if (!setup3()) {
/* various stuff */
if (!something_went_wrong) {
/* more stuff */
}
teardown3();
}
teardown2();
}
teardown1();
}
is, IMHO, less readable and less maintainable. It's harder to track
where you are by looking at indentation, and there's less room on a
default-width screen for writing clear code inside /* more stuff */.
-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
|
|
0
|
|
|
|
Reply
|
Seebs
|
4/25/2010 2:53:26 AM
|
|
On Apr 24, 9:10=A0pm, "Daniel T." <danie...@earthlink.net> wrote:
> ...
> everyone who is tempted to argue about this issue to start from
> Dijkstra's paper rather than simply asserting that "goto is good"
> without understanding the issues involved.
>
> http://www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_
> Harmful.html
I did click the link, though I'm sure I'd read the paper a few times
earlier.
It has one key sentence which I think is now widely understood:
Edsger W. Dijkstra wrote:
> The unbridled use of the go to statement has an immediate consequence
> that it becomes terribly hard to find a meaningful set of coordinates
> in which to describe the process progress.
(Hmmm. Dijkstra *does* write "UNBRIDLED use of goto". Funny how that
disappears from the pedants' sound-bite summaries.)
Dijkstra speaks of "meaningful ... coordinates ... to describe ..."
I think that when state machines are implemented with goto's, the goto
*helps* to map such "coordinates": the transition rules move you to
state 36 so you ... GOTO state39!
One of my own goto's appears horrendous, but is actually just
a way to go to the appropriate progress point when the "meaningful
coordinates" have been established:
Pseudo-code comparison
http://fabpedigree.com/james/gotoalt.htm
Actual C code
http://fabpedigree.com/james/dbldum.htm
(Warning: if anyone *does* say anything good about my code,
it will be a first, and I'll probably faint from the exhiliration!)
> http://www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_
> Harmful.html
PS: Your newswriter seems to have clipped the link, Daniel, which
I then had to hand-enter. I think Google Groups would have gotten
it right, so you may want to switch to that: :-)
> http://www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_=
Harmful.html
James Dow Allen
|
|
0
|
|
|
|
Reply
|
James
|
4/25/2010 3:17:52 AM
|
|
On Apr 25, 10:17=A0am, James Dow Allen <jdallen2...@yahoo.com> wrote:
> PS: =A0Your newswriter seems to have clipped the link, Daniel, which
> I then had to hand-enter. =A0I think Google Groups would have gotten
> it right, so you may want to switch to that: =A0:-)
Yes, Google's link did work. And yes, it was tongue-in-cheek of
me to suggest you switch to Google. :-)
Nevertheless I will point out that some pedants delight in ranting
at every Google bug. When Google gets it right and their news
software doesn't, they seem to view the non-Google foibles as
"treasured souvenirs of a bygone superior era." :-)
Just saying.
|
|
0
|
|
|
|
Reply
|
James
|
4/25/2010 3:22:00 AM
|
|
On Apr 25, 5:47=A0am, James Kanze <james.ka...@gmail.com> wrote:
> [Duff's device] almost certainly wouldn't work
> correctly with any modern [C] compiler.
I just noticed this and was startled! I'd have guessed
that it *would* work correctly with any modern bug-free
compiler. I can't check right now, but I might recall the
Device *is* used in glib functions like memcpy().
Dennis Ritchie, IIRC, said the Device would work with
any C compiler that "I [Ritchie] believe in."
It might be fun for experts on The Standard to determine
whether or not the Device is *guaranteed* to work.
James Dow Allen
|
|
0
|
|
|
|
Reply
|
James
|
4/25/2010 3:31:51 AM
|
|
On 2010-04-25, James Dow Allen <jdallen2000@yahoo.com> wrote:
> It might be fun for experts on The Standard to determine
> whether or not the Device is *guaranteed* to work.
So far as I can tell, it's been consistently agreed that of course
it would work.
-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
|
|
0
|
|
|
|
Reply
|
Seebs
|
4/25/2010 3:45:30 AM
|
|
On 2010-04-25, Daniel T. <daniel_t@earthlink.net> wrote:
>
> Near the beginning of my career, I did code maintenance and I would
> sometimes find loops with multiple breaks along with a continue or two.
> I learned to fear such constructs even without formerly learning
> structured programming.
>
I am working on porting a codebase full of monstronsities such as
while(1) {
if(condition) {
continue;
} else
break;
}
These ones I would rewrite completely, even though I was trying
to tread very lightly and change almost nothing. (At this stage
of porting, I didn't yet realize that the real problems had to
do with the code trying to do DMA without asking the VMM first,
so every small change caused a change in what was cached in CPU
and the program's behavior would change from randomly wrong to a
different sort of randomly wrong.)
This was but one of many WTF's littered throughout the code,
and is certainly a strong argument for the Just Don't Use Break
crowd.
--
Andrew Poelstra
http://www.wpsoftware.net/andrew
|
|
0
|
|
|
|
Reply
|
Andrew
|
4/25/2010 5:02:27 AM
|
|
On 2010-04-25, Seebs <usenet-nospam@seebs.net> wrote:
> On 2010-04-25, James Dow Allen <jdallen2000@yahoo.com> wrote:
>> It might be fun for experts on The Standard to determine
>> whether or not the Device is *guaranteed* to work.
>
> So far as I can tell, it's been consistently agreed that of course
> it would work.
>
I can't imagine ever saying "of course" in regards to Duff's Device.
;)
--
Andrew Poelstra
http://www.wpsoftware.net/andrew
|
|
0
|
|
|
|
Reply
|
Andrew
|
4/25/2010 5:05:14 AM
|
|
In comp.lang.c++ Ali Karaali <alicpp@gmail.com> wrote:
> I use goto to break nested for loops and I can't see a
> reason to ban goto.
No. The correct keyword for breaking out of nested loops (in C++) is
'return'. If you are using 'goto' for that purpose, you are doing it
wrong.
"It's not the same thing". Precisely. If you design your code such that
you can always use 'return' to break out of nested loops, it will become
cleaner and easier to understand.
I have been programming in C++ both professionally and as a hobby for
over 10 years, and I have never got into a situation where 'goto' would
have been a tempting alternative because of being a simpler and more
straightforward solution than something else. It just doesn't come up.
I don't remember ever having written a 'goto' in the last 10+ years.
It's not a question of banning 'goto'. There is no *need* for 'goto'.
And if you code in such way that you just don't need it, your code will
become cleaner in a completely natural way.
|
|
0
|
|
|
|
Reply
|
Juha
|
4/25/2010 5:09:15 AM
|
|
On Apr 25, 1:06=A0am, "Daniel T." <danie...@earthlink.net> wrote:
> spinoza1111<spinoza1...@yahoo.com> wrote:
> > On Apr 24, 11:46=A0pm, "bartc" <ba...@freeuk.com> wrote:
> > > "Daniel T." <danie...@earthlink.net> wrote:
> > > > Ali Karaali <ali...@gmail.com> wrote:
>
> > > > > I use goto to break nested for loops and I can't see a reason to
> > > > > ban goto.
>
> > > > I'll give you a reason to ban goto. This is a line of BASIC code:
>
> > > > 90 x =3D 5
>
> > > > Now, I ask you, where is the line that was previously executed? Is
> > > > it directly above line 90, is it directly below it, or could it be
> > > > anywhere in the program? Because of the goto statement, simply
> > > > because an unstructured "goto" is possible in the language, you
> > > > have to analyze the entire program to know the answer. If we ban
> > > > the use of "goto", we can confidently know exactly what line of
> > > > code comes before line 90.
>
> > > Goto's at least are usually confined to the same function; if the
> > > function is smallish, you don't have to look far to match a goto
> > > with a label.
>
> > It's not a question of how far you have to look. It is a question of
> > minimal preconditions. If you have a go to even in a small program,
> > the code that follows it has a larger set of preconditions.
>
> Could you go into more detail? Maybe with some examples?
For every go to there is a label. For each place that control "comes
from" there is a separate bundle of facts that cane be true.
|
|
0
|
|
|
|
Reply
|
spinoza1111
|
4/25/2010 5:21:48 AM
|
|
On 4/24/2010 5:54 PM, Andrew Poelstra wrote:
> The alternative here, using the loop structure, would be:
>
> for(i = 0; i< 10&& arr[i].state != READY; ++i)
> ;
> /* now use arr[i], or if i is 10, indicate failure. */
>
As a purely stylistic matter, my empty loops always look like:
for ( begin_expr; test_expr; next_expr)
/* do nothing */ ;
That is, I always explicitly comment the empty loop so that
it's clear that I wanted the loop to be empty.
Makes life easier later on down the line.
|
|
0
|
|
|
|
Reply
|
red
|
4/25/2010 6:19:49 AM
|
|
In comp.lang.c++ red floyd <no.spam.here@its.invalid> wrote:
> As a purely stylistic matter, my empty loops always look like:
>
> for ( begin_expr; test_expr; next_expr)
> /* do nothing */ ;
No, the proper way of writing an empty loop is:
for(begin_expr; test_expr; next_expr) {}
The empty block makes it explicitly clear that it's intended to be empty,
and not just a typo. (The empty block could also be put in the next line,
below the 'for', if so desired. A matter of style.)
|
|
0
|
|
|
|
Reply
|
Juha
|
4/25/2010 7:02:51 AM
|
|
On Apr 24, 3:33=A0pm, James Kanze <james.ka...@gmail.com> wrote:
> On Apr 24, 10:26 pm, Phil Carmody <thefatphil_demun...@yahoo.co.uk>
> wrote:
>
> > Tim Streater <timstrea...@waitrose.com> writes:
> > > I haven't used a goto since 1978 (when I stopped writing
> > > FORTRAN).
>
> Me neither.
>
> > I'm with Knuth.
>
> In other words, if goto makes the code simpler, it means that
> you haven't found the correct expression of the algorithm.
>
> And of course, the problem isn't with goto, per se. =A0It's with
> the way it is used. =A0But because it can be abused so badly,
> modern languages (including C and C++) provide all of the
> necessary structures (and then some) so you don't have to use
> it.
I wish there were distinct breaks for loops and switches as well as
multi-level breaks for nested loops. goto's at times are the least
evil since they don't require you to implement extra variables to
break out of nested loops and they help to simplify function cleanup
code (where resources are being freed on various conditions).
> > I've reviewed patches and told the submitter to just convert
> > all his jumble of 'structure' into nice clean goto statements
> > many times this year. I don't use it for my own code, but
> > $DAYJOB has a clear coding style that recommends goto in many
> > situations. If goto has made your function unreadable, it was
> > probably too big and unreadable anyway.
>
> If goto seems necessary, it's because your function is too big
> and unreadable.
But you don't want too many trivial functions either for you won't see
the forest behind the trees. There should be a certain balance,
subjective, of course, but it's not like goto's are evil no matter
what. If they are evil, let's remember about pointers, which require a
lot of care. And about horrible type conversions, where you can't even
safely compare a signed int and an unsigned int (which is an absurd
thing, IMO). And then about non-portable things, about implementation-
defined/specific and undefined behavior. Now we're talking. goto is
just nothing compared to all of that. :)
Alex
|
|
0
|
|
|
|
Reply
|
Alexei
|
4/25/2010 7:46:45 AM
|
|
Juha Nieminen wrote:
> In comp.lang.c++ red floyd <no.spam.here@its.invalid> wrote:
>> As a purely stylistic matter, my empty loops always look like:
>>
>> for ( begin_expr; test_expr; next_expr)
>> /* do nothing */ ;
>
> No, the proper way of writing an empty loop is:
>
> for(begin_expr; test_expr; next_expr) {}
>
> The empty block makes it explicitly clear that it's intended to be
> empty,
> and not just a typo. (The empty block could also be put in the next line,
> below the 'for', if so desired. A matter of style.)
No, the proper way of writing an empty loop is:
for(begin_expr; test_expr; next_expr) ;
The semicolon makes it explicitly clear that it's intended to be
empty, and not just a typo. (The semicolon could also be put in the next
line, below the 'for', if so desired. A matter of style.)
Couldn't resist :-)
Best
Kai-Uwe Bux
|
|
0
|
|
|
|
Reply
|
Kai
|
4/25/2010 7:53:58 AM
|
|
On Apr 24, 10:09=A0pm, Juha Nieminen <nos...@thanks.invalid> wrote:
> In comp.lang.c++ Ali Karaali <ali...@gmail.com> wrote:
>
> > I use goto to break nested for loops and I can't see a
> > reason to ban goto.
>
> =A0 No. The correct keyword for breaking out of nested loops (in C++) is
> 'return'. If you are using 'goto' for that purpose, you are doing it
> wrong.
Now, let's consider C (or C++ where this function has to explicitly
free up some used resources or do some other cleanup). The objects
won't get freed here automatically by the magic of the destructor call
generated for you by the C++ compiler. You could implement the cleanup
code in several places of that function as block operators ending with
a return, but very often these blocks are to a certain degree
duplicates of one another. And it's not just the source code bloat
that's bad, it's also us making a trap for ourselves because one day
we may modify the function and forget to modify one or more of these
cleanup block operators in it.
> =A0 "It's not the same thing". Precisely. If you design your code such th=
at
> you can always use 'return' to break out of nested loops, it will become
> cleaner and easier to understand.
>
> =A0 I have been programming in C++ both professionally and as a hobby for
> over 10 years, and I have never got into a situation where 'goto' would
> have been a tempting alternative because of being a simpler and more
> straightforward solution than something else. It just doesn't come up.
> I don't remember ever having written a 'goto' in the last 10+ years.
>
> =A0 It's not a question of banning 'goto'. There is no *need* for 'goto'.
> And if you code in such way that you just don't need it, your code will
> become cleaner in a completely natural way.
Surprisingly, my code is pretty clean with gotos, which, btw, I use
just for almost exclusively 2 things:
- breaking out of nested loops (not always, if I can do that w/o
writing more than two lines of code, I don't use goto)
- jumping to the common cleanup code at the end of the function when I
detect some error
I get by without goto in almost all other situations. I don't see
what's not natural here. It's a clearly written and structured code,
that is easy to follow, without surprises, without bloat. Of course,
if you never need to do any cleanup or you never check error
conditions or rely heavily on C++ exceptions, the 2nd use may be just
unnatural to you as it is to me since I'm programming C, mixed C and C+
+ and I often have to deal explicitly with resource allocation.
Alex
|
|
0
|
|
|
|
Reply
|
Alexei
|
4/25/2010 8:07:01 AM
|
|
On Apr 25, 1:09=A0pm, Juha Nieminen <nos...@thanks.invalid> wrote:
> In comp.lang.c++ Ali Karaali <ali...@gmail.com> wrote:
>
> > I use goto to break nested for loops and I can't see a
> > reason to ban goto.
>
> =A0 No. The correct keyword for breaking out of nested loops (in C++) is
> 'return'. If you are using 'goto' for that purpose, you are doing it
> wrong.
Don't you mean "break"? Return exits the containing function and has
its place, certainly, under abnormal conditions. But break goes to the
statement following the loop and is considered acceptably structured
in reality, because it can be so readily simulated as I've shown using
a flag.
>
> =A0 "It's not the same thing". Precisely. If you design your code such th=
at
> you can always use 'return' to break out of nested loops, it will become
> cleaner and easier to understand.
>
> =A0 I have been programming in C++ both professionally and as a hobby for
> over 10 years, and I have never got into a situation where 'goto' would
> have been a tempting alternative because of being a simpler and more
> straightforward solution than something else. It just doesn't come up.
> I don't remember ever having written a 'goto' in the last 10+ years.
>
> =A0 It's not a question of banning 'goto'. There is no *need* for 'goto'.
> And if you code in such way that you just don't need it, your code will
> become cleaner in a completely natural way.
|
|
0
|
|
|
|
Reply
|
spinoza1111
|
4/25/2010 8:09:04 AM
|
|
"Rod Pemberton" ha scritto nel messaggio
> "io_x" <a@b.c.invalid> wrote in message
> Structured programming generally requires a single entry and single exit
> from any procedure or loop.
it should be for one loop one single entry but one or more exits
[at last for error code "more exits"]
> It seems you stirred up the comp.lang.c, comp.lang.c++, crowds... I've
> removed them from this post. I'm not interested in hearing from them that
> my experience and knowledge is wrong.
they not understand that all with goto is easy, easier than their
difficult way of describe one algorithm, and more flexible
|
|
0
|
|
|
|
Reply
|
io_x
|
4/25/2010 8:31:41 AM
|
|
Seebs wrote:
> On 2010-04-25, Andrew Poelstra <apoelstra@localhost.localdomain>
> wrote:
>> I often see code like
>
>> if(setup1() == 0)
>> goto fail;
>>
>> if(setup2() == 0)
>> goto fail;
>>
>> if(setup3() == 0)
>> goto fail;
>>
>> /* now do stuff */
>>
>> return 0;
>> fail:
>> /* :( */
>> return 1;
>
>> Personally, I would do this as:
>>
>> if(setup1() &&
>> setup2() &&
>> setup3()) {
>> /* now do stuff */
>> return 0;
>> }
>> else {
>> /* :( */
>> return 1;
>> }
>
>> But from a stylistic view, the first version doesn't seem all
>> that bad. I see it a lot and it doesn't bother me, anyway.
>
> It gets worse when there's non-trivial work which needs to be done
> between the various setup(), and/or they have to interact with more
> than one or two local variables. There's also the fairly common
> idiom:
>
> if (setup1())
> goto fail;
>
> if (setup2())
> goto teardown1;
>
> if (setup3())
> goto teardown2;
>
> /* various stuff */
> if (something_went_wrong)
> goto teardown3;
> /* more stuff */
>
> teardown3:
> teardown3();
> teardown2:
> teardown2();
> teardown1:
> teardown1();
> fail:
> return -1;
>
> This has the advantage that, if later you need to add a setup2_5(),
> you don't have to go to multiple different places later in the code
> and add a teardown2_5().
>
> In general, I find that overly dogmatic structuring tends to reduce
> readability. The "obvious" alternative to the above:
>
> if (!setup1()) {
> if (!setup2()) {
> if (!setup3()) {
> /* various stuff */
> if (!something_went_wrong) {
> /* more stuff */
> }
> teardown3();
> }
> teardown2();
> }
> teardown1();
> }
>
> is, IMHO, less readable and less maintainable. It's harder to track
> where you are by looking at indentation, and there's less room on a
> default-width screen for writing clear code inside /* more stuff */.
>
> -s
Guess why C++ added destructors to automatically destroy objects that
go out of scope.
Sorry, couldn't resist. :-)
Bo Persson
|
|
0
|
|
|
|
Reply
|
Bo
|
4/25/2010 8:51:05 AM
|
|
On Apr 24, 5:18=A0pm, "Rod Pemberton" <do_not_h...@havenone.cmm> wrote:
....
> used. =A0But, from a different perspective, BASIC or C, GOTO's cause prob=
lems.
> They are unstructured. =A0That means that a GOTO can branch out of one lo=
op
> and into another, intentionally or accidentally. =A0Since most loops have=
a
> loop variable or counter, this causes problems with a misplaced GOTO. =A0=
The
> jumped into loop may not terminate correctly. =A0
We can misplace and incorrectly reorder many things, not just goto's.
If you restrict the use of goto in C/C++ to several simple patterns
and write your code carefully, goto's aren't really a problem.
Alex
|
|
0
|
|
|
|
Reply
|
alexfrunews (33)
|
4/25/2010 9:20:07 AM
|
|
On Apr 24, 5:18=A0pm, "Rod Pemberton" <do_not_h...@havenone.cmm> wrote:
> It seems you stirred up the comp.lang.c, comp.lang.c++, crowds... =A0I've
> removed them from this post. =A0I'm not interested in hearing from them t=
hat
> my experience and knowledge is wrong.
Stay away from purists and idealists, they are far too often too
strict and offer impractical advice. :)
I too have been bitten by those folks. That's not to say I didn't
learn anything from the experience -- I spent quite some time figuring
out proper C as per its standard and started coding more portably and
defensively (but that's a totally different story).
Alex
|
|
0
|
|
|
|
Reply
|
alexfrunews (33)
|
4/25/2010 9:49:15 AM
|
|
On 24 Apr, 16:48, "Leigh Johnston" <le...@i42.co.uk> wrote:
> "Daniel T." <danie...@earthlink.net> wrote in message
>
> news:daniel_t-DBCC13.11141024042010@70-3-168-216.pools.spcsdns.net...
>
> > Ali Karaali <ali...@gmail.com> wrote:
>
> >> I use goto to break nested for loops and I can't see a
> >> reason to ban goto.
>
> > I'll give you a reason to ban goto. This is a line of BASIC code:
>
> > 90 x = 5
>
> > Now, I ask you, where is the line that was previously executed? Is it
> > directly above line 90, is it directly below it, or could it be anywhere
> > in the program? Because of the goto statement, simply because an
> > unstructured "goto" is possible in the language, you have to analyze the
> > entire program to know the answer. If we ban the use of "goto", we can
> > confidently know exactly what line of code comes before line 90.
>
> This channel is about C++ not BASIC, you do not have to analyze the entire
> program in C++ as goto can only jump within the same function so comparisons
> with BASIC is silly.
there's longjmp
though even that can only jump upstack
|
|
0
|
|
|
|
Reply
|
Nick
|
4/25/2010 9:50:07 AM
|
|
On Apr 25, 5:50=A0pm, Nick Keighley <nick_keighley_nos...@hotmail.com>
wrote:
> On 24 Apr, 16:48, "Leigh Johnston" <le...@i42.co.uk> wrote:
>
>
>
>
>
> > "Daniel T." <danie...@earthlink.net> wrote in message
>
> >news:daniel_t-DBCC13.11141024042010@70-3-168-216.pools.spcsdns.net...
>
> > > Ali Karaali <ali...@gmail.com> wrote:
>
> > >> I use goto to break nested for loops and I can't see a
> > >> reason to ban goto.
>
> > > I'll give you a reason to ban goto. This is a line of BASIC code:
>
> > > 90 x =3D 5
>
> > > Now, I ask you, where is the line that was previously executed? Is it
> > > directly above line 90, is it directly below it, or could it be anywh=
ere
> > > in the program? Because of the goto statement, simply because an
> > > unstructured "goto" is possible in the language, you have to analyze =
the
> > > entire program to know the answer. If we ban the use of "goto", we ca=
n
> > > confidently know exactly what line of code comes before line 90.
>
> > This channel is about C++ not BASIC, you do not have to analyze the ent=
ire
> > program in C++ as goto can only jump within the same function so compar=
isons
> > with BASIC is silly.
>
> there's longjmp
> though even that can only jump upstack
Hmm, I never have to use longjmp, since I tend to factor more.
Factoring a problem is resisted in Amerikkkan programming because
Amerikkkan managers don't want employees to be "creative", and it
takes a minimal amount of creativity to create a new C function.
Employees who learn how to construct and manage large systems are
innately dangerous, since their knowledge might transfer to labor
union organization or political causes above the level of Tea Baggery.
This is why properly factored code that consists of properly
functionally bound units often ENRAGES managers, and programmers
alienated and dispirited by the corporate rat race.
If it contains small functions whose purpose can be expressed in a
well-constructed sentence it is an image of a decent society in a
society that thrives on exporting death and importing alienation.
It's ideologically safer to use slop programmerese such as "I don't
wanna call dis function in multiple cases becuz dat is bad" in order
to show you know your place in the pecking order.
The ideal program is a single main() routine that does everything: a
model of a Fascist society.
Ein reich! Ein Fuhrer!
|
|
0
|
|
|
|
Reply
|
spinoza1111
|
4/25/2010 10:28:18 AM
|
|
"James Kanze" <james.kanze@gmail.com> wrote in message
news:30002fc4-d539-446c-ac84-84dcf5b8c954@t36g2000yqt.googlegroups.com...
> On Apr 24, 10:26 pm, Phil Carmody <thefatphil_demun...@yahoo.co.uk>
> wrote:
>> Tim Streater <timstrea...@waitrose.com> writes:
>> > I haven't used a goto since 1978 (when I stopped writing
>> > FORTRAN).
>
> Me neither.
>
>> I'm with Knuth.
>
> In other words, if goto makes the code simpler, it means that
> you haven't found the correct expression of the algorithm.
That may not matter. Sometimes goto or multi-level break can be a useful,
temporary way out of a tricky situation.
Later on it can be fixed up properly, but often the code is still subject to
changes and might end up completely differently or even disappear entirely.
No point in that case to introduce extra variables, logic, functions, in
short turn the code upside down to remove a goto or break, when a minute
later you have to do it all again.
> And of course, the problem isn't with goto, per se. It's with
> the way it is used. But because it can be abused so badly,
> modern languages (including C and C++) provide all of the
> necessary structures (and then some) so you don't have to use
> it.
There are sometimes nice control structures not directly available in the
language (language designers seem a conservative bunch...). Although it
would be better to try and get along with what there is, goto is a useful
extra tool, especially if translating from another, more expressive
language.
But it can cause problems if used without discipline and in a haphazard
manner (jumping into or out of expressions for example). But then, so can
any other feature.
--
Bartc
|
|
0
|
|
|
|
Reply
|
bartc
|
4/25/2010 10:32:01 AM
|
|
"James Kanze" <james.kanze@gmail.com> wrote in message
news:f8ad45ef-b5e6-488c-8940-5841b2408e0b@11g2000yqr.googlegroups.com...
> On Apr 24, 1:20 pm, "Leigh Johnston" <le...@i42.co.uk> wrote:
>> "spinoza1111" <spinoza1...@yahoo.com> wrote in message
>
>> news:051fa27d-5cf8-4f7e-94c8-e9e5b26566b7@g34g2000pro.googlegroups.com...
>
>> > On Apr 24, 6:06 pm, Ali Karaali <ali...@gmail.com> wrote:
>> >> I use goto to break nested for loops and I can't see a
>> >> reason to ban goto.
>
>> > Why not use break instead? Does the same thing, spares you
>> > from having to define a label.
>
>> Because break only breaks out of the innermost loop, using
>> goto to break out of nested loops is one of the few sensible
>> uses of goto.
>
> But when do you have to break out of a nested loop? (And of
> course, the only valid use of break in C++ is to end a case in a
> switch. Otherwise, it's just a goto in disguise.)
>
> --
> James Kanze
I don't use goto much, I have just three uses of it in my entire codebase
and in all cases it is for breaking out of a nested control structure: two
are for exiting a switch inside a while loop and the other is exiting a
nested for loop. The alternative to using goto in these cases would involve
the creation of an extra exit flag that would have to be checked at each
level which is not always desirable.
/Leigh
|
|
0
|
|
|
|
Reply
|
Leigh
|
4/25/2010 10:54:56 AM
|
|
Juha Nieminen <nospam@thanks.invalid> writes:
> In comp.lang.c++ Ali Karaali <alicpp@gmail.com> wrote:
>> I use goto to break nested for loops and I can't see a
>> reason to ban goto.
>
> No. The correct keyword for breaking out of nested loops (in C++) is
> 'return'. If you are using 'goto' for that purpose, you are doing it
> wrong.
This is a purely religious point of view.
> "It's not the same thing". Precisely. If you design your code such that
> you can always use 'return' to break out of nested loops, it will become
> cleaner and easier to understand.
In that case you have to pass all state into and out of the function
that performs the nested loop. That might be significantly less
efficient than just having all the state locally, such that the target
of a goto still has access to it all. Again, your point of view looks
religious and blinkered.
> I have been programming in C++ both professionally and as a hobby for
> over 10 years
One should never flaunt ones lack of experience in order to back up
ones argument.
Phil
--
I find the easiest thing to do is to k/f myself and just troll away
-- David Melville on r.a.s.f1
|
|
0
|
|
|
|
Reply
|
Phil
|
4/25/2010 10:55:52 AM
|
|
James Kanze <james.kanze@gmail.com> writes:
> On Apr 24, 1:20 pm, "Leigh Johnston" <le...@i42.co.uk> wrote:
>> "spinoza1111" <spinoza1...@yahoo.com> wrote in message
>
>> news:051fa27d-5cf8-4f7e-94c8-e9e5b26566b7@g34g2000pro.googlegroups.com...
>
>> > On Apr 24, 6:06 pm, Ali Karaali <ali...@gmail.com> wrote:
>> >> I use goto to break nested for loops and I can't see a
>> >> reason to ban goto.
>
>> > Why not use break instead? Does the same thing, spares you
>> > from having to define a label.
>
>> Because break only breaks out of the innermost loop, using
>> goto to break out of nested loops is one of the few sensible
>> uses of goto.
>
> But when do you have to break out of a nested loop?
For the same reason you want to break out of a single loop.
Do you have issues with people breaking out of single loops?
> (And of
> course, the only valid use of break in C++ is to end a case in a
> switch. Otherwise, it's just a goto in disguise.)
What do you mean by 'otherwise' - even that's just a goto in disguise?
Phil
--
I find the easiest thing to do is to k/f myself and just troll away
-- David Melville on r.a.s.f1
|
|
0
|
|
|
|
Reply
|
Phil
|
4/25/2010 11:17:27 AM
|
|
Phil Carmody wrote:
> Juha Nieminen <nospam@thanks.invalid> writes:
>> In comp.lang.c++ Ali Karaali <alicpp@gmail.com> wrote:
>>> I use goto to break nested for loops and I can't see a
>>> reason to ban goto.
>>
>> No. The correct keyword for breaking out of nested loops (in
>> C++) is 'return'. If you are using 'goto' for that purpose, you
>> are doing it wrong.
>
> This is a purely religious point of view.
Yes. :-)
>
>> "It's not the same thing". Precisely. If you design your code
>> such that you can always use 'return' to break out of nested
>> loops, it will become cleaner and easier to understand.
>
> In that case you have to pass all state into and out of the function
> that performs the nested loop. That might be significantly less
> efficient than just having all the state locally, such that the
> target of a goto still has access to it all. Again, your point of
> view looks religious and blinkered.
I guess James means that in the "properly designed" code, the state
you operate on is already part of the class' state. Adding another
member function doesn't affect the code efficiency. At least not more
that the presence of a goto and label might disturb the efficiency of
the compiler optimizer.
Bo Persson
|
|
0
|
|
|
|
Reply
|
Bo
|
4/25/2010 11:28:35 AM
|
|
Andrew Poelstra <apoelstra@localhost.localdomain> writes:
> I often see code like
>
> if(setup1() == 0)
> goto fail;
>
> if(setup2() == 0)
> goto fail;
>
> if(setup3() == 0)
> goto fail;
>
> /* now do stuff */
>
> return 0;
> fail:
> /* :( */
> return 1;
You forgot to do the unsetup3(), unsetup2(), and unsetup1() as
appropriate for the setup*() that succeeded above. Congratulations,
you've leaked memory, left a file open, and locked a semaphore.
> Personally, I would do this as:
>
> if(setup1() &&
> setup2() &&
> setup3()) {
> /* now do stuff */
> return 0;
> }
> else {
> /* :( */
> return 1;
> }
Where would the unsetup3() call go in the above?
> But from a stylistic view, the first version doesn't seem all
> that bad. I see it a lot and it doesn't bother me, anyway.
I never particularly liked goto, but sometimes they are the simplest
and most readable thing to do. It's the standard in the project I'm
currently working on, for example. Far better than disguised gotos
such as do { /* ... */ break; /* ... */ } while(0);
Phil
--
I find the easiest thing to do is to k/f myself and just troll away
-- David Melville on r.a.s.f1
|
|
0
|
|
|
|
Reply
|
Phil
|
4/25/2010 11:30:54 AM
|
|
"io_x" wrote:
> [Xpost to: alt.comp.programming, alt.lang.asm,
> comp.lang.c, comp.lang.c++, comp.programming]
> the people that speak not good about "goto"
> are uttled wrong; their code bug full etc
> more distant is your code from goto
> more your code is bug full and incompresible
> the "goto" is the key word for programming;
> all the remain, other than goto or jmp or jc or jz,
> and the easy cpu layout
> is the wrong way for programming
Except that GOTO is a HLL keyword and I'm Asmist and
more machine-code oriented than concerned about needs
within abstract structured HLL-compilers, I see nothing
wrong with GOTO as long it does what a programmer want.
I once checked PowerBasic's GOTO and found it always
compiled a long (16:16) jump, even rare required.
But its syntax checker cried aloud if you tried to
jump out of a [FOR/IF/...]-struct with GOTO.
I don't know C/C+-, but what I see by disassembling their
resulting output seem to end up in heavy bloated code,
perhaps from using BREAK and GOTO within nested blocks,
which the compiler may grant with copying all required
code-trails (stack recover/cleanup) to every added path.
So in this aspect GOTO may be really not the best choice.
see me happy for I don't need to care this in my world :)
__
wolfgang (ALA)
|
|
0
|
|
|
|
Reply
|
wolfgang
|
4/25/2010 11:49:58 AM
|
|
"Bo Persson" <bop@gmb.dk> writes:
> Phil Carmody wrote:
>> Juha Nieminen <nospam@thanks.invalid> writes:
>>> In comp.lang.c++ Ali Karaali <alicpp@gmail.com> wrote:
>>>> I use goto to break nested for loops and I can't see a
>>>> reason to ban goto.
>>>
>>> No. The correct keyword for breaking out of nested loops (in
>>> C++) is 'return'. If you are using 'goto' for that purpose, you
>>> are doing it wrong.
>>
>> This is a purely religious point of view.
>
> Yes. :-)
>
>>
>>> "It's not the same thing". Precisely. If you design your code
>>> such that you can always use 'return' to break out of nested
>>> loops, it will become cleaner and easier to understand.
>>
>> In that case you have to pass all state into and out of the function
>> that performs the nested loop. That might be significantly less
>> efficient than just having all the state locally, such that the
>> target of a goto still has access to it all. Again, your point of
>> view looks religious and blinkered.
>
> I guess James means that in the "properly designed" code, the state
> you operate on is already part of the class' state.
If you think that the only state that is important is the state
of the object being acted upon, then you must not use _any_ other
variables at all in your methods, as they too contain state. Even
if they are a pure function of the object's state, by throwing that
away you then have to re-derive it, which is waste.
> Adding another
> member function doesn't affect the code efficiency. At least not more
> that the presence of a goto and label might disturb the efficiency of
> the compiler optimizer.
It's certainly true that gotos can sometimes decrease efficiency, I
don't deny that, simply because they may carry too much state around.
Without a goto, you might be able to assume a==b or c<=0, for example,
and the goto might prevent useful optimisations based on those
assumptions.
Phil
--
I find the easiest thing to do is to k/f myself and just troll away
-- David Melville on r.a.s.f1
|
|
0
|
|
|
|
Reply
|
Phil
|
4/25/2010 12:09:35 PM
|
|
Andrew Poelstra <apoelstra@localhost.localdomain> writes:
> On 2010-04-25, Daniel T. <daniel_t@earthlink.net> wrote:
>>
>> Near the beginning of my career, I did code maintenance and I would
>> sometimes find loops with multiple breaks along with a continue or two.
>> I learned to fear such constructs even without formerly learning
>> structured programming.
>>
>
> I am working on porting a codebase full of monstronsities such as
>
> while(1) {
> if(condition) {
> continue;
> } else
> break;
> }
<snip>
>
> This was but one of many WTF's littered throughout the code,
> and is certainly a strong argument for the Just Don't Use Break
> crowd.
I disagree. The code is horrid and should not have been written but it
is no more an argument against break than an ugly sentence is an
argument about the words used in it.
I like to imagine that there is something akin to good taste in
programming. Even people with impeccable taste will swear on occasion
if the situation merits it; so programmers who code tastefully will
sometimes use continue or break.
If that is too twee a notion, you can consider giving various C
constructs a "obfuscation cost" with the objective being to code with
the minimum cost. For me, the cost of an extra Boolean variable is
slightly higher than that of a simple break in a loop but, as always,
YMMV.
--
Ben.
|
|
0
|
|
|
|
Reply
|
Ben
|
4/25/2010 1:39:32 PM
|
|
Alexei A. Frounze wrote:
....
> Surprisingly, my code is pretty clean with gotos, which, btw, I use
> just for almost exclusively 2 things:
> - breaking out of nested loops (not always, if I can do that w/o
> writing more than two lines of code, I don't use goto)
> - jumping to the common cleanup code at the end of the function when I
> detect some error
....
When I was first considering using Java for a project, I was a little
worried about the lack of goto.
I knew I had written a couple of gotos in C and maintained code
containing goto that would have had to be much more convoluted without
it. When I analyzed those uses of goto, I realized they were all in
those two categories, mainly the common cleanup code case.
That meant I would not need goto in a language with try-finally and
named loop break.
Patricia
|
|
0
|
|
|
|
Reply
|
Patricia
|
4/25/2010 1:56:32 PM
|
|
Ben Bacarisse <ben.usenet@bsb.me.uk> wrote:
> I like to imagine that there is something akin to good taste in
> programming. Even people with impeccable taste will swear on occasion
> if the situation merits it; so programmers who code tastefully will
> sometimes use continue or break.
I like your analogy. Only use continue, break or goto when appropriate.
The problem is that all of us agree with that sentiment (even Dijkstra
didn't say it should be outlawed completely,) the debate is about how
much use is appropriate.
|
|
0
|
|
|
|
Reply
|
Daniel
|
4/25/2010 1:59:45 PM
|
|
In article <slrnht74s4.6l9.apoelstra@localhost.localdomain>,
Andrew Poelstra <apoelstra@localhost.localdomain> wrote:
> I often see code like
>
> if(setup1() == 0)
> goto fail;
>
> if(setup2() == 0)
> goto fail;
>
> if(setup3() == 0)
> goto fail;
>
> /* now do stuff */
>
> return 0;
> fail:
> /* :( */
> return 1;
>
>
> Personally, I would do this as:
>
> if(setup1() &&
> setup2() &&
> setup3()) {
> /* now do stuff */
> return 0;
> }
> else {
> /* :( */
> return 1;
> }
>
> But from a stylistic view, the first version doesn't seem all
> that bad. I see it a lot and it doesn't bother me, anyway.
Personally I'd do:
// Get error cases out of the way first
if (setup1()==0 || setup2()==0 || setup2()==0) return 1;
// Now, no indentation needed for the real work
// Now do stuff
return 0;
I also see no reason to stick to short lines of code (some of mine are
150 or so long).
--
Tim
"That excessive bail ought not to be required, nor excessive fines imposed,
nor cruel and unusual punishments inflicted" -- Bill of Rights 1689
|
|
0
|
|
|
|
Reply
|
Tim
|
4/25/2010 2:36:35 PM
|
|
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> Andrew Poelstra <apoelstra@localhost.localdomain> writes:
>
>> On 2010-04-25, Daniel T. <daniel_t@earthlink.net> wrote:
>>>
>>> Near the beginning of my career, I did code maintenance and I would
>>> sometimes find loops with multiple breaks along with a continue or two.
>>> I learned to fear such constructs even without formerly learning
>>> structured programming.
>>>
>>
>> I am working on porting a codebase full of monstronsities such as
>>
>> while(1) {
>> if(condition) {
>> continue;
>> } else
>> break;
>> }
> <snip>
>>
>> This was but one of many WTF's littered throughout the code,
>> and is certainly a strong argument for the Just Don't Use Break
>> crowd.
>
> I disagree. The code is horrid and should not have been written but it
> is no more an argument against break than an ugly sentence is an
> argument about the words used in it.
>
> I like to imagine that there is something akin to good taste in
> programming. Even people with impeccable taste will swear on occasion
> if the situation merits it; so programmers who code tastefully will
> sometimes use continue or break.
>
> If that is too twee a notion, you can consider giving various C
> constructs a "obfuscation cost" with the objective being to code with
> the minimum cost. For me, the cost of an extra Boolean variable is
> slightly higher than that of a simple break in a loop but, as always,
> YMMV.
There is nothing whatsoever wrong with a break statement - it frequently
helps against overly convoluted loop conditions.
--
"Avoid hyperbole at all costs, its the most destructive argument on
the planet" - Mark McIntyre in comp.lang.c
|
|
0
|
|
|
|
Reply
|
Richard
|
4/25/2010 3:01:19 PM
|
|
James Dow Allen <jdallen2000@yahoo.com> wrote:
> On Apr 24, 9:10�pm, "Daniel T." <danie...@earthlink.net> wrote:
> > ...
> > everyone who is tempted to argue about this issue to start from
> > Dijkstra's paper rather than simply asserting that "goto is good"
> > without understanding the issues involved.
> >
> > http://www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_
> > Harmful.html
>
> I did click the link, though I'm sure I'd read the paper a few times
> earlier. It has one key sentence which I think is now widely
> understood: Edsger W. Dijkstra wrote:
> > The unbridled use of the go to statement has an immediate
> > consequence that it becomes terribly hard to find a meaningful set
> > of coordinates in which to describe the process progress.
>
> (Hmmm. Dijkstra *does* write "UNBRIDLED use of goto". Funny how that
> disappears from the pedants' sound-bite summaries.)
Agreed, and many also fail to notice that it is rather hard to use goto
in an "unbridled" fashion in C and C++.
> One of my own goto's appears horrendous, but is actually just a way to
> go to the appropriate progress point when the "meaningful coordinates"
> have been established:
> Pseudo-code comparison
> http://fabpedigree.com/james/gotoalt.htm
> Actual C code
> http://fabpedigree.com/james/dbldum.htm
>
> (Warning: if anyone *does* say anything good about my code, it will be
> a first, and I'll probably faint from the exhiliration!)
It looks as though you have implemented a depth first search. (If it
isn't a depth first search, then I'd say your code isn't readable.) That
said, I fully agree that your code is better than the psudo-code you
present in comparison (you call it "Tim's code".) However, there are
better ways of implementing depth first searches than either of the two
you present.
|
|
0
|
|
|
|
Reply
|
Daniel
|
4/25/2010 3:03:05 PM
|
|
Kai-Uwe Bux <jkherciueh@gmx.net> wrote:
> Juha Nieminen wrote:
> > red floyd <no.spam.here@its.invalid> wrote:
> >
> > > As a purely stylistic matter, my empty loops always look like:
> > >
> > > for ( begin_expr; test_expr; next_expr)
> > > /* do nothing */ ;
> >
> > No, the proper way of writing an empty loop is:
> >
> > for(begin_expr; test_expr; next_expr) {}
> >
> > The empty block makes it explicitly clear that it's intended to be
> > empty, and not just a typo. (The empty block could also be put in
> > the next line, below the 'for', if so desired. A matter of style.)
>
> No, the proper way of writing an empty loop is:
>
> for(begin_expr; test_expr; next_expr) ;
>
> The semicolon makes it explicitly clear that it's intended to be
> empty, and not just a typo. (The semicolon could also be put in the
> next line, below the 'for', if so desired. A matter of style.)
>
> Couldn't resist :-)
I was resisting, until I saw that you couldn't, so I won't either... :-)
The proper way of writing an empty loop is to not do it.
begin_expr;
while (test_expr) {
next_expr;
}
|
|
0
|
|
|
|
Reply
|
Daniel
|
4/25/2010 3:14:13 PM
|
|
Patricia Shanahan <pats@acm.org> writes:
> Alexei A. Frounze wrote:
> ...
>> Surprisingly, my code is pretty clean with gotos, which, btw, I use
>> just for almost exclusively 2 things:
>> - breaking out of nested loops (not always, if I can do that w/o
>> writing more than two lines of code, I don't use goto)
>> - jumping to the common cleanup code at the end of the function when I
>> detect some error
> ...
>
> When I was first considering using Java for a project, I was a little
> worried about the lack of goto.
>
> I knew I had written a couple of gotos in C and maintained code
> containing goto that would have had to be much more convoluted without
> it. When I analyzed those uses of goto, I realized they were all in
> those two categories, mainly the common cleanup code case.
>
> That meant I would not need goto in a language with try-finally and
> named loop break.
I'm not a java person at all, but from what I understand try-finally
doesn't do what I use goto for, namely error-path cleanup. If, according
to Sun, "the finally block always executes when the try block exits",
then it's not error-path clean-up at all - it's unconditional cleanup.
Which is completely not what you want in a function whose job is to
acquire a bunch of resources.
Phil
--
I find the easiest thing to do is to k/f myself and just troll away
-- David Melville on r.a.s.f1
|
|
0
|
|
|
|
Reply
|
Phil
|
4/25/2010 3:27:43 PM
|
|
Phil Carmody wrote:
> Patricia Shanahan <pats@acm.org> writes:
>> Alexei A. Frounze wrote:
>> ...
>>> Surprisingly, my code is pretty clean with gotos, which, btw, I use
>>> just for almost exclusively 2 things:
>>> - breaking out of nested loops (not always, if I can do that w/o
>>> writing more than two lines of code, I don't use goto)
>>> - jumping to the common cleanup code at the end of the function when I
>>> detect some error
>> ...
>>
>> When I was first considering using Java for a project, I was a little
>> worried about the lack of goto.
>>
>> I knew I had written a couple of gotos in C and maintained code
>> containing goto that would have had to be much more convoluted without
>> it. When I analyzed those uses of goto, I realized they were all in
>> those two categories, mainly the common cleanup code case.
>>
>> That meant I would not need goto in a language with try-finally and
>> named loop break.
>
> I'm not a java person at all, but from what I understand try-finally
> doesn't do what I use goto for, namely error-path cleanup. If, according
> to Sun, "the finally block always executes when the try block exits",
> then it's not error-path clean-up at all - it's unconditional cleanup.
> Which is completely not what you want in a function whose job is to
> acquire a bunch of resources.
....
I should have mentioned the use of a catch block to deal with
error-specific clean-up. The finally block is, indeed, the place for
unconditional clean-up.
Of course, memory clean-up is not an issue in Java, but there are other
resources that need explicit handling.
Patricia
|
|
0
|
|
|
|
Reply
|
Patricia
|
4/25/2010 3:34:26 PM
|
|
On Apr 24, 6:41 pm, James Kanze <james.ka...@gmail.com> wrote:
> On Apr 24, 5:12 pm, "Daniel T." <danie...@earthlink.net> wrote:
>
> > "Leigh Johnston" <le...@i42.co.uk> wrote:
>
> [...]
>
> > In C and C++, goto is sufficiently restricted that as long as
> > your functions are small, it is largely harmless.
>
> In C and C++, if your functions are small enough, goto is
> largely harmless. And also useless. All of the examples I've
> seen defending goto introduce excessively complex functions in
> order to justify it.
The Kuzmin circle tracing algorithm is certainly not "excessively
complex" and is an (elegant) example of goto being /necessary/ to
to provide the optimal solution in some very real and important
scenarios. There was a moderated flame war about this nine months
ago culminating with these final posts
http://groups.google.com/group/comp.lang.c++.moderated/msg/3ac2368e485e740d
http://groups.google.com/group/comp.lang.c++.moderated/msg/5beca2fac77f7ab9
that empirically proved beyond any contestation at the time that
the goto version was optimal in some scenarios. All the source
code, scripts, etc are still available at
http://www.duggar.org/pub/code/circle/
to anyone who wishes to /rationally/ challenge the results with
empirical evidence. Otherwise continued unconditional anti-goto
preaching is simply anti-intellectual religion and certainly not
computer science.
Note these empirical results could (should?) have been "expected"
from the fact that Knuth already mathematically proved, decades
ago, that certain goto structures cannot be transformed into the
"structured" forms without introducing additional calculations or
code duplication both of which can be suboptimal on both old and
modern physical platforms not only on abstract computers.
Finally, if you do try and measure results note that the provided
code takes exceptional care when it comes to certain things that
to the naive might seem unimportant such as removal of constants,
randomization, control of inlining, avoidance of monolithic
compilation, etc. That is all /necessary/ for accurate profiling
which can be tricky to say the least. That was one source of the
disagreement in that original thread, ie one participant who
thought he was "all that" was simply ignorant of many of those
real world profiling and measurement considerations.
Subsequently I discussed that flame war with one of the worlds
genius compiler writers who confirmed the necessity of the inlining
etc controls explained above. However, he also added that in his
experience it is pointless to argue with the anti-goto mob because
it is a religion that ignores all inconvenient empirical evidence.
KHD
|
|
0
|
|
|
|
Reply
|
Keith
|
4/25/2010 3:36:14 PM
|
|
"Alexei A. Frounze" <alexfrunews@gmail.com> writes:
> Surprisingly, my code is pretty clean with gotos, which, btw, I use
> just for almost exclusively 2 things:
> - breaking out of nested loops (not always, if I can do that w/o
> writing more than two lines of code, I don't use goto)
> - jumping to the common cleanup code at the end of the function when I
> detect some error
> I get by without goto in almost all other situations. I don't see
> what's not natural here. It's a clearly written and structured code,
> that is easy to follow, without surprises, without bloat. Of course,
> if you never need to do any cleanup or you never check error
> conditions or rely heavily on C++ exceptions, the 2nd use may be just
> unnatural to you as it is to me since I'm programming C, mixed C and C+
> + and I often have to deal explicitly with resource allocation.
I've just looked at my pile of code and there are no actual gotos in
there (there is a setjmp/longjmp pair, and a fair smattering of breaks,
continues and returns from part way through functions).
There seems to be a fairly common situation when you are programming,
particularly in C where you have to do a lot of stuff yourself, that
there isn't a "nice" way to deal with. This is when you have 3 or 4
lines of code that need to be executed under conditional circumstances
and in different but related places.
Making them into functions makes reading the code harder, and they don't
really make sense as a conceptual chunk of code. Embedding them in the
code can lead to convoluted flow control - and it's here that goto and
various other tricks tend to get invoked.
The clean-up example is a common one, but it's not the only one.
Just today I found myself in such a situation where I had two such
blocks which, depending on a couple of conditions, I wanted to execute
one, the other, or both in both orders - right in the middle of a large
function. So putting the code in functions several pages away from
where they were needed wasn't nice, and short of jumping around (either
with a loop even though there is only a single pass, or with goto) the
only other solution is to replicate the code.
In the end I compromised and with a bit of playing around was able to
reduce the shorter to a single line of fairly straightforward code, so
didn't mind repeating it inside conditionals either side of the larger
one. Still not a perfect solution of course.
--
Online waterways route planner | http://canalplan.eu
Plan trips, see photos, check facilities | http://canalplan.org.uk
|
|
0
|
|
|
|
Reply
|
Nick
|
4/25/2010 3:52:24 PM
|
|
"Alexei A. Frounze" <alexfrunews@gmail.com> wrote in message
news:aab23e01-b4d4-44c4-a136-a619da00a3f7@m24g2000prc.googlegroups.com...
> I wish there were distinct breaks for loops and switches as well as
> multi-level breaks for nested loops. goto's at times are the least
> evil since they don't require you to implement extra variables to
> break out of nested loops and they help to simplify function cleanup
> code (where resources are being freed on various conditions).
Amusing that Fortran has a mechanism to break out of nested loops
and permits one to use internal subroutines for function cleanup,
not to mention no fall-through in SELECT CASE constructs. These uses
of goto are simply artifacts of the limitations of C-style languages.
--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end
|
|
0
|
|
|
|
Reply
|
James
|
4/25/2010 4:18:54 PM
|
|
On Apr 25, 6:56=A0am, Patricia Shanahan <p...@acm.org> wrote:
> Alexei A. Frounze wrote:
>
> ...> Surprisingly, my code is pretty clean with gotos, which, btw, I use
> > just for almost exclusively 2 things:
> > - breaking out of nested loops (not always, if I can do that w/o
> > writing more than two lines of code, I don't use goto)
> > - jumping to the common cleanup code at the end of the function when I
> > detect some error
>
> ...
>
> When I was first considering using Java for a project, I was a little
> worried about the lack of goto.
>
> I knew I had written a couple of gotos in C and maintained code
> containing goto that would have had to be much more convoluted without
> it. When I analyzed those uses of goto, I realized they were all in
> those two categories, mainly the common cleanup code case.
>
> That meant I would not need goto in a language with try-finally and
> named loop break.
>
> Patricia
Of course, you could do that. And even if it was plain C but with
removed goto, you'd still be able to do your work.
Alex
|
|
0
|
|
|
|
Reply
|
Alexei
|
4/25/2010 5:27:17 PM
|
|
On Apr 25, 8:52=A0am, Nick <3-nos...@temporary-address.org.uk> wrote:
> "Alexei A. Frounze" <alexfrun...@gmail.com> writes:
>
> > Surprisingly, my code is pretty clean with gotos, which, btw, I use
> > just for almost exclusively 2 things:
> > - breaking out of nested loops (not always, if I can do that w/o
> > writing more than two lines of code, I don't use goto)
> > - jumping to the common cleanup code at the end of the function when I
> > detect some error
> > I get by without goto in almost all other situations. I don't see
> > what's not natural here. It's a clearly written and structured code,
> > that is easy to follow, without surprises, without bloat. Of course,
> > if you never need to do any cleanup or you never check error
> > conditions or rely heavily on C++ exceptions, the 2nd use may be just
> > unnatural to you as it is to me since I'm programming C, mixed C and C+
> > + and I often have to deal explicitly with resource allocation.
>
> I've just looked at my pile of code and there are no actual gotos in
> there (there is a setjmp/longjmp pair, and a fair smattering of breaks,
> continues and returns from part way through functions).
>
> There seems to be a fairly common situation when you are programming,
> particularly in C where you have to do a lot of stuff yourself, that
> there isn't a "nice" way to deal with. =A0This is when you have 3 or 4
> lines of code that need to be executed under conditional circumstances
> and in different but related places.
>
> Making them into functions makes reading the code harder, and they don't
> really make sense as a conceptual chunk of code. =A0Embedding them in the
> code can lead to convoluted flow control - and it's here that goto and
> various other tricks tend to get invoked.
>
> The clean-up example is a common one, but it's not the only one.
>
> Just today I found myself in such a situation where I had two such
> blocks which, depending on a couple of conditions, I wanted to execute
> one, the other, or both in both orders - right in the middle of a large
> function. =A0So putting the code in functions several pages away from
> where they were needed wasn't nice, and short of jumping around (either
> with a loop even though there is only a single pass, or with goto) the
> only other solution is to replicate the code.
>
> In the end I compromised and with a bit of playing around was able to
> reduce the shorter to a single line of fairly straightforward code, so
> didn't mind repeating it inside conditionals either side of the larger
> one. =A0Still not a perfect solution of course.
> --
> Online waterways route planner =A0 =A0 =A0 =A0 =A0 =A0|http://canalplan.e=
u
> Plan trips, see photos, check facilities =A0|http://canalplan.org.uk
I don't know if this would work or not for your specific case, but if
blocks are sufficiently large and it's exactly one or both in either
order in the same place, then you could theoretically do something
like this:
#include <stdio.h>
int main(void)
{
const int ss[4][2] =3D
{
{ 1, 1 },
{ 2, 2 },
{ 1, 2 },
{ 2, 1 }
};
int i, cnt, start, stop, var;
for (i =3D 0; i < 4; i++)
{
start =3D ss[i][0];
stop =3D ss[i][1];
for (var =3D start, cnt =3D 1 + (start !=3D stop);
cnt--;
var +=3D (stop >=3D start) ? 1 : -1)
{
if (var =3D=3D 1) printf("block 1 ");
else if (var =3D=3D 2) printf("block 2 ");
}
printf("\n");
}
return 0;
}
Alex
|
|
0
|
|
|
|
Reply
|
Alexei
|
4/25/2010 6:07:55 PM
|
|
Alexei A. Frounze wrote:
> On Apr 25, 6:56 am, Patricia Shanahan <p...@acm.org> wrote:
>> Alexei A. Frounze wrote:
>>
>> ...> Surprisingly, my code is pretty clean with gotos, which, btw, I use
>>> just for almost exclusively 2 things:
>>> - breaking out of nested loops (not always, if I can do that w/o
>>> writing more than two lines of code, I don't use goto)
>>> - jumping to the common cleanup code at the end of the function when I
>>> detect some error
>> ...
>>
>> When I was first considering using Java for a project, I was a little
>> worried about the lack of goto.
>>
>> I knew I had written a couple of gotos in C and maintained code
>> containing goto that would have had to be much more convoluted without
>> it. When I analyzed those uses of goto, I realized they were all in
>> those two categories, mainly the common cleanup code case.
>>
>> That meant I would not need goto in a language with try-finally and
>> named loop break.
>>
>> Patricia
>
> Of course, you could do that. And even if it was plain C but with
> removed goto, you'd still be able to do your work.
That depends on the definition of "do your work". C with goto removed
would remain Turing-complete. The issue is one of clarity and simplicity
of the code.
Patricia
|
|
0
|
|
|
|
Reply
|
Patricia
|
4/25/2010 6:11:43 PM
|
|
"Alexei A. Frounze" <alexfrunews@gmail.com> writes:
> On Apr 25, 8:52 am, Nick <3-nos...@temporary-address.org.uk> wrote:
>>
>> Just today I found myself in such a situation where I had two such
>> blocks which, depending on a couple of conditions, I wanted to execute
>> one, the other, or both in both orders - right in the middle of a large
>> function. So putting the code in functions several pages away from
>> where they were needed wasn't nice, and short of jumping around (either
>> with a loop even though there is only a single pass, or with goto) the
>> only other solution is to replicate the code.
>
> I don't know if this would work or not for your specific case, but if
> blocks are sufficiently large and it's exactly one or both in either
> order in the same place, then you could theoretically do something
> like this:
>
> #include <stdio.h>
> int main(void)
> {
> const int ss[4][2] =
> {
> { 1, 1 },
> { 2, 2 },
> { 1, 2 },
> { 2, 1 }
> };
> int i, cnt, start, stop, var;
>
> for (i = 0; i < 4; i++)
> {
> start = ss[i][0];
> stop = ss[i][1];
>
> for (var = start, cnt = 1 + (start != stop);
> cnt--;
> var += (stop >= start) ? 1 : -1)
> {
> if (var == 1) printf("block 1 ");
> else if (var == 2) printf("block 2 ");
> }
> printf("\n");
> }
>
> return 0;
> }
That's the sort of thing (the var loop) that I meant by playing around
with loops. That is just so much more confusing than:
/* framework that sets do_first, do_second and first_is_first from array */
if(do_first && first_is_first)
printf("block 1\n");
if(do_second)
printf("block 2\n");
if(do_first && !first_is_first)
printf("block 1\n");
Which is exactly the problem - this one is clear, but gets messy if
"block 1" is a few lines but not obviously a function. Yours avoids
that, but is far from clear at first sight why it's looping.
If I was going for a loop, I'd be far more likely to set those three
variables, as for the above code and then create another flag and do:
do_first_this_time = do_first && first_is_first;
for(;;) {
if(do_first_at_all)
printf("Block 1\n");
if(do_second) {
printf("Block 2\n");
do_second = false;
}
if(do_first && !first_is_first) {
do_first_this_time = true;
continue;
} else
break;
}
Yes, pretty hideous. I still prefer it to yours though!
--
Online waterways route planner | http://canalplan.eu
Plan trips, see photos, check facilities | http://canalplan.org.uk
|
|
0
|
|
|
|
Reply
|
Nick
|
4/25/2010 6:21:58 PM
|
|
On 2010-04-25, Bo Persson <bop@gmb.dk> wrote:
> I guess James means that in the "properly designed" code, the state
> you operate on is already part of the class' state.
If it's only useful in one function, that seems questionable.
> Adding another
> member function doesn't affect the code efficiency. At least not more
> that the presence of a goto and label might disturb the efficiency of
> the compiler optimizer.
But adding more member objects might well affect code and storage
efficiency, quite a bit. That becomes a cost you pay all the time, even
when you're not using it; at least the cost of the goto is necessarily
restricted to a single function.
-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
|
|
0
|
|
|
|
Reply
|
Seebs
|
4/25/2010 6:33:30 PM
|
|
On Apr 25, 11:21=A0am, Nick <3-nos...@temporary-address.org.uk> wrote:
> "Alexei A. Frounze" <alexfrun...@gmail.com> writes:
>
>
>
> > On Apr 25, 8:52=A0am, Nick <3-nos...@temporary-address.org.uk> wrote:
>
> >> Just today I found myself in such a situation where I had two such
> >> blocks which, depending on a couple of conditions, I wanted to execute
> >> one, the other, or both in both orders - right in the middle of a larg=
e
> >> function. =A0So putting the code in functions several pages away from
> >> where they were needed wasn't nice, and short of jumping around (eithe=
r
> >> with a loop even though there is only a single pass, or with goto) the
> >> only other solution is to replicate the code.
>
> > I don't know if this would work or not for your specific case, but if
> > blocks are sufficiently large and it's exactly one or both in either
> > order in the same place, then you could theoretically do something
> > like this:
>
> > #include <stdio.h>
> > int main(void)
> > {
> > =A0 const int ss[4][2] =3D
> > =A0 {
> > =A0 =A0 { 1, 1 },
> > =A0 =A0 { 2, 2 },
> > =A0 =A0 { 1, 2 },
> > =A0 =A0 { 2, 1 }
> > =A0 };
> > =A0 int i, cnt, start, stop, var;
>
> > =A0 for (i =3D 0; i < 4; i++)
> > =A0 {
> > =A0 =A0 start =3D ss[i][0];
> > =A0 =A0 stop =3D ss[i][1];
>
> > =A0 =A0 for (var =3D start, cnt =3D 1 + (start !=3D stop);
> > =A0 =A0 =A0 =A0 =A0cnt--;
> > =A0 =A0 =A0 =A0 =A0var +=3D (stop >=3D start) ? 1 : -1)
> > =A0 =A0 {
> > =A0 =A0 =A0 if (var =3D=3D 1) printf("block 1 ");
> > =A0 =A0 =A0 else if (var =3D=3D 2) printf("block 2 ");
> > =A0 =A0 }
> > =A0 =A0 printf("\n");
> > =A0 }
>
> > =A0 return 0;
> > }
>
> That's the sort of thing (the var loop) that I meant by playing around
> with loops. =A0That is just so much more confusing than:
>
> /* framework that sets do_first, do_second and first_is_first from array =
*/
> if(do_first && first_is_first)
> =A0 =A0 =A0 =A0 =A0 =A0 printf("block 1\n");
> if(do_second)
> =A0 =A0 =A0 =A0 =A0 =A0 printf("block 2\n");
> if(do_first && !first_is_first)
> =A0 =A0 =A0 =A0 =A0 =A0 printf("block 1\n");
>
> Which is exactly the problem - this one is clear, but gets messy if
> "block 1" is a few lines but not obviously a function. =A0Yours avoids
> that, but is far from clear at first sight why it's looping.
>
> If I was going for a loop, I'd be far more likely to set those three
> variables, as for the above code and then create another flag and do:
>
> do_first_this_time =3D do_first && first_is_first;
> for(;;) {
> =A0 =A0 =A0 =A0 if(do_first_at_all)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 printf("Block 1\n");
> =A0 =A0 =A0 =A0 if(do_second) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 printf("Block 2\n");
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 do_second =3D false;
> =A0 =A0 =A0 =A0 }
> =A0 =A0 =A0 =A0 if(do_first && !first_is_first) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 do_first_this_time =3D true;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 continue;
> =A0 =A0 =A0 =A0 } else
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 break;
>
> }
>
> Yes, pretty hideous. =A0I still prefer it to yours though!
> --
> Online waterways route planner =A0 =A0 =A0 =A0 =A0 =A0|http://canalplan.e=
u
> Plan trips, see photos, check facilities =A0|http://canalplan.org.uk
:)
Actually, there was some left-over from the previous attempt, so this
one is a tad more simple:
....
for (var =3D start, cnt =3D 1 + (start !=3D stop);
cnt--;
var +=3D stop - start)
{
if (var =3D=3D 1) printf("block 1 ");
else if (var =3D=3D 2) printf("block 2 ");
}
....
Alex
|
|
0
|
|
|
|
Reply
|
Alexei
|
4/25/2010 6:50:03 PM
|
|
Everyone knows goto is evil. Modern languages like Java have been
able to completely eliminate goto! Instead they use much superior
language tools such as labeled breaks:
http://java.sun.com/docs/books/tutorial/java/nutsandbolts/branch.html
Fortunately C/C++ is powerful enough that it can very closely emulate
this far superior Java language feature. Here is the code snippet
from the java tutorial demonstrating labeled breaks translated to C++,
using a new and improved "labeled_break" statement:
#define RCONCAT(x,y) y##x
#define labeled_break(x) RCONCAT(to, go) x
....
search:
for (i = 0; i < arrayOfInts.length; i++) {
for (j = 0; j < arrayOfInts[i].length; j++) {
if (arrayOfInts[i][j] == searchfor) {
foundIt = true;
labeled_break( search );
}
}
}
One should always use this labeled_break facility instead of the
extremely evil and error prone goto!
-Howard
;-)
|
|
0
|
|
|
|
Reply
|
Howard
|
4/25/2010 8:44:17 PM
|
|
On Apr 25, 10:03=A0pm, "Daniel T." <danie...@earthlink.net> wrote:
> James Dow Allen <jdallen2...@yahoo.com> wrote:
>> > understood: Edsger W. Dijkstra wrote:
> > > The unbridled use of the go to statement has an immediate
> > > consequence that it becomes terribly hard to find a meaningful set
> > > of coordinates in which to describe the process progress.
> .
> > (Hmmm. =A0Dijkstra *does* write "UNBRIDLED use of goto". =A0Funny how t=
hat
> > disappears from the pedants' sound-bite summaries.)
> .
> Agreed, and many also fail to notice that it is rather hard to use goto
> in an "unbridled" fashion in C and C++.
Did you mean "bridled"? ... Since you were arguing against goto.
> .
> > One of my own goto's appears horrendous...
> >http://fabpedigree.com/james/dbldum.htm
> .
> It looks as though you have implemented a depth first search.
Yes. Or rather backtracking, which is DFS with a smidgen
of extra control logic. The problem specifics mean there's
3 or 4 "smidgens" of extra control logic here. And in my
comments I admit that there are better ways to deal with *simpler*
backtracking problems, and better ways to deal with *harder*
backtracking applications.
> ... I fully agree that your code is better than the psudo-code you
> present in comparison ...
Well, thanks for that! The side-by-side comparison clearly shows
that I use 1 goto and 1 for-loop to avoid 2 break's, 4 if's,
2 else's and 2 other minor defects. I'm not arguing that goto's
aren't bad, just that other things (break's, too many variables,
etc.) are also bad and one seeks compromise.
> there are better ways of implementing depth first searches
> than either of the two you present.
If you submit working code that runs slower than mine by no more
than 20%, I will show it at the website as "Daniel's structured
improvement." (Speed *is* important of course for the target
application.)
James
|
|
0
|
|
|
|
Reply
|
James
|
4/26/2010 4:31:37 AM
|
|
"wolfgang kern" <nowhere@never.at> ha scritto nel messaggio
news:hr1a9j$4qf$1@newsreader2.utanet.at...
>
> "io_x" wrote:
>> [Xpost to: alt.comp.programming, alt.lang.asm,
>> comp.lang.c, comp.lang.c++, comp.programming]
>
>> the people that speak not good about "goto"
>> are uttled wrong; their code bug full etc
>
>> more distant is your code from goto
>> more your code is bug full and incompresible
>
>> the "goto" is the key word for programming;
>> all the remain, other than goto or jmp or jc or jz,
>> and the easy cpu layout
>> is the wrong way for programming
>
> Except that GOTO is a HLL keyword and I'm Asmist and
> more machine-code oriented than concerned about needs
> within abstract structured HLL-compilers, I see nothing
> wrong with GOTO as long it does what a programmer want.
you see all jmp, je, jc etc etc for me they are all gotos
> I once checked PowerBasic's GOTO and found it always
> compiled a long (16:16) jump, even rare required.
> But its syntax checker cried aloud if you tried to
> jump out of a [FOR/IF/...]-struct with GOTO.
i used when i were 12-13, Basic too the Basic for vic-20
i think it was not the way for programming well
> I don't know C/C+-, but what I see by disassembling their
> resulting output seem to end up in heavy bloated code,
> perhaps from using BREAK and GOTO within nested blocks,
> which the compiler may grant with copying all required
> code-trails (stack recover/cleanup) to every added path.
> So in this aspect GOTO may be really not the best choice.
if you see the asm, without the .c or .cpp line of the traslation
could be difficult to understand
> see me happy for I don't need to care this in my world :)
it is not possible that i wrote some functions easily
than in C or in C++, with not big time,
without the "gotos==very good"
> __
> wolfgang (ALA)
|
|
0
|
|
|
|
Reply
|
io_x
|
4/26/2010 6:46:40 AM
|
|
Richard wrote:
[snip]
> There is nothing whatsoever wrong with a break statement - it frequently
> helps against overly convoluted loop conditions.
Nicely put. If I will ever be tempted enough to actually start a
"poesiealbum" for little pieces of wisdom, this little gem would be
among the ten first entries (why, it would probably the first).
Just to add my 2 cents:
Your statement says that break-statements (I really like the term
"goto in disguise", thank you, James) can keep the loop condition
short and sweet. I think that this is probably not the most convincing
argument for the usage of break-statements, but the readability of
code should not be underestimated. That's why I'd suggest that also
the use of continue-statements can increase the readability a lot. If
you have a look at the following piece of code (from actual production
environment):
// Iterate through all interfaces from the type library.
UINT uiNumberOfTypes = spTypeLib->GetTypeInfoCount ();
for (int i = 0; i < uiNumberOfTypes; i++)
{
ITypeInfoPtr spCurrTypeInfo;
spTypeLib->GetTypeInfo (i, &spCurrTypeInfo);
if (!(bool) spCurrTypeInfo)
return false;
// We only want to process interface definitions, so if we encounter
anything
// else (for example enums), we skip the rest of the loop.
TYPEATTR* pCurrentTypeAttr;
VERIFY (SUCCEEDED (spCurrTypeInfo->GetTypeAttr
(&pCurrentTypeAttr)));
if (pCurrentTypeAttr->typekind != TKIND_DISPATCH &&
pCurrentTypeAttr->typekind != TKIND_INTERFACE)
continue;
: // here comes a quite lengthy loop rest of the loop body (about
130 lines)
}
The same code without a continue-statement would add an if-statement,
which would indent the quite lengthy loop body one more time. Most
people would probably ask "So what?" In my opinion too much indented
code is almost as unreadable as a goto-ridden spaghetti code. When you
have a quite lengthy loop/if body, it's quite easy to forget under
which which conditions the code will actually run (which is why many
people repeat the condition of an if-statement as comment in the else-
part). Keeping this information as small as possible (in above case
the user has only to remember: "we are iterating through the type
library" instead of "we are iterating through all elements of the type
library that are actually interfaces") is, in my eyes, one of the
keypoints of writing readable code: it kind of better matches the
"information flow" of the human brain (I'm probably sticking my neck
out with this thesis, it'd be really interesting to find out whether
this can be backed up scientifically).
As you can see, I couldn't put it as short as you could.
Regards,
Stuart
|
|
0
|
|
|
|
Reply
|
Stuart
|
4/26/2010 7:03:54 AM
|
|
* Howard Hinnant:
> Everyone knows goto is evil. Modern languages like Java have been
> able to completely eliminate goto! Instead they use much superior
> language tools such as labeled breaks:
>
> http://java.sun.com/docs/books/tutorial/java/nutsandbolts/branch.html
>
> Fortunately C/C++ is powerful enough that it can very closely emulate
> this far superior Java language feature. Here is the code snippet
> from the java tutorial demonstrating labeled breaks translated to C++,
> using a new and improved "labeled_break" statement:
>
> #define RCONCAT(x,y) y##x
> #define labeled_break(x) RCONCAT(to, go) x
>
> ...
>
> search:
> for (i = 0; i < arrayOfInts.length; i++) {
> for (j = 0; j < arrayOfInts[i].length; j++) {
> if (arrayOfInts[i][j] == searchfor) {
> foundIt = true;
> labeled_break( search );
> }
> }
> }
>
> One should always use this labeled_break facility instead of the
> extremely evil and error prone goto!
Oh dear. I've been trying, really trying, to mark this thread "read" every time
I let my Thunderbird out to flap her wings. But, anyway, I'm afraid the
labeled_break implementation above is a bit too /roundabout/ for my liking, sort
of, my head spins in a loop just thinking about it.
Here's my more direct take on it.
It's not perfect, but hey!
<code>
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <stdexcept>
#include <stddef.h>
#include <assert.h>
typedef ptrdiff_t Size;
typedef Size Index;
typedef std::string String;
template< typename T >
class Array
{
private:
std::vector< T > myItems;
Size getLength() const { return myItems.size(); }
struct LengthProperty
{
Array* a;
LengthProperty( Array& arr ): a( &arr ) {}
operator Size() const { return a->getLength(); }
};
public:
LengthProperty length;
Array(): length( *this ) {}
T& operator[]( Index i ) { return myItems.at( i ); }
T const& operator[]( Index i ) const { return myItems.at( i ); }
Array& operator<<( T const& v )
{
myItems.push_back( v );
return *this;
}
};
struct Success {};
struct Failure {};
bool fail() { throw Failure(); }
namespace sys { namespace out {
void println( String const& s )
{
std::cout << s << std::endl;
}
} } // namespace sys::out
class S
{
private:
std::ostringstream stream;
public:
template< typename T >
S& operator<<( T const& v )
{
stream << v;
return *this;
}
operator String() const { return stream.str(); }
};
int main()
{
typedef Array< int > IntArray;
typedef Array< IntArray > IntMatrix;
IntMatrix const arrayOfInts = IntMatrix()
<< ( IntArray() << 32 << 87 << 3 << 589 )
<< ( IntArray() << 12 << 1076 << 2000 << 8 )
<< ( IntArray() << 622 << 127 << 77 << 955 );
int const searchFor = 12;
int i;
int j;
try
{
for( i = 0; i < arrayOfInts.length || fail(); ++i )
{
for( j = 0; j < arrayOfInts[i].length; ++j )
{
if( arrayOfInts[i][j] == searchFor )
{
throw Success();
}
}
}
assert( false );
}
catch( Success )
{
sys::out::println(
S() << "Found " << searchFor << " at " << i << ", " << j
);
}
catch( Failure )
{
sys::out::println( S() << searchFor << " not in the array" );
}
}
</code>
I think, one should always use this very clear Success/Failure combo instead of
the extremely evil and error prone "goto" or boolean variable! ;-)
Cheers,
- Alf
PS: Do you think the comma operator could help?
|
|
0
|
|
|
|
Reply
|
Alf
|
4/26/2010 8:10:58 AM
|
|
"Alexei A. Frounze" <alexfrunews@gmail.com> wrote in message
news:59eed8de-fa97-42f9-8550-8154ac69a167@h16g2000prf.googlegroups.com...
>
> If you restrict the use of goto in C/C++ to several simple patterns
> and write your code carefully, goto's aren't really a problem.
>
But, are goto's of any advantage in C over other solutions? With
optimization and good code structuring, is there any place that a goto is
the best choice?
"break" and "continue" function like goto's - without needing goto labels...
If "break" is used with "while(0)" code block, it is functionally the same
as using a forward goto. "continue" can be used for a backward goto...
IMO, this means simple usage of goto is no better than using structured C
control flow. That leaves more complicated situations where goto might have
some advantage.
The most common arguments for their use is 1) to break out of multiple, say
three or more, nested loops or 2) error recovery. Status flags,
fall-through, using a switch, restructuring the code blocks, reducing the
number of loops, can all be used to fix such problems. Is there some
situation that really advantages a goto?...
C has a robust flow control syntax. About the only thing that can't be done
readily is to detect if a while() loop was executed. The need for this is
exceptionally rare, IMO. You could use status flags, at the expense of
another variable... But, it's handled easily by adding an if() around the
while() with the same set of conditions:
A)
while(conditions)
{
/* loop stuff */
}
/* did loop execute or not? */
B)
if(identical_conditions_as_while)
{
while(conditions)
{
/* loop stuff */
}
/* if here, loop executed because */
/* conditions of if() while() are the same*/
}
> ... several simple patterns ...
Like?
Rod Pemberton
|
|
0
|
|
|
|
Reply
|
do_not_have6088 (68)
|
4/26/2010 9:06:26 AM
|
|
Rod Pemberton wrote:
> But, are goto's of any advantage in C over other solutions? With
> optimization and good code structuring, is there any place that a goto is
> the best choice?
Yes, finite state machines. You can do those by putting a switch() on a loop but in the end
that is nothing more than a crude hack used to desperately (and irrationally) avoid using
goto.
Rui Maciel
|
|
0
|
|
|
|
Reply
|
rui.maciel (1761)
|
4/26/2010 10:43:40 AM
|
|
In alt.lang.asm Rod Pemberton <do_not_have@havenone.cmm> wrote in part:
> But, are goto's of any advantage in C over other solutions?
> With optimization and good code structuring, is there any
> place that a goto is the best choice?
>
> "break" and "continue" function like goto's - without needing
> goto labels... If "break" is used with "while(0)" code
> block, it is functionally the same as using a forward goto.
> "continue" can be used for a backward goto...
>
> IMO, this means simple usage of goto is no better than using
> structured C control flow. That leaves more complicated
> situations where goto might have some advantage.
Precisely! In small [teaching] examples, GOTO looks obviously
messy, confusing, "jumpy" and what have you. IOW, harmful [Dijkstra]
But structure _does_not_ scale! One if..then..else or case()
looks great. But when you have them 9 deep they are marching off
the page (formatting is a big part of the additional clarity)
and [worse], a bug in the substructures has the potential to
mess up the overall control flow. Misnesting.
GOTO _is_ messy. But it scales -- just lookup the target in
the symbol table. You do _not_ need to parse or worry about
any intervening code.
As a concrete example of the unsung benefits of GOTO, please
consider a text editor with letter commands. In C you'd do
this as a case() or switch() statement. It will be huge since
each of the commands may be quite involved. A structural bug
in (a) could affect (b). The compile may catch some of these,
but cannot when they are "paired", even far apart. A compiler
should not be used as a debugging tool.
In ASM (or C if it'll do this), you'd implement via a jmp table
(`jmp [ebx]`) and terminate each of the letter functions with
`jmp keyloop`. Or the equivalent call [ebx]/ret. More or
less how the C compiler will code it anyways.
obTroll: In many ways, GOTO is reminiscent of the slightly
more recent calculator debate between fans of TI algebraic
notation and HP reverse polish notation.
-- Robert
|
|
0
|
|
|
|
Reply
|
redelm (106)
|
4/26/2010 1:02:57 PM
|
|
On 26 Apr., 10:10, "Alf P. Steinbach" wrote:
>
> Here's my more direct take on it.
> It's not perfect, but hey!
>
> [...]
>
> int main()
> {
> =A0 =A0 =A0typedef Array< int > =A0 =A0 =A0 =A0IntArray;
> =A0 =A0 =A0typedef Array< IntArray > =A0 IntMatrix;
>
> [...]
>
> =A0 =A0 =A0int const searchFor =3D 12;
> =A0 =A0 =A0int =A0 =A0 i;
> =A0 =A0 =A0int =A0 =A0 j;
>
> =A0 =A0 =A0try
> =A0 =A0 =A0{
> =A0 =A0 =A0 =A0 =A0for( i =3D 0; =A0i < arrayOfInts.length || fail(); =A0=
++i )
> =A0 =A0 =A0 =A0 =A0{
> =A0 =A0 =A0 =A0 =A0 =A0 =A0for( j =3D 0; =A0j < arrayOfInts[i].length; =
=A0++j )
> =A0 =A0 =A0 =A0 =A0 =A0 =A0{
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if( arrayOfInts[i][j] =3D=3D searchFor=
)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0{
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0throw Success();
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> =A0 =A0 =A0 =A0 =A0}
> =A0 =A0 =A0 =A0 =A0assert( false );
> =A0 =A0 =A0}
> =A0 =A0 =A0catch( Success )
> =A0 =A0 =A0{
> =A0 =A0 =A0 =A0 =A0sys::out::println(
> =A0 =A0 =A0 =A0 =A0 =A0 =A0S() << "Found " << searchFor << " at " << i <<=
", " << j
> =A0 =A0 =A0 =A0 =A0 =A0 =A0);
> =A0 =A0 =A0}
> =A0 =A0 =A0catch( Failure )
> =A0 =A0 =A0{
> =A0 =A0 =A0 =A0 =A0sys::out::println( S() << searchFor << " not in the ar=
ray" );
> =A0 =A0 =A0}
> }
>
> I think, one should always use this very clear Success/Failure combo inst=
ead of
> the extremely evil and error prone "goto" or boolean variable! ;-)
I realize that this was intended to be a joke. But let me comment on
it anyways. I see no reason for a goto here. Just wrap your "find
algorithm" inside its own function and use a return statement instead
of "throw Success()".
return is another "goto in disguise" but I'm fine with it. I even used
goto in one of my C programs, so, I'm not totally opposed to it. But
if I can manage to avoid it without hurting readability, I'll just do
that. I don't think I ever used goto in a C++ program. At least I
can't remember. This is probably due to the possibility of "RAII".
Cheers,
SG
|
|
0
|
|
|
|
Reply
|
SG
|
4/26/2010 3:21:55 PM
|
|
On 4/24/2010 8:20 AM, Rui Maciel wrote:
> io_x wrote:
>
[... "goto bad" ...]
>
> I see there is a small misconception in this issue. The only nasty thing that is usually
> said about goto is that it's use may end up generating code which isn't easy to read, to
> interpret and to follow.
[...]
I often use "goto" to make it easier to implement "only one return" in some
more complex functions, especially those that require some cleanup before
returning.
--
Kenneth Brody
|
|
0
|
|
|
|
Reply
|
Kenneth
|
4/26/2010 3:29:08 PM
|
|
On Apr 26, 2:06=A0am, "Rod Pemberton" <do_not_h...@havenone.cmm> wrote:
> "Alexei A. Frounze" <alexfrun...@gmail.com> wrote in messagenews:59eed8de=
-fa97-42f9-8550-8154ac69a167@h16g2000prf.googlegroups.com...
>
>
>
> > If you restrict the use of goto in C/C++ to several simple patterns
> > and write your code carefully, goto's aren't really a problem.
>
> But, are goto's of any advantage in C over other solutions? =A0With
> optimization and good code structuring, is there any place that a goto is
> the best choice?
>
> "break" and "continue" function like goto's - without needing goto labels=
....
> If "break" is used with "while(0)" code block, it is functionally the sam=
e
> as using a forward goto. =A0"continue" can be used for a backward goto...
while(0 /*shouldn't it actually be 1 because with 0 it won't execute
even once*/) looks like a legitimate loop at first until you have
found that all the breaks out of it. What's worse it introduces an
extra nesting level, so, if there's another loop inside, breaking out
the inner one won't be as simple as still doing goto -- you'll still
have to implement some variables or whatnot in order to do what a
single goto would.
> IMO, this means simple usage of goto is no better than using structured C
> control flow. =A0That leaves more complicated situations where goto might=
have
> some advantage.
>
> The most common arguments for their use is 1) to break out of multiple, s=
ay
> three or more, nested loops or 2) error recovery. =A0Status flags,
> fall-through, using a switch, restructuring the code blocks, reducing the
> number of loops, can all be used to fix such problems. =A0 Is there some
> situation that really advantages a goto?...
I'm using goto almost exclusively for the above two scenarios. For
everything else its ifs and switches (and ?: at times).
> C has a robust flow control syntax. =A0About the only thing that can't be=
done
> readily is to detect if a while() loop was executed. =A0The need for this=
is
> exceptionally rare, IMO. =A0You could use status flags, at the expense of
> another variable... =A0But, it's handled easily by adding an if() around =
the
> while() with the same set of conditions:
Yeah. But if you're linearly searching for something, then you begin
with an invalid index or NULL pointer and after the loop you just
examine it and see whether it has become valid or not and you don't
always need an extra variable.
Alex
|
|
0
|
|
|
|
Reply
|
alexfrunews (33)
|
4/26/2010 5:17:57 PM
|
|
"Ali Karaali" <alicpp@gmail.com> wrote in message
news:dda9d933-e9c1-418f-b62a-bc30bd1dd16c@r27g2000yqn.googlegroups.com...
|I use goto to break nested for loops and I can't see a
| reason to ban goto.
Many languages provide a means of leaving loops
prematurely, and without the need to use GO TO.
PL/I, for instance, provides the LEAVE statement.
To skip the remainder of the statements in a loop
and to begin another iteration of the loop,
PL/I provides an ITERATE statement.
In both cases, you don't need to go looking for the
label where a GOTO might transfer control.
|
|
0
|
|
|
|
Reply
|
robin
|
4/27/2010 12:30:11 AM
|
|
"Alexei A. Frounze" <alexfrunews@gmail.com> wrote in message
news:aab23e01-b4d4-44c4-a136-a619da00a3f7@m24g2000prc.googlegroups.com...
>I wish there were distinct breaks for loops and switches as well as
>multi-level breaks for nested loops. goto's at times are the least
>evil since they don't require you to implement extra variables to
>break out of nested loops
But they do require the introduction of additional labels.
As well, you have to go looking for the place where the GOTO
transfers.
Using a structured method (such as LEAVE in PL/I)
makes it obvious that the end of a particular loop is
where control resumes.
> and they help to simplify function cleanup
>code (where resources are being freed on various conditions).
|
|
0
|
|
|
|
Reply
|
robin
|
4/27/2010 12:39:13 AM
|
|
On Mon, 26 Apr 2010 15:02:57 +0200, Robert Redelmeier
<redelm@ev1.net.invalid> wrote:
[editor with key processing]
> In ASM (or C if it'll do this), you'd implement via a jmp table
> (`jmp [ebx]`) and terminate each of the letter functions with
> `jmp keyloop`. Or the equivalent call [ebx]/ret. More or
> less how the C compiler will code it anyways.
Pshurely 'call [ebx]' and end each section with 'ret', no goto required?
> obTroll: In many ways, GOTO is reminiscent of the slightly
> more recent calculator debate between fans of TI algebraic
> notation and HP reverse polish notation.
Damn, missed that!
betterTroll: what about Comefrom?
>
> -- Robert
>
Needs a CRLF in there?
--
Nuns! Nuns! Reverse
|
|
0
|
|
|
|
Reply
|
Esra
|
4/27/2010 6:33:47 AM
|
|
"Alexei A. Frounze" <alexfrunews@gmail.com> wrote in message
news:3175dd42-6ff2-452b-af2e-93de277ec661@t14g2000prm.googlegroups.com...
On Apr 26, 2:06 am, "Rod Pemberton" <do_not_h...@havenone.cmm> wrote:
>
> while(0 /*shouldn't it actually be 1 because with 0 it
> won't execute even once*/)
>
Eee... Good catch! Sorry, that doesn't work.
But, no, definately not "while(1)"... That'd would be a loop. How about
"do {} while(0)"... With a "break" or "continue", we should have a forward
or backward goto. If the "break" or "continue" is not executed, the entire
section only executes once, as if the "do {} while(0)" was not there.
Hopefully, that's correct this time?
:-)
Rod Pemberton
|
|
0
|
|
|
|
Reply
|
do_not_have6088 (68)
|
4/27/2010 6:38:45 AM
|
|
On Apr 26, 11:38=A0pm, "Rod Pemberton" <do_not_h...@havenone.cmm> wrote:
> "Alexei A. Frounze" <alexfrun...@gmail.com> wrote in messagenews:3175dd42=
-6ff2-452b-af2e-93de277ec661@t14g2000prm.googlegroups.com...
> On Apr 26, 2:06 am, "Rod Pemberton" <do_not_h...@havenone.cmm> wrote:
>
>
>
> > while(0 /*shouldn't it actually be 1 because with 0 it
> > won't execute even once*/)
>
> Eee... =A0Good catch! =A0Sorry, that doesn't work.
>
> But, no, definately not "while(1)"... =A0That'd would be a loop. =A0How a=
bout
> "do {} while(0)"... =A0With a "break" or "continue", we should have a for=
ward
> or backward goto. =A0If the "break" or "continue" is not executed, the en=
tire
> section only executes once, as if the "do {} while(0)" was not there.
> Hopefully, that's correct this time?
>
> :-)
>
> Rod Pemberton
That (do {} while(0)) is a possibility and it is sometimes used for
other purposes. Also, you could just put a break at the end of
while(1)/for(;;)'s block.
Alex
|
|
0
|
|
|
|
Reply
|
alexfrunews (33)
|
4/27/2010 8:43:35 AM
|
|
"robin" <robin51@dodo.com.au> wrote in message
news:4bd63021$0$23073$c30e37c6@exi-reader.telstra.net...
> "Ali Karaali" <alicpp@gmail.com> wrote in message
> news:dda9d933-e9c1-418f-b62a-bc30bd1dd16c@r27g2000yqn.googlegroups.com...
> |I use goto to break nested for loops and I can't see a
> | reason to ban goto.
>
> Many languages provide a means of leaving loops
> prematurely, and without the need to use GO TO.
> PL/I, for instance, provides the LEAVE statement.
>
> To skip the remainder of the statements in a loop
> and to begin another iteration of the loop,
> PL/I provides an ITERATE statement.
>
> In both cases, you don't need to go looking for the
> label where a GOTO might transfer control.
I use a language which uses 4 control statements to exit or reiterate
a loop:
restart Re-start the whole loop
redo Repeat this iteration
next Next iteration
exit Exit (Break) completely (by-passing any else-part)
(Some loops can have a else-part which is executed on normal exit of
the loop, but is skipped when exit is used.)
These all work with nested loops, and are in addition to return,
stop, and goto. Of course if all seven controls appeared within each
level of multiply-nested loops, it would look chaotic. The idea is
that these controls are used sensibly and sparingly.
Goto itself I mostly use in switch/case statements, where code is
shared. For example, if cases X,Y,Z first do A,B,C respectively, but
then they all do D. Or they all do P, but then do Q,R,S respectively.
I'm still working on a tidy way of representing this without goto,
and without putting the common code in a function (which is often
inappropriate, troublesome, inefficient and less readable).
--
Bartc
|
|
0
|
|
|
|
Reply
|
bartc
|
4/27/2010 10:04:13 AM
|
|
James Dow Allen <jdallen2000@yahoo.com> wrote:
> PS: Your newswriter seems to have clipped the link, Daniel, which
> I then had to hand-enter. I think Google Groups would have gotten
> it right, so you may want to switch to that: :-)
> > http://www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_=
> Harmful.html
Except, of course, that it doesn't. Quoted-illegible: Just Say No.
Richard
|
|
0
|
|
|
|
Reply
|
raltbos
|
4/27/2010 11:16:50 AM
|
|
James Kanze <james.kanze@gmail.com> wrote:
> In other words, if goto makes the code simpler, it means that
> you haven't found the correct expression of the algorithm.
>
> And of course, the problem isn't with goto, per se. It's with
> the way it is used.
Those two statements are in contradiction.
And that says all you need to know about the argument that "goto is
eeeevviiiillll!!!!!"
Sheesh, next thing someone'll want to ban it "for the sake of our
chiiillldruuuunnn!!!!"
Richard
|
|
0
|
|
|
|
Reply
|
raltbos
|
4/27/2010 2:07:38 PM
|
|
"Daniel T." <daniel_t@earthlink.net> wrote:
[ Quoting Dijkstra's "Goto considered harmful": ]
> The unbridled use of the go to statement
This is the one thing which Dijkstra's editor (who wrote that headline),
the War-On-Goto lobby, and even Dijkstra himself in later years, seem to
have missed.
_Unbridled_.
The unbridled use of salt is also deadly to humans. We must ban it
outright.
Richard (takes a little salt, not a lot)
|
|
0
|
|
|
|
Reply
|
raltbos
|
4/27/2010 2:07:41 PM
|
|
On Apr 27, 10:07=A0am, ralt...@xs4all.nl (Richard Bos) wrote:
> "Daniel T." <danie...@earthlink.net> wrote:
>
> [ Quoting Dijkstra's "Goto considered harmful": ]
>
> > =A0 =A0The unbridled use of the go to statement
>
> This is the one thing which Dijkstra's editor (who wrote that headline),
> the War-On-Goto lobby, and even Dijkstra himself in later years, seem to
> have missed.
>
> _Unbridled_.
>
> The unbridled use of salt is also deadly to humans. We must ban it
> outright.
>
> Richard (takes a little salt, not a lot)
Indeed. Unbridled water drinking can be fatal:
http://en.wikipedia.org/wiki/Water_intoxication
Pure water is dangerous and highly concentrated being 55 molar. Water
kills more than a million people per year, half of them children! How
can anyone stand for the unbridled use of water.
KHD
|
|
0
|
|
|
|
Reply
|
Keith
|
4/27/2010 2:25:51 PM
|
|
In comp.lang.c++ Alexei A. Frounze <alexfrunews@gmail.com> wrote:
> Now, let's consider C (or C++ where this function has to explicitly
> free up some used resources or do some other cleanup). The objects
> won't get freed here automatically by the magic of the destructor call
> generated for you by the C++ compiler.
Make a wild guess what is one of the reasons I don't like C.
|
|
0
|
|
|
|
Reply
|
Juha
|
4/27/2010 6:34:08 PM
|
|
In comp.lang.c++ spinoza1111 <spinoza1111@yahoo.com> wrote:
> On Apr 25, 1:09�pm, Juha Nieminen <nos...@thanks.invalid> wrote:
>> In comp.lang.c++ Ali Karaali <ali...@gmail.com> wrote:
>>
>> > I use goto to break nested for loops and I can't see a
>> > reason to ban goto.
>>
>> � No. The correct keyword for breaking out of nested loops (in C++) is
>> 'return'. If you are using 'goto' for that purpose, you are doing it
>> wrong.
>
> Don't you mean "break"?
Exactly how do you exit out of a set of nested loops with a "break"?
|
|
0
|
|
|
|
Reply
|
Juha
|
4/27/2010 6:35:17 PM
|
|
In comp.lang.c++ Phil Carmody <thefatphil_demunged@yahoo.co.uk> wrote:
> This is a purely religious point of view.
>
> One should never flaunt ones lack of experience in order to back up
> ones argument.
I prefer "a purely religious point of view" over insulting a person
you don't know anything about.
|
|
0
|
|
|
|
Reply
|
Juha
|
4/27/2010 6:37:19 PM
|
|
Juha Nieminen wrote:
> In comp.lang.c++ spinoza1111 <spinoza1111@yahoo.com> wrote:
>> On Apr 25, 1:09 pm, Juha Nieminen <nos...@thanks.invalid> wrote:
>>> In comp.lang.c++ Ali Karaali <ali...@gmail.com> wrote:
>>>
>>>> I use goto to break nested for loops and I can't see a
>>>> reason to ban goto.
>>> No. The correct keyword for breaking out of nested loops (in C++) is
>>> 'return'. If you are using 'goto' for that purpose, you are doing it
>>> wrong.
>> Don't you mean "break"?
>
> Exactly how do you exit out of a set of nested loops with a "break"?
I don't. I exit out of a set of nested loops using the conditions in the
loop controllers.
--
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
|
|
0
|
|
|
|
Reply
|
Richard
|
4/27/2010 6:45:55 PM
|
|
In comp.lang.c++ Richard Heathfield <rjh@see.sig.invalid> wrote:
>> Exactly how do you exit out of a set of nested loops with a "break"?
>
> I don't. I exit out of a set of nested loops using the conditions in the
> loop controllers.
The idea was to make the code simpler, cleaner and easier to follow, not
more complicated and contrived.
|
|
0
|
|
|
|
Reply
|
Juha
|
4/27/2010 6:51:08 PM
|
|
Juha Nieminen wrote:
> In comp.lang.c++ Richard Heathfield <rjh@see.sig.invalid> wrote:
>>> Exactly how do you exit out of a set of nested loops with a "break"?
>> I don't. I exit out of a set of nested loops using the conditions in the
>> loop controllers.
>
> The idea was to make the code simpler, cleaner and easier to follow, not
> more complicated and contrived.
Yes. That's precisely why I use the conditions in the loop controllers.
--
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
|
|
0
|
|
|
|
Reply
|
Richard
|
4/27/2010 7:01:49 PM
|
|
On 04/26/10 17:03, Stuart Redmann wrote:
>
> Just to add my 2 cents:
> Your statement says that break-statements (I really like the term
> "goto in disguise", thank you, James) can keep the loop condition
> short and sweet. I think that this is probably not the most convincing
> argument for the usage of break-statements, but the readability of
> code should not be underestimated. That's why I'd suggest that also
> the use of continue-statements can increase the readability a lot. If
> you have a look at the following piece of code (from actual production
> environment):
Well, every control statement is goto-in disguise.
Goto is in:
FORLOOP: for (...) {
...
} // hiden goto FORLOOP
WHILELOOP: while (...) {
...
break; // hidden goto END
...
continue; // hidden goto WHILELOOP
...
END:} // hidden goto WHILELOOP
switch(expr) {
// hidden goto `expr`
case GOTOLABEL_1:
case GOTOLABEL_2:
...
break; // hidden goto END
case GOTOLABEL_3:
END: }
if (expr) { // hidden conditional goto ELSE
ELSE: } else {
}
void func() {
FUNCCALL:
...
} // hidden goto RETURN
void caller() {
func(); // hidden goto FUNCCALL
RETURN: ...
}
what else? hidden goto is so obiquitous that it's meaningless to claim
that some control structure is just a hidden goto.
|
|
0
|
|
|
|
Reply
|
Lie
|
4/27/2010 7:15:18 PM
|
|
On 04/25/10 16:19, red floyd wrote:
> On 4/24/2010 5:54 PM, Andrew Poelstra wrote:
>
>> The alternative here, using the loop structure, would be:
>>
>> for(i = 0; i< 10&& arr[i].state != READY; ++i)
>> ;
>> /* now use arr[i], or if i is 10, indicate failure. */
>>
>
> As a purely stylistic matter, my empty loops always look like:
>
>
> for ( begin_expr; test_expr; next_expr)
> /* do nothing */ ;
>
> That is, I always explicitly comment the empty loop so that
> it's clear that I wanted the loop to be empty.
>
Stylistically, I would put an empty { } to the side, containing a single
space:
for ( begin_expr; test_expr; next_expr) { }
instead of semicolons. Most brace-language programmer would
unconsciously filter out semicolons from the end of lines, while { } is
much more visible since it's more unusual to open a block only to close
it again.
|
|
0
|
|
|
|
Reply
|
Lie
|
4/27/2010 7:18:41 PM
|
|
Lie Ryan <lie.1296@gmail.com> writes:
> On 04/26/10 17:03, Stuart Redmann wrote:
>>
>> Just to add my 2 cents:
>> Your statement says that break-statements (I really like the term
>> "goto in disguise", thank you, James) can keep the loop condition
>> short and sweet. I think that this is probably not the most convincing
>> argument for the usage of break-statements, but the readability of
>> code should not be underestimated. That's why I'd suggest that also
>> the use of continue-statements can increase the readability a lot. If
>> you have a look at the following piece of code (from actual production
>> environment):
>
>
> Well, every control statement is goto-in disguise.
>
> Goto is in:
>
> FORLOOP: for (...) {
> ...
> } // hiden goto FORLOOP
[snip]
> what else? hidden goto is so obiquitous that it's meaningless to claim
> that some control structure is just a hidden goto.
Exactly. The distinguishing feature of the goto statements is that
it's (relatively) unconstrained. The other control flow constructs
aren't gotos in disguise; they're gotos with constraints, which means
that they aren't really gotos at all. Or, to put it another way,
it's the "disguise" that makes them really useful.
In my opinion, gotos are mostly useful as workarounds for missing
language features. A goto to error handling code at the end of
a function is a workaround for the lack of an exception handling
mechanism. A goto to break out of a multi-level loop is a workaround
for the lack of named loops.
On the other hand, a goto in an explicit finite state machine
implementation makes much more sense, because it directly models a
concept in the problem domain (states are represented by your current
location in the code, a goto represents a transition from one state to
another). Though I might still prefer a switch statement in a loop,
with the state represented by the current value of a state variable.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
Keith
|
4/27/2010 7:53:05 PM
|
|
raltbos@xs4all.nl (Richard Bos) wrote:
> "Daniel T." <daniel_t@earthlink.net> wrote:
>
> [ Quoting Dijkstra's "Goto considered harmful": ]
>
> > The unbridled use of the go to statement
>
> This is the one thing which Dijkstra's editor (who wrote that headline),
> the War-On-Goto lobby, and even Dijkstra himself in later years, seem to
> have missed.
>
> _Unbridled_.
>
> The unbridled use of salt is also deadly to humans. We must ban it
> outright.
>
> Richard (takes a little salt, not a lot)
Unbridled use of strychnine is deadly too, how much strychnine do you
take? The debate is not the false dichotomy that some try to make it out
to be.
|
|
0
|
|
|
|
Reply
|
Daniel
|
4/27/2010 8:12:26 PM
|
|
In alt.lang.asm Esra Sdrawkcab <admin@127.0.0.1> wrote in part:
> [editor with key processing]
> Pshurely 'call [ebx]' and end each section with 'ret', no goto required?
Certainly if you wish to reuse the commands between different
modes. Less if you are desparately counting cycles on an 8088
(jmp saves a jmp after the ret). Also less good if the key
never returns "exit".
>> obTroll: In many ways, GOTO is reminiscent of the slightly
>> more recent calculator debate between fans of TI algebraic
>> notation and HP reverse polish notation.
>
> Damn, missed that!
>
> betterTroll: what about Comefrom?
??? what is even slightly trollish about COMEFROM?
It is an obvious debugging tool with _plenty_ of
hardware support (brkpt instructions & debug registers).
If someone chooses to use COMEFROM in their code, they
must think their code has bugs. They would know :)
>> -- Robert
>>
> Needs a CRLF in there?
'dems fightin' words. You callin' me MS-DOSish :)
Yes, I realize \n is old-school correct from when people (incl
me) had real paper ttys. I tr to save readers an extra line on
their too-short read-boxes. (I normally run monitors in portrait
mode with 100+ lines).
-- Robert
>
|
|
0
|
|
|
|
Reply
|
redelm (106)
|
4/28/2010 3:38:47 AM
|
|
"Robert Redelmeier" <redelm@ev1.net.invalid> wrote in message
news:hr8ak7$vhk$1@speranza.aioe.org...
>
> modes. Less if you are desparately counting cycles on an 8088
> (jmp saves a jmp after the ret).
Don't you mean that a 'jmp' saves a 'ret' after a 'ret'??
For nested calls, the final call can be replaced by a jmp. E.g.:
,---
Afunc:
<misc. code & func calls>
call Zfunc
`---
replaced by...
,---
Afunc:
<misc. code & func calls>
jmp Zfunc
`---
Nathan.
|
|
0
|
|
|
|
Reply
|
nathancbaker263 (50)
|
4/28/2010 5:00:16 AM
|
|
In comp.lang.c++ Richard Heathfield <rjh@see.sig.invalid> wrote:
> Juha Nieminen wrote:
>> In comp.lang.c++ Richard Heathfield <rjh@see.sig.invalid> wrote:
>>>> Exactly how do you exit out of a set of nested loops with a "break"?
>>> I don't. I exit out of a set of nested loops using the conditions in the
>>> loop controllers.
>>
>> The idea was to make the code simpler, cleaner and easier to follow, not
>> more complicated and contrived.
>
> Yes. That's precisely why I use the conditions in the loop controllers.
Care to show an actual example of your "simpler, cleaner and easier to
follow" version of exiting a nested loop by meddling with the loop
conditions instead of using 'return'? For example, modify the following
code to conform to your specifications:
Value_t* MyClass::findValue(const Value_t& value)
{
for(size_t xInd = 0; xInd < data.size(); ++xInd)
for(size_t yInd = 0; yInd < data[xInd].size(); ++yInd)
for(size_t zInd = 0; zInd < data[xInd][yInd].size(); ++zInd)
{
if(data[xInd][yInd][zInd] == value)
return &data[xInd][yInd][zInd];
}
return 0;
}
|
|
0
|
|
|
|
Reply
|
Juha
|
4/28/2010 5:16:09 AM
|
|
On Apr 25, 7:47=A0am, James Kanze <james.ka...@gmail.com> wrote:
> [...] in C and in
> C++, for all "good" uses of goto (and a number of bad ones), the
> language has specialized structures which better express the
> meaning.
Just not so. Much low-level state-based code is best expressed via
gotos. There are a couple hundred usages spread over 7 different
Boost libraries (as of 1.41). Have a look and you might find
something you think reasonable. Sometimes working too much in a
particular set of problem domains can either make it seem like goto
isn't beneficial, or make it completely obvious it is. Parsers are
one area where the uses are clear, for example: the boost regex
parser. Similarly, some lexers I've written have employed gotos
too... it's just cleaner. I'm pretty sure Walter Bright chipped in on
an argument like this a couple years back, also supporting some uses
of gotos... not somebody who's experience I'd challenge - will try to
dig up the reference if anyone cares....
Cheers,
Tony
|
|
0
|
|
|
|
Reply
|
tonydee
|
4/28/2010 7:12:26 AM
|
|
On 25 Apr, 08:02, Juha Nieminen <nos...@thanks.invalid> wrote:
> In comp.lang.c++ red floyd <no.spam.h...@its.invalid> wrote:
> > As a purely stylistic matter, my empty loops always look like:
>
> > for ( begin_expr; test_expr; next_expr)
> > =A0 =A0/* do nothing */ ;
>
> =A0 No, the proper way of writing an empty loop is:
alarm bells go off whenever I see a sentence of the form "the proper
way to..."
> for(begin_expr; test_expr; next_expr) {}
>
> =A0 The empty block makes it explicitly clear that it's intended to be em=
pty,
> and not just a typo. (The empty block could also be put in the next line,
> below the 'for', if so desired. A matter of style.)
for (begin_expr; test_expr; next_expr)
;
is my usual form. And I cam across this and was taken with it
for (begin_expr; test_expr; next_expr)
continue;
(the place I'd comtemplate a continue)
|
|
0
|
|
|
|
Reply
|
Nick
|
4/28/2010 7:26:52 AM
|
|
On 27 Apr, 21:12, "Daniel T." <danie...@earthlink.net> wrote:
> ralt...@xs4all.nl (Richard Bos) wrote:
> > "Daniel T." <danie...@earthlink.net> wrote:
>
> > [ Quoting Dijkstra's "Goto considered harmful": ]
>
> > > =A0 =A0The unbridled use of the go to statement
>
> > This is the one thing which Dijkstra's editor (who wrote that headline)=
,
> > the War-On-Goto lobby, and even Dijkstra himself in later years, seem t=
o
> > have missed.
>
> > _Unbridled_.
>
> > The unbridled use of salt is also deadly to humans. We must ban it
> > outright.
>
> > Richard (takes a little salt, not a lot)
>
> Unbridled use of strychnine is deadly too, how much strychnine do you
> take? The debate is not the false dichotomy that some try to make it out
> to be.
digitalis is a poison and quite a lot of peopel take on the doctor's
advice
|
|
0
|
|
|
|
Reply
|
Nick
|
4/28/2010 7:28:33 AM
|
|
On Apr 28, 12:16=A0pm, Juha Nieminen <nos...@thanks.invalid> wrote:
> In comp.lang.c++ Richard Heathfield <r...@see.sig.invalid> wrote:
I'll admit my C functions tend to be overly long, but, without
mentioning names, some C programmers seem to use functions that
tend to be overly short! When a slightly complicated code fragment
is posted, like Juha's though there are unrelated examples, an
oft-seen response is "break it into smaller functions." For example
foo() { for ... for ... for ...}
can be built from three functions like
foo1() { for ... foo2(); }
*That*'s a big reason why some programmers "never need to use goto."
> > Juha Nieminen wrote:
> >> =A0 The idea was to make the code simpler, cleaner and easier to follo=
w, not
> >> more complicated and contrived.
> > Yes. That's precisely why I use the conditions in the loop controllers.
> =A0 ... For example, modify the following
> code to conform to your specifications:
> [ for ... for ... for ... if ... return ]
As Juha is well aware, it's possible to make the code conform
by making the for statements much more complicated.
But when one compares the code, before and after, it's hard
to see why anyone would prefer the complicated code unless
they just have a dogmatic aversion to inner-returns or gotos.
On Apr 28, 2:12 pm, tonydee <tony_in_da...@yahoo.co.uk> wrote:
> Sometimes working too much in a
> particular set of problem domains can either make it seem like goto
> isn't beneficial, or make it completely obvious it is.
This is an important point. In some ways, my experience has
been fairly broad, but I've never written a real parser, a
database manager, an accounting program, or a serious user
interface! (Some who now laugh at my inexperience may not
have written state space searchers, hardware diagnostics,
compressors, kernels, graphic or image manipulations, etc.)
Different applications will lead to different coding
style choices.
James Dow Allen
|
|
0
|
|
|
|
Reply
|
James
|
4/28/2010 7:32:36 AM
|
|
On 28 Apr, 06:16, Juha Nieminen <nos...@thanks.invalid> wrote:
> In comp.lang.c++ Richard Heathfield <r...@see.sig.invalid> wrote:
>
> > Juha Nieminen wrote:
> >> In comp.lang.c++ Richard Heathfield <r...@see.sig.invalid> wrote:
> >>>> =A0 Exactly how do you exit out of a set of nested loops with a "bre=
ak"?
> >>> I don't. I exit out of a set of nested loops using the conditions in =
the
> >>> loop controllers.
>
> >> =A0 The idea was to make the code simpler, cleaner and easier to follo=
w, not
> >> more complicated and contrived.
>
> > Yes. That's precisely why I use the conditions in the loop controllers.
>
> =A0 Care to show an actual example of your "simpler, cleaner and easier t=
o
> follow" version of exiting a nested loop by meddling with the loop
> conditions instead of using 'return'? For example, modify the following
> code to conform to your specifications:
>
> Value_t* MyClass::findValue(const Value_t& value)
> {
> =A0 =A0 for(size_t xInd =3D 0; xInd < data.size(); ++xInd)
> =A0 =A0 =A0 =A0 for(size_t yInd =3D 0; yInd < data[xInd].size(); ++yInd)
> =A0 =A0 =A0 =A0 =A0 =A0 for(size_t zInd =3D 0; zInd < data[xInd][yInd].si=
ze(); ++zInd)
> =A0 =A0 =A0 =A0 =A0 =A0 {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if(data[xInd][yInd][zInd] =3D=3D value)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return &data[xInd][yInd][zInd];
> =A0 =A0 =A0 =A0 =A0 =A0 }
>
> =A0 =A0 return 0;
check out Richard Heathfield's posting history he's a confirmed single-
entry-single-exit man (like spinoza). I don't happen to agree but
there's no point in arguing about it.
|
|
0
|
|
|
|
Reply
|
Nick
|
4/28/2010 7:33:09 AM
|
|
"Daniel T." <daniel_t@earthlink.net> writes:
> raltbos@xs4all.nl (Richard Bos) wrote:
>> "Daniel T." <daniel_t@earthlink.net> wrote:
>>
>> [ Quoting Dijkstra's "Goto considered harmful": ]
>>
>> > The unbridled use of the go to statement
>>
>> This is the one thing which Dijkstra's editor (who wrote that headline),
>> the War-On-Goto lobby, and even Dijkstra himself in later years, seem to
>> have missed.
>>
>> _Unbridled_.
>>
>> The unbridled use of salt is also deadly to humans. We must ban it
>> outright.
>>
>> Richard (takes a little salt, not a lot)
>
> Unbridled use of strychnine is deadly too, how much strychnine do you
> take?
As a stimulant or a performance-enhancing drug, a couple of milligrams,
traditionally.
> The debate is not the false dichotomy that some try to make it out
> to be.
It's odd that you appear to have attempted to push it towards a
dichotomy with the above.
Phil
--
I find the easiest thing to do is to k/f myself and just troll away
-- David Melville on r.a.s.f1
|
|
0
|
|
|
|
Reply
|
Phil
|
4/28/2010 7:36:32 AM
|
|
Juha Nieminen wrote:
> In comp.lang.c++ Richard Heathfield <rjh@see.sig.invalid> wrote:
>> Juha Nieminen wrote:
>>> In comp.lang.c++ Richard Heathfield <rjh@see.sig.invalid> wrote:
>>>>> Exactly how do you exit out of a set of nested loops with a "break"?
>>>> I don't. I exit out of a set of nested loops using the conditions in the
>>>> loop controllers.
>>> The idea was to make the code simpler, cleaner and easier to follow, not
>>> more complicated and contrived.
>> Yes. That's precisely why I use the conditions in the loop controllers.
>
> Care to show an actual example of your "simpler, cleaner and easier to
> follow" version of exiting a nested loop by meddling with the loop
> conditions instead of using 'return'?
I wasn't planning on "meddling" with anything. I was planning on writing
appropriate loop conditions.
> For example, modify the following
> code to conform to your specifications:
>
> Value_t* MyClass::findValue(const Value_t& value)
I'm reading this in comp.lang.c, but I'll give you a C parallel if you like.
> {
> for(size_t xInd = 0; xInd < data.size(); ++xInd)
> for(size_t yInd = 0; yInd < data[xInd].size(); ++yInd)
> for(size_t zInd = 0; zInd < data[xInd][yInd].size(); ++zInd)
> {
> if(data[xInd][yInd][zInd] == value)
> return &data[xInd][yInd][zInd];
> }
>
> return 0;
> }
If the data are sorted, bsearch.
If not, why not?
In any case, your loop condition expressions do not correctly describe
the conditions under which the loop will terminate. Please rewrite your
example so that they do, and then by all means ask me again if you wish.
--
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
|
|
0
|
|
|
|
Reply
|
Richard
|
4/28/2010 9:02:47 AM
|
|
Nick Keighley wrote:
<snip>
> check out Richard Heathfield's posting history he's a confirmed single-
> entry-single-exit man (like spinoza).
If that's true (and it might well be true) about "spinoza", then I find
it mildly interesting, but no more than that. He uses (a kind of)
English, too, but that doesn't make English a poor choice of language.
> I don't happen to agree but
> there's no point in arguing about it.
Probably true. The problem is rather like that of threading vs state
machines. State machine advocates claim that threading is for people who
can't write state machines, and threading advocates claim that state
machines are for people who can't understand threading.
SESE works for me. Clearly, multiple exits work for Juha. Since we don't
work on the same code base, let us celebrate this cultural diversity
instead of arguing about it. :-)
--
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
|
|
0
|
|
|
|
Reply
|
Richard
|
4/28/2010 9:13:37 AM
|
|
In comp.lang.c++ Richard Heathfield <rjh@see.sig.invalid> wrote:
> If the data are sorted, bsearch.
>
> If not, why not?
>
> In any case, your loop condition expressions do not correctly describe
> the conditions under which the loop will terminate. Please rewrite your
> example so that they do, and then by all means ask me again if you wish.
No offense, but it always amuses me how some C programmers try to
wiggle themselves out of actually giving honest answers when they are
presented with problematic situations related to their coding style, C,
or both.
The question was not "how would you keep this kind of data stored so
that it's as fast and easy to find as possible?" That's completely besides
the point.
The question was "if the task, whatever it might be, is resolved in the
innermost loop, and hence all the loops can be ended right away because
the desired result has been retrieved, what would be the simplest way of
doing that?"
Or in less words: "What's the simplest way of exiting nested loops?"
You simply attempted to evade that question by nitpicking on irrelevant
details of the example code. It doesn't matter what kind of data container
the routine was dealing with or how it's being searched: The relevant part
was that a triply-nested loop is being performed, and the task is achieved
in the innermost one.
And I have no idea what you mean by "your loop condition expressions do
not correctly describe the conditions under which the loop will terminate".
Of course they do. Is this just another attempt at wiggling yourself out
of actually giving the answer?
Is it *really* that hard to simply say "yes, in this particular example
the 'return' is indeed the simplest way"? Does it hurt your pride or
something?
|
|
0
|
|
|
|
Reply
|
Juha
|
4/28/2010 11:19:31 AM
|
|
On 28 Apr, 10:13, Richard Heathfield <r...@see.sig.invalid> wrote:
> Nick Keighley wrote:
> > check out Richard Heathfield's posting history he's a confirmed single-
> > entry-single-exit man (like spinoza).
>
> If that's true (and it might well be true) about "spinoza", then I find
> it mildly interesting, but no more than that. He uses (a kind of)
> English, too, but that doesn't make English a poor choice of language.
>
> > I don't happen to agree but
> > there's no point in arguing about it.
>
> Probably true. The problem is rather like that of threading vs state
> machines. State machine advocates claim that threading is for people who
> can't write state machines, and threading advocates claim that state
> machines are for people who can't understand threading.
>
> SESE works for me. Clearly, multiple exits work for Juha. Since we don't
> work on the same code base, let us celebrate this cultural diversity
> instead of arguing about it. :-)
that's what i meant about "not arguing". I'm happy to discuss my
opinion and coding practices on SESE etc. To lay out the pros and cons
of the different approaches but in the end there is an amount of
"taste" involved in the final descision. Its arguments about "taste" I
find pointless. That is why I suggested he read your backposts you've
stated your opinion clearly in the past and argued your points well.
--
Unpredictability may be exciting, but I don't believe it constitutes
good programming practice.
Richard Heathfield
|
|
0
|
|
|
|
Reply
|
Nick
|
4/28/2010 11:40:28 AM
|
|
Phil Carmody <thefatphil_demunged@yahoo.co.uk> wrote:
> "Daniel T." <daniel_t@earthlink.net> writes:
>
> > The debate is not the false dichotomy that some try to make it out
> > to be.
>
> It's odd that you appear to have attempted to push it towards a
> dichotomy with the above.
Not at all. I specifically picked strychnine because it is something
that can be taken (but it's far from common.) I am simply pointing out
that there are degrees, and the debate is about degrees, not about
throwing a switch.
Three examples have been presented using your analogy, water, salt, and
strychnine. The question is, which is goto more like? The question isn't
"whether" goto is safe to use, but "how safe is it." Are better
alternatives available?
|
|
0
|
|
|
|
Reply
|
Daniel
|
4/28/2010 11:55:57 AM
|
|
Nick Keighley <nick_keighley_nospam@hotmail.com> wrote:
> On 27 Apr, 21:12, "Daniel T." <danie...@earthlink.net> wrote:
> > ralt...@xs4all.nl (Richard Bos) wrote:
> > > "Daniel T." <danie...@earthlink.net> wrote:
> >
> > > [ Quoting Dijkstra's "Goto considered harmful": ]
> >
> > > > � �The unbridled use of the go to statement
> >
> > > This is the one thing which Dijkstra's editor (who wrote that
> > > headline), the War-On-Goto lobby, and even Dijkstra himself in
> > > later years, seem to have missed.
> >
> > > _Unbridled_.
> >
> > > The unbridled use of salt is also deadly to humans. We must ban it
> > > outright.
> >
> > > Richard (takes a little salt, not a lot)
> >
> > Unbridled use of strychnine is deadly too, how much strychnine do
> > you take? The debate is not the false dichotomy that some try to
> > make it out to be.
>
> digitalis is a poison and quite a lot of peopel take on the doctor's
> advice
"On doctor's advice," how would that fit in the analogy? Maybe "upon
extensive peer review, a consensus was reached that goto was the best
alternative in this context."
|
|
0
|
|
|
|
Reply
|
Daniel
|
4/28/2010 11:58:30 AM
|
|
On 28 Apr., 11:02, Richard Heathfield wrote:
> Juha Nieminen wrote:
> > Richard Heathfield wrote:
> >> Juha Nieminen wrote:
> >>>>> Exactly how do you exit out of a set of nested loops with a "break"=
?
> >>>> I don't. I exit out of a set of nested loops using the conditions in=
the
> >>>> loop controllers.
> >>> The idea was to make the code simpler, cleaner and easier to follow, =
not
> >>> more complicated and contrived.
> >> Yes. That's precisely why I use the conditions in the loop controllers=
..
> > Care to show an actual example of your "simpler, cleaner and easier to
> > follow" version of exiting a nested loop by meddling with the loop
> > conditions instead of using 'return'?
> I wasn't planning on "meddling" with anything. I was planning on writing
> appropriate loop conditions.
[snip]
> > Value_t* MyClass::findValue(const Value_t& value)
> > {
> > =A0 for(size_t xInd =3D 0; xInd < data.size(); ++xInd)
> > =A0 =A0 for(size_t yInd =3D 0; yInd < data[xInd].size(); ++yInd)
> > =A0 =A0 =A0 for(size_t zInd =3D 0; zInd < data[xInd][yInd].size(); ++zI=
nd)
> > =A0 =A0 =A0 {
> > =A0 =A0 =A0 =A0 if(data[xInd][yInd][zInd] =3D=3D value)
> > =A0 =A0 =A0 =A0 =A0 return &data[xInd][yInd][zInd];
> > =A0 =A0 =A0 }
> > =A0 return 0;
> > }
[snip]
> In any case, your loop condition expressions do not correctly describe
> the conditions under which the loop will terminate.
This was probably intentional. Expressing it "correctly" forces you to
write slightly more comprex loop conditions which contain some kind of
"i'm done"-flag like this:
Value_t* MyClass::findValue(const Value_t& value)
{
Value_t* result =3D 0;
for(size_t xInd =3D 0; !result && xInd < data.size(); ++xInd)
for(size_t yInd =3D 0; !result && yInd < data[xInd].size();
++yInd)
for(size_t zInd =3D 0; !result && zInd < data[xInd]
[yInd].size();
++zInd)
{
if(data[xInd][yInd][zInd] =3D=3D value)
result =3D &data[xInd][yInd][zInd];
}
return result;
}
I don't know about you but I like the first version better. It's more
concise. I find it easier to see what the loop's doing. Maybe it's
just me. I guess I'm used to these kinds of loops.
> Please rewrite your example so that they do, [...]
That's the point. You don't *have* to write them "correctly". You can
get away with simpler conditions and without introducing otherwise
unnecessary flags.
Cheers,
SG
|
|
0
|
|
|
|
Reply
|
SG
|
4/28/2010 12:00:50 PM
|
|
On Wed, 28 Apr 2010 04:38:47 +0100, Robert Redelmeier
<redelm@ev1.net.invalid> wrote:
> In alt.lang.asm Esra Sdrawkcab <admin@127.0.0.1> wrote in part:
>> [editor with key processing]
>
>> Pshurely 'call [ebx]' and end each section with 'ret', no goto required?
>
> Certainly if you wish to reuse the commands between different
> modes. Less if you are desparately counting cycles on an 8088
> (jmp saves a jmp after the ret). Also less good if the key
> never returns "exit".
>
Fairy 'nuff. But we're looking at speed, not (lack of) "Goto"s then.
>>> obTroll: In many ways, GOTO is reminiscent of the slightly
>>> more recent calculator debate between fans of TI algebraic
>>> notation and HP reverse polish notation.
>>
>> Damn, missed that!
>>
>> betterTroll: what about Comefrom?
>
> ??? what is even slightly trollish about COMEFROM?
>
> It is an obvious debugging tool with _plenty_ of
> hardware support (brkpt instructions & debug registers).
>
> If someone chooses to use COMEFROM in their code, they
> must think their code has bugs. They would know :)
>
>>> -- Robert
>>>
>> Needs a CRLF in there?
>
> 'dems fightin' words. You callin' me MS-DOSish :)
>
> Yes, I realize \n is old-school correct from when people (incl
> me) had real paper ttys. I tr to save readers an extra line on
> their too-short read-boxes. (I normally run monitors in portrait
> mode with 100+ lines).
>
> -- Robert
>
Ok a newline then!
I was taught sig sep should be newline dash dash space newline.
>
>>
--
Nuns! Nuns! Reverse
|
|
0
|
|
|
|
Reply
|
Esra
|
4/28/2010 12:58:16 PM
|
|
In article
<dbac22e7-4667-485e-b829-2505e2bd948d@q23g2000yqd.googlegroups.com>,
SG <s.gesemann@gmail.com> wrote:
> On 28 Apr., 11:02, Richard Heathfield wrote:
> > Juha Nieminen wrote:
> > > Richard Heathfield wrote:
> > >> Juha Nieminen wrote:
> > >>>>> Exactly how do you exit out of a set of nested loops with a "break"?
> > >>>> I don't. I exit out of a set of nested loops using the conditions in
> > >>>> the
> > >>>> loop controllers.
> > >>> The idea was to make the code simpler, cleaner and easier to follow,
> > >>> not
> > >>> more complicated and contrived.
> > >> Yes. That's precisely why I use the conditions in the loop controllers.
> > > Care to show an actual example of your "simpler, cleaner and easier to
> > > follow" version of exiting a nested loop by meddling with the loop
> > > conditions instead of using 'return'?
> > I wasn't planning on "meddling" with anything. I was planning on writing
> > appropriate loop conditions.
>
> [snip]
>
> > > Value_t* MyClass::findValue(const Value_t& value)
> > > {
> > > � for(size_t xInd = 0; xInd < data.size(); ++xInd)
> > > � � for(size_t yInd = 0; yInd < data[xInd].size(); ++yInd)
> > > � � � for(size_t zInd = 0; zInd < data[xInd][yInd].size(); ++zInd)
> > > � � � {
> > > � � � � if(data[xInd][yInd][zInd] == value)
> > > � � � � � return &data[xInd][yInd][zInd];
> > > � � � }
> > > � return 0;
> > > }
>
> [snip]
>
> > In any case, your loop condition expressions do not correctly describe
> > the conditions under which the loop will terminate.
>
> This was probably intentional. Expressing it "correctly" forces you to
> write slightly more comprex loop conditions which contain some kind of
> "i'm done"-flag like this:
>
> Value_t* MyClass::findValue(const Value_t& value)
> {
> Value_t* result = 0;
> for(size_t xInd = 0; !result && xInd < data.size(); ++xInd)
> for(size_t yInd = 0; !result && yInd < data[xInd].size();
> ++yInd)
> for(size_t zInd = 0; !result && zInd < data[xInd]
> [yInd].size();
> ++zInd)
> {
> if(data[xInd][yInd][zInd] == value)
> result = &data[xInd][yInd][zInd];
> }
> return result;
> }
>
> I don't know about you but I like the first version better. It's more
> concise. I find it easier to see what the loop's doing. Maybe it's
> just me. I guess I'm used to these kinds of loops.
Since the sample code is obviously in c++, I would rather see something
like:
Iterator it = data.begin()
while(it != data.end() && *it != value)
++it;
return it != data.end();
|
|
0
|
|
|
|
Reply
|
Daniel
|
4/28/2010 12:59:08 PM
|
|
On 4/27/2010 10:25 AM, Keith H Duggar wrote:
> On Apr 27, 10:07 am, ralt...@xs4all.nl (Richard Bos) wrote:
>> "Daniel T."<danie...@earthlink.net> wrote:
>>
>> [ Quoting Dijkstra's "Goto considered harmful": ]
>>
>>> The unbridled use of the go to statement
>>
>> This is the one thing which Dijkstra's editor (who wrote that headline),
>> the War-On-Goto lobby, and even Dijkstra himself in later years, seem to
>> have missed.
>>
>> _Unbridled_.
>>
>> The unbridled use of salt is also deadly to humans. We must ban it
>> outright.
>>
>> Richard (takes a little salt, not a lot)
>
> Indeed. Unbridled water drinking can be fatal:
>
> http://en.wikipedia.org/wiki/Water_intoxication
>
> Pure water is dangerous and highly concentrated being 55 molar. Water
> kills more than a million people per year, half of them children! How
> can anyone stand for the unbridled use of water.
Forget about water. What about DHMO contamination?
http://www.dhmo.org/
--
Kenneth Brody
|
|
0
|
|
|
|
Reply
|
Kenneth
|
4/28/2010 1:28:00 PM
|
|
On 4/28/2010 3:26 AM, Nick Keighley wrote:
> On 25 Apr, 08:02, Juha Nieminen<nos...@thanks.invalid> wrote:
>> In comp.lang.c++ red floyd<no.spam.h...@its.invalid> wrote:
>
>>> As a purely stylistic matter, my empty loops always look like:
[... snip "the right way" to write empty loop ...]
>
> for (begin_expr; test_expr; next_expr)
> ;
>
> is my usual form. And I cam across this and was taken with it
>
> for (begin_expr; test_expr; next_expr)
> continue;
>
> (the place I'd comtemplate a continue)
We can discuss "the right way" til the cows come home. However, I think
we'd probably all agree that this is "the wrong way":
for ( begin ; test ; next );
Yes, I've seen it, numerous times, in someone's code.
Even worse is when different editors have caused tab misalignment, and you
end up with:
for ( begin ; test ; next );
if ( this )
do_that();
(I've seen that, too.)
--
Kenneth Brody
|
|
0
|
|
|
|
Reply
|
Kenneth
|
4/28/2010 1:35:45 PM
|
|
On 4/27/2010 10:07 AM, Richard Bos wrote:
> "Daniel T."<daniel_t@earthlink.net> wrote:
>
> [ Quoting Dijkstra's "Goto considered harmful": ]
>
>> The unbridled use of the go to statement
>
> This is the one thing which Dijkstra's editor (who wrote that headline),
> the War-On-Goto lobby, and even Dijkstra himself in later years, seem to
> have missed.
>
> _Unbridled_.
>
> The unbridled use of salt is also deadly to humans. We must ban it
> outright.
I thought that "on goto" was part of BASIC, and not C or C++.
<gdrc>
--
Kenneth Brody
|
|
0
|
|
|
|
Reply
|
Kenneth
|
4/28/2010 1:37:52 PM
|
|
On 04/25/10 01:18, Richard wrote:
>>> but it is a good opportunity to suggest to
>>> everyone who is tempted to argue about this issue to start from
>>> Dijkstra's paper rather than simply asserting that "goto is good"
>>> without understanding the issues involved.
>>>
>>> http://www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_
>>> Harmful.html
>>
>> And then read Knuth's "Structured Programming with go to Statements" (a bad
>> scan is here:
>> http://pplab.snu.ac.kr/courses/adv_pl05/papers/p261-knuth.pdf)
>>
>> "... programmers and language designers still feel the need for some
>> euphemism that 'goes to' without saying 'go to' ..."
>
> Recommending Knuth is like telling someone they need to qualify as a
> NASA rocket scientist in order to fly a kite.
The Japanese thought so: Ikaros "Interspace *Kite*-craft Accelerated by
Radiation of Sun"
http://www.news.com.au/technology/ikaros-space-yacht-ready-to-sail-as-far-as-sun-shines/story-e6frfro0-1225859168363
|
|
0
|
|
|
|
Reply
|
Lie
|
4/28/2010 3:02:53 PM
|
|
On Apr 28, 12:19=A0pm, Juha Nieminen <nos...@thanks.invalid> wrote:
> =A0 Or in less words: "What's the simplest way of exiting nested loops?"
> You simply attempted to evade that question by nitpicking on irrelevant
> details of the example code.
Juha Nieminen, meet Richard Heathfield.
|
|
0
|
|
|
|
Reply
|
gwowen
|
4/28/2010 3:22:09 PM
|
|
On Apr 28, 2:13=A0am, Richard Heathfield <r...@see.sig.invalid> wrote:
....
> Probably true. The problem is rather like that of threading vs state
> machines. State machine advocates claim that threading is for people who
> can't write state machines, and threading advocates claim that state
> machines are for people who can't understand threading.
How's that? I think some problems can't be solved (at all or easily)
with one of the two. And at times both are necessary.
Alex
|
|
0
|
|
|
|
Reply
|
Alexei
|
4/28/2010 3:52:05 PM
|
|
On 2010-04-28, Richard Heathfield <rjh@see.sig.invalid> wrote:
>> {
>> for(size_t xInd = 0; xInd < data.size(); ++xInd)
>> for(size_t yInd = 0; yInd < data[xInd].size(); ++yInd)
>> for(size_t zInd = 0; zInd < data[xInd][yInd].size(); ++zInd)
>> {
>> if(data[xInd][yInd][zInd] == value)
>> return &data[xInd][yInd][zInd];
>> }
>>
>> return 0;
>> }
> If the data are sorted, bsearch.
> If not, why not?
I do not normally expect something structured like a three-dimensional
array to be sorted, I expect it to be a representation of objects.
> In any case, your loop condition expressions do not correctly describe
> the conditions under which the loop will terminate. Please rewrite your
> example so that they do, and then by all means ask me again if you wish.
I think the point was that he was asking *you* to rewrite the example
so that the loop conditions correctly describe the conditions under which
the loop will terminate.
I put it to you that it is impossible to write the above loop with remotely
comparable clarity without using a jump of some sort out of the inner
loop. Any attempt to do so will result in a MASSIVE loss of clarity.
* You can't refer to yInd and zInd from the outer loop unless you declare
them outside those inner loops, but doing that is undesireable, because
loop indecies should ideally be declared with their loops and used only
in those loops.
* Until you've started the inner loops, you can't refer to the innermost
value, and as such, you can't write that comparison.
* Adding an extra test to every level of the loop creates extra computational
time and makes things more confusing.
The best approximation I can think of is to do each of these as a separate
function, but even that doesn't let us avoid either some kind of break/return,
or adding a "found" value.
In short, this is a case where dogmatism about single-entry/single-exit has
very high costs to clarity. Now, it may be that it's worth it because of the
net gains in clarity and consistency elsewhere, but this certainly is one
of the worst cases for it.
-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
|
|
0
|
|
|
|
Reply
|
Seebs
|
4/28/2010 5:09:50 PM
|
|
"Seebs" <usenet-nospam@seebs.net> wrote in message
news:slrnhtgquu.lhj.usenet-nospam@guild.seebs.net...
> On 2010-04-28, Richard Heathfield <rjh@see.sig.invalid> wrote:
>>> {
>>> for(size_t xInd = 0; xInd < data.size(); ++xInd)
>>> for(size_t yInd = 0; yInd < data[xInd].size(); ++yInd)
>>> for(size_t zInd = 0; zInd < data[xInd][yInd].size(); ++zInd)
>>> {
>>> if(data[xInd][yInd][zInd] == value)
>>> return &data[xInd][yInd][zInd];
>>> }
>>>
>>> return 0;
>>> }
> I put it to you that it is impossible to write the above loop with
> remotely
> comparable clarity without using a jump of some sort out of the inner
> loop. Any attempt to do so will result in a MASSIVE loss of clarity.
int* findvalue(int value)
{int *a=0;
for(int xInd = 0; !a && xInd < datasize; ++xInd)
for(int yInd = 0; !a && yInd < dataxindsize; ++yInd)
for(int zInd = 0; !a && zInd < dataxindyindsize; ++zInd)
{
if(data[xInd][yInd][zInd] == value)
a=&data[xInd][yInd][zInd];
}
return a;
}
--
Bartc
|
|
0
|
|
|
|
Reply
|
bart
|
4/28/2010 5:47:24 PM
|
|
On 2010-04-28, bart.c <bartc@freeuk.com> wrote:
> int* findvalue(int value)
> {int *a=0;
>
> for(int xInd = 0; !a && xInd < datasize; ++xInd)
> for(int yInd = 0; !a && yInd < dataxindsize; ++yInd)
> for(int zInd = 0; !a && zInd < dataxindyindsize; ++zInd)
> {
> if(data[xInd][yInd][zInd] == value)
> a=&data[xInd][yInd][zInd];
> }
>
> return a;
> }
This is noticably slower and less clear. I would not consider it
an acceptable rewrite -- but I would consider the other form a good
rewrite of it.
-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
|
|
0
|
|
|
|
Reply
|
Seebs
|
4/28/2010 6:16:04 PM
|
|
Seebs <usenet-nospam@seebs.net> writes:
> On 2010-04-28, bart.c <bartc@freeuk.com> wrote:
>> int* findvalue(int value)
>> {int *a=0;
>>
>> for(int xInd = 0; !a && xInd < datasize; ++xInd)
>> for(int yInd = 0; !a && yInd < dataxindsize; ++yInd)
>> for(int zInd = 0; !a && zInd < dataxindyindsize; ++zInd)
>> {
>> if(data[xInd][yInd][zInd] == value)
>> a=&data[xInd][yInd][zInd];
>> }
>>
>> return a;
>> }
>
> This is noticably slower and less clear. I would not consider it
> an acceptable rewrite -- but I would consider the other form a good
> rewrite of it.
I mostly agree, but -- "noticably slower"? How did you notice?
I also wonder why Bartc changed the index type from size_t to int.
For the body of the inner loop, I might consider writing:
const int *p = &data[xInd][yInd][zInd];
if (*p == value) {
return p;
}
For a sufficiently naive compiler, it might avoid recomputing
the address; that by itself probably isn't a good enough reason
to do it, since I suspect most decent optimizing compilers will
avoid recomputing it anyway. But it also avoids writing a fairly
complex expression twice, which could be helpful to the reader.
A typo in one of the two occurrences of data[xInd][yInd][zInd]
could result in a bug that's very difficult to track down.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
Keith
|
4/28/2010 6:28:48 PM
|
|
On 2010-04-28, Keith Thompson <kst-u@mib.org> wrote:
> I mostly agree, but -- "noticably slower"? How did you notice?
Good point. But I'd certainly *expect* it to be slower to add another
test and a sequence point. I guess we could measure it.
> For a sufficiently naive compiler, it might avoid recomputing
> the address; that by itself probably isn't a good enough reason
> to do it, since I suspect most decent optimizing compilers will
> avoid recomputing it anyway. But it also avoids writing a fairly
> complex expression twice, which could be helpful to the reader.
> A typo in one of the two occurrences of data[xInd][yInd][zInd]
> could result in a bug that's very difficult to track down.
Yes.
-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
|
|
0
|
|
|
|
Reply
|
Seebs
|
4/28/2010 6:45:18 PM
|
|
Keith Thompson wrote:
> Seebs <usenet-nospam@seebs.net> writes:
>> On 2010-04-28, bart.c <bartc@freeuk.com> wrote:
>>> int* findvalue(int value)
>>> {int *a=0;
>>>
>>> for(int xInd = 0; !a && xInd < datasize; ++xInd)
>>> for(int yInd = 0; !a && yInd < dataxindsize; ++yInd)
>>> for(int zInd = 0; !a && zInd < dataxindyindsize; ++zInd)
>>> {
>>> if(data[xInd][yInd][zInd] == value)
>>> a=&data[xInd][yInd][zInd];
>>> }
>>>
>>> return a;
>>> }
>> This is noticably slower and less clear. I would not consider it
>> an acceptable rewrite -- but I would consider the other form a good
>> rewrite of it.
>
> I mostly agree, but -- "noticably slower"? How did you notice?
Certainly is for the case data[0][0][0] == value. ;-)
Jeff
|
|
0
|
|
|
|
Reply
|
Jeff
|
4/28/2010 6:57:55 PM
|
|
"Keith Thompson" <kst-u@mib.org> wrote in message
news:lnr5lza0tb.fsf@nuthaus.mib.org...
> Seebs <usenet-nospam@seebs.net> writes:
>> On 2010-04-28, bart.c <bartc@freeuk.com> wrote:
>>> int* findvalue(int value)
>>> {int *a=0;
>>> for(int xInd = 0; !a && xInd < datasize; ++xInd)
>>> for(int yInd = 0; !a && yInd < dataxindsize; ++yInd)
>>> for(int zInd = 0; !a && zInd < dataxindyindsize; ++zInd)
>>> {
>>> if(data[xInd][yInd][zInd] == value)
>>> a=&data[xInd][yInd][zInd];
>>> }
>>> return a;
>>> }
>>
>> This is noticably slower and less clear. I would not consider it
>> an acceptable rewrite -- but I would consider the other form a good
>> rewrite of it.
> I mostly agree, but -- "noticably slower"? How did you notice?
I thought the issue was clarity rather than performance. But as it happened
I did measure my code with a version using the return in the inner loop, and
the latter was faster (at least, with a 2x3x4 array of ints).
> I also wonder why Bartc changed the index type from size_t to int.
I don't like size_t's (because they look unwieldy). And if speed is a
factor, I don't see the point of allowing the compiler to use 64-bit indices
when 32-bit ones might do just as well, and possibly better.
> For the body of the inner loop, I might consider writing:
>
> const int *p = &data[xInd][yInd][zInd];
> if (*p == value) {
> return p;
> }
>
> For a sufficiently naive compiler, it might avoid recomputing
> the address; that by itself probably isn't a good enough reason
> to do it, since I suspect most decent optimizing compilers will
> avoid recomputing it anyway. But it also avoids writing a fairly
> complex expression twice, which could be helpful to the reader.
The second expression is only evaluated once (compared with
possibly millions of times for the first).
> A typo in one of the two occurrences of data[xInd][yInd][zInd]
> could result in a bug that's very difficult to track down.
When clarity is important, using xInd, yInd, zInd instead of just x,y,z,
size_t instead of int (and declaring those inside instead of outside the
loops), and those long expressions for the bounds of each dimension, have a
bigger impact, imo, than adding an extra test.
--
Bartc
|
|
0
|
|
|
|
Reply
|
bart
|
4/28/2010 7:06:51 PM
|
|
Richard Heathfield wrote:
) In any case, your loop condition expressions do not correctly describe
) the conditions under which the loop will terminate. Please rewrite your
) example so that they do, and then by all means ask me again if you wish.
Don't be silly.
'loop conditions should correctly describe the conditions under
which the loop will terminate' is a requirement that is roughly
equivalent to 'you should never exit from within a loop'.
In other words, you're begging the question.
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
|
|
0
|
|
|
|
Reply
|
Willem
|
4/28/2010 7:09:00 PM
|
|
Jeff Flinn <TriumphSprint2000@hotmail.com> writes:
> Keith Thompson wrote:
>> Seebs <usenet-nospam@seebs.net> writes:
>>> On 2010-04-28, bart.c <bartc@freeuk.com> wrote:
>>>> int* findvalue(int value)
>>>> {int *a=0;
>>>>
>>>> for(int xInd = 0; !a && xInd < datasize; ++xInd)
>>>> for(int yInd = 0; !a && yInd < dataxindsize; ++yInd)
>>>> for(int zInd = 0; !a && zInd < dataxindyindsize; ++zInd)
>>>> {
>>>> if(data[xInd][yInd][zInd] == value)
>>>> a=&data[xInd][yInd][zInd];
>>>> }
>>>>
>>>> return a;
>>>> }
>>> This is noticably slower and less clear. I would not consider it
>>> an acceptable rewrite -- but I would consider the other form a good
>>> rewrite of it.
>>
>> I mostly agree, but -- "noticably slower"? How did you notice?
>
> Certainly is for the case data[0][0][0] == value. ;-)
How so?
I'm not arguing that it's not *likely* to be slower, but (a) it's not
likely to be *noticeably* slower unless the entire loop is executed many
many times, and (b) it might not be slower at all, depending on how
clever the compiler is.
(I'm assuming there's not some semantic difference that I haven't
noticed.)
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
Keith
|
4/28/2010 7:13:06 PM
|
|
"Daniel T." <daniel_t@earthlink.net> writes:
> Phil Carmody <thefatphil_demunged@yahoo.co.uk> wrote:
>> "Daniel T." <daniel_t@earthlink.net> writes:
>>
>> > The debate is not the false dichotomy that some try to make it out
>> > to be.
>>
>> It's odd that you appear to have attempted to push it towards a
>> dichotomy with the above.
>
> Not at all. I specifically picked strychnine because it is something
> that can be taken (but it's far from common.) I am simply pointing out
> that there are degrees, and the debate is about degrees, not about
> throwing a switch.
>
> Three examples have been presented using your analogy, water, salt, and
> strychnine. The question is, which is goto more like? The question isn't
> "whether" goto is safe to use, but "how safe is it." Are better
> alternatives available?
IMHO, if you're deep in the linux kernel or its drivers, then it's
salt. You really don't want much, but some is almost always necessary,
and then it's definitely better than the lack thereof.
If you're in some bloaty multi-layered, multi-libraried userspace
program, then it's strychnine. If you're pretending to obsess about
the extra efficiency goto gives you, you're missing the point.
If it's water, and you're awash with gotos, then you're in the wrong
language.
Phil
--
I find the easiest thing to do is to k/f myself and just troll away
-- David Melville on r.a.s.f1
|
|
0
|
|
|
|
Reply
|
Phil
|
4/28/2010 7:58:36 PM
|
|
"bart.c" <bartc@freeuk.com> writes:
> "Keith Thompson" <kst-u@mib.org> wrote in message
> news:lnr5lza0tb.fsf@nuthaus.mib.org...
>> Seebs <usenet-nospam@seebs.net> writes:
>>> On 2010-04-28, bart.c <bartc@freeuk.com> wrote:
>>>> int* findvalue(int value)
>>>> {int *a=0;
>>>> for(int xInd = 0; !a && xInd < datasize; ++xInd)
>>>> for(int yInd = 0; !a && yInd < dataxindsize; ++yInd)
>>>> for(int zInd = 0; !a && zInd < dataxindyindsize; ++zInd)
>>>> {
>>>> if(data[xInd][yInd][zInd] == value)
>>>> a=&data[xInd][yInd][zInd];
>>>> }
>>>> return a;
>>>> }
>>>
>>> This is noticably slower and less clear. I would not consider it
>>> an acceptable rewrite -- but I would consider the other form a good
>>> rewrite of it.
>
>> I mostly agree, but -- "noticably slower"? How did you notice?
>
> I thought the issue was clarity rather than performance. But as it happened
> I did measure my code with a version using the return in the inner loop, and
> the latter was faster (at least, with a 2x3x4 array of ints).
Actual measurement? Now you've spoiled everybody's empty speculation!
>> I also wonder why Bartc changed the index type from size_t to int.
>
> I don't like size_t's (because they look unwieldy). And if speed is a
> factor, I don't see the point of allowing the compiler to use 64-bit indices
> when 32-bit ones might do just as well, and possibly better.
Speaking of "clarity rather than performance" ...
32-bit (or even 16-bit if int is that small) indices might *not* be
sufficient, and if they're not then you're probably not going to get a
warning from the compiler. size_t is (almost?) guaranteed to be big
enough. And it's not clear 32-bit indices are going to give you faster
code than 64-bit indices.
>> For the body of the inner loop, I might consider writing:
>>
>> const int *p = &data[xInd][yInd][zInd];
>> if (*p == value) {
>> return p;
>> }
>>
>> For a sufficiently naive compiler, it might avoid recomputing
>> the address; that by itself probably isn't a good enough reason
>> to do it, since I suspect most decent optimizing compilers will
>> avoid recomputing it anyway. But it also avoids writing a fairly
>> complex expression twice, which could be helpful to the reader.
>
> The second expression is only evaluated once (compared with
> possibly millions of times for the first).
Ah, good point!
>> A typo in one of the two occurrences of data[xInd][yInd][zInd]
>> could result in a bug that's very difficult to track down.
>
> When clarity is important, using xInd, yInd, zInd instead of just x,y,z,
> size_t instead of int (and declaring those inside instead of outside the
> loops), and those long expressions for the bounds of each dimension, have a
> bigger impact, imo, than adding an extra test.
I agree about xInd, yInd, and zInd. I disagree about size_t. And I
find declaring the indices inside the loops to be substantially
clearer than declaring them separately (assuming your compiler
supports that feature, of course).
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
Keith
|
4/28/2010 8:13:47 PM
|
|
Phil Carmody <thefatphil_demunged@yahoo.co.uk> wrote:
> "Daniel T." <daniel_t@earthlink.net> writes:
> > Phil Carmody <thefatphil_demunged@yahoo.co.uk> wrote:
> > > "Daniel T." <daniel_t@earthlink.net> writes:
> > >
> > > > The debate is not the false dichotomy that some try to make it
> > > > out to be.
> > >
> > > It's odd that you appear to have attempted to push it towards a
> > > dichotomy with the above.
> >
> > Not at all. I specifically picked strychnine because it is something
> > that can be taken (but it's far from common.) I am simply pointing
> > out that there are degrees, and the debate is about degrees, not
> > about throwing a switch.
> >
> > Three examples have been presented using your analogy, water, salt,
> > and strychnine. The question is, which is goto more like? The
> > question isn't "whether" goto is safe to use, but "how safe is it."
> > Are better alternatives available?
>
> IMHO, if you're deep in the linux kernel or its drivers, then it's
> salt. You really don't want much, but some is almost always necessary,
> and then it's definitely better than the lack thereof.
>
> If you're in some bloaty multi-layered, multi-libraried userspace
> program, then it's strychnine. If you're pretending to obsess about
> the extra efficiency goto gives you, you're missing the point.
>
> If it's water, and you're awash with gotos, then you're in the wrong
> language.
Good point. Maybe that is why Dijkstra called goto "low level."
|
|
0
|
|
|
|
Reply
|
Daniel
|
4/28/2010 10:49:38 PM
|
|
In alt.lang.asm Nathan Baker <nathancbaker@gmail.com> wrote in part:
> "Robert Redelmeier" <redelm@ev1.net.invalid> wrote in message
> news:hr8ak7$vhk$1@speranza.aioe.org...
>>
>> modes. Less if you are desparately counting cycles on an 8088
>> (jmp saves a jmp after the ret).
>
> Don't you mean that a 'jmp' saves a 'ret' after a 'ret'??
No. This is the code I'm contemplating:
# other startup code
keyloop:
# wait/get keycode, error check and adjust
jmp [ebx]
A_code:
# instructions to execute cmd "A"
jmp keyloop
B_code: .......
>
> For nested calls, the final call can be replaced by a jmp. E.g.:
SOunds like that'll misalign the ESP stack and the hw call/ret stack.
-- Robert
|
|
0
|
|
|
|
Reply
|
redelm (106)
|
4/29/2010 12:47:50 AM
|
|
On 28 Apr, 13:59, "Daniel T." <danie...@earthlink.net> wrote:
> In article
> <dbac22e7-4667-485e-b829-2505e2bd9...@q23g2000yqd.googlegroups.com>,
> =A0SG <s.gesem...@gmail.com> wrote:
> > On 28 Apr., 11:02, Richard Heathfield wrote:
> > > Juha Nieminen wrote:
<snip>
> > > > Value_t* MyClass::findValue(const Value_t& value)
> > > > {
> > > > for(size_t xInd =3D 0; xInd < data.size(); ++xInd)
> > > > for(size_t yInd =3D 0; yInd < data[xInd].size(); ++yInd)
> > > > for(size_t zInd =3D 0; zInd < data[xInd][yInd].size(); ++zInd)
> > > > {
> > > > if(data[xInd][yInd][zInd] =3D=3D value)
> > > > return &data[xInd][yInd][zInd];
> > > > }
> > > > return 0;
> > > > }
> >
> > > In any case, your loop condition expressions do not correctly describ=
e
> > > the conditions under which the loop will terminate.
>
> > This was probably intentional. Expressing it "correctly" forces you to
> > write slightly more comprex loop conditions which contain some kind of
> > "i'm done"-flag like this:
>
> > =A0 Value_t* MyClass::findValue(const Value_t& value)
> > =A0 {
> > =A0 =A0 Value_t* result =3D 0;
> > =A0 =A0 for(size_t xInd =3D 0; !result && xInd < data.size(); ++xInd)
> > =A0 =A0 =A0 for(size_t yInd =3D 0; !result && yInd < data[xInd].size();
> > =A0 =A0 =A0 =A0 =A0 ++yInd)
> > =A0 =A0 =A0 =A0 for(size_t zInd =3D 0; !result && zInd < data[xInd]
> > [yInd].size();
> > =A0 =A0 =A0 =A0 =A0 =A0 ++zInd)
> > =A0 =A0 =A0 =A0 {
> > =A0 =A0 =A0 =A0 =A0 if(data[xInd][yInd][zInd] =3D=3D value)
> > =A0 =A0 =A0 =A0 =A0 =A0 result =3D &data[xInd][yInd][zInd];
> > =A0 =A0 =A0 =A0 }
> > =A0 =A0 return result;
> > =A0 }
>
> > I don't know about you but I like the first version better. It's more
> > concise. I find it easier to see what the loop's doing. Maybe it's
> > just me. I guess I'm used to these kinds of loops.
>
> Since the sample code is obviously in c++, I would rather see something
> like:
>
> Iterator it =3D data.begin()
> while(it !=3D data.end() && *it !=3D value)
> =A0 =A0++it;
> return it !=3D data.end();
is a for-loop regarded as poor style in C++?
for (Iterator it =3D data.begin(); it !=3D data.end() && *it !=3D value; +
+it)
;
--
"Perilous to us all are the devices of an art deeper than we possess
ourselves."
Gandalf The Grey (discussing Template Meta-programming)
|
|
0
|
|
|
|
Reply
|
Nick
|
4/29/2010 8:03:00 AM
|
|
Keith H Duggar <duggar@alum.mit.edu> writes:
> On Apr 24, 6:41 pm, James Kanze <james.ka...@gmail.com> wrote:
>> On Apr 24, 5:12 pm, "Daniel T." <danie...@earthlink.net> wrote:
>>
>> > "Leigh Johnston" <le...@i42.co.uk> wrote:
>>
>> [...]
>>
>> > In C and C++, goto is sufficiently restricted that as long as
>> > your functions are small, it is largely harmless.
>>
>> In C and C++, if your functions are small enough, goto is
>> largely harmless. And also useless. All of the examples I've
>> seen defending goto introduce excessively complex functions in
>> order to justify it.
>
> The Kuzmin circle tracing algorithm is certainly not "excessively
> complex" and is an (elegant) example of goto being /necessary/ to
> to provide the optimal solution in some very real and important
> scenarios. There was a moderated flame war about this nine months
> ago culminating with these final posts
>
> http://groups.google.com/group/comp.lang.c++.moderated/msg/3ac2368e485e740d
> http://groups.google.com/group/comp.lang.c++.moderated/msg/5beca2fac77f7ab9
>
> that empirically proved beyond any contestation at the time that
> the goto version was optimal in some scenarios. All the source
> code, scripts, etc are still available at
>
> http://www.duggar.org/pub/code/circle/
>
> to anyone who wishes to /rationally/ challenge the results with
> empirical evidence. Otherwise continued unconditional anti-goto
> preaching is simply anti-intellectual religion and certainly not
> computer science.
Good of you to make this available. I do have some other comments
further down, but I think the effort and general approach should be
applauded.
> [snip]
>
> Finally, if you do try and measure results note that the provided
> code takes exceptional care when it comes to certain things that
> to the naive might seem unimportant such as removal of constants,
> randomization, control of inlining, avoidance of monolithic
> compilation, etc. That is all /necessary/ for accurate profiling
> which can be tricky to say the least. That was one source of the
> disagreement in that original thread, ie one participant who
> thought he was "all that" was simply ignorant of many of those
> real world profiling and measurement considerations.
Some comments and suggestions --
Good points: The measurement methodology looks fairly good. The
things you mention certainly can have large effects on performance.
It might be good to report results also for different optimization
levels (because different algorithms respond differently to different
levels of optimization, and it's good to know what those differences
are).
Bad points: The output is baffling. No labels on the columns,
no units shown for the different measurements. What is being
measured exactly, and what do the different columns represent?
The output should say, in English that is at least decipherable.
Missing (?) points: It isn't clear what ranges of radius values
are being measured. In this kind of measurement it's valuable to
see results for several restricted ranges of argument values (say
1-10, 10-50, 50-250, 500+), as well as several weighted averages.
Perhaps some of these different possibilities are shown, the
unlabelled output makes it difficult to tell (and one should
never have to rummage around in the source code to discover such
things).
Returning to the algorithm... Clearly it's a clever person who
devised the algorithm. Is it excessively complex? Maybe not,
but it isn't excessively simple either. To say that another way,
although it's easy in some sense to see what it's doing, it's
harder to say how it works or why. For reference I am talking
about circle0 (shown as in the original except for some white
space changes, and leaving out 'inline'):
int
circle0( int r ){
int x = r;
int y = 0;
int e = - r / 2;
if( r & 1 ){ --e; goto odd; }
even:
if( y >= x ) return y+1;
e += y++;
if( e >= 0 ) e -= --x;
odd:
if( y >= x ) return y+1;
e += ++y;
if( e >= 0 ) e -= --x;
goto even;
}
There's a much simpler way of coding this algorithm (ie, one that
goes through the same sequence of x,y values):
int
circle_simple( int r ){
int x = r;
int y = 0;
int e = -r;
while(1){
if( y >= x ) return y+1;
e += y+y+1, y++;
if( e >= 0 ) x--, e -= x+x;
}
}
In my measurements circle_simple performed better than circle0 by
between 1 and 8 percent (for large radius values), and by larger
amounts, up to 25 percent, for smaller radius values. Of course,
YMMV, and I'm sure it will in other environments, but certainly
this simpler algorithm is at least competitive performance wise.
(The smaller code footprint is another plus.) Given that, the
argument that using goto is necessary here seems a little bit
overstated.
> Subsequently I discussed that flame war with one of the worlds
> genius compiler writers who confirmed the necessity of the inlining
> etc controls explained above. However, he also added that in his
> experience it is pointless to argue with the anti-goto mob because
> it is a religion that ignores all inconvenient empirical evidence.
Essentially the same thing could be said of the pro-goto mob.
P.S. I've kept the original set of newsgroups even though I
don't read most of them.
|
|
0
|
|
|
|
Reply
|
Tim
|
4/29/2010 8:20:25 AM
|
|
Bo Persson wrote:
> Seebs wrote:
>> On 2010-04-25, Andrew Poelstra <apoelstra@localhost.localdomain>
>> wrote:
>>> I often see code like
>>> if(setup1() == 0)
>>> goto fail;
>>>
>>> if(setup2() == 0)
>>> goto fail;
>>>
>>> if(setup3() == 0)
>>> goto fail;
>>>
>>> /* now do stuff */
>>>
>>> return 0;
>>> fail:
>>> /* :( */
>>> return 1;
>>> Personally, I would do this as:
>>>
>>> if(setup1() &&
>>> setup2() &&
>>> setup3()) {
>>> /* now do stuff */
>>> return 0;
>>> }
>>> else {
>>> /* :( */
>>> return 1;
>>> }
>>> But from a stylistic view, the first version doesn't seem all
>>> that bad. I see it a lot and it doesn't bother me, anyway.
>> It gets worse when there's non-trivial work which needs to be done
>> between the various setup(), and/or they have to interact with more
>> than one or two local variables. There's also the fairly common
>> idiom:
>>
>> if (setup1())
>> goto fail;
>>
>> if (setup2())
>> goto teardown1;
>>
>> if (setup3())
>> goto teardown2;
>>
>> /* various stuff */
>> if (something_went_wrong)
>> goto teardown3;
>> /* more stuff */
>>
>> teardown3:
>> teardown3();
>> teardown2:
>> teardown2();
>> teardown1:
>> teardown1();
>> fail:
>> return -1;
>>
>> This has the advantage that, if later you need to add a setup2_5(),
>> you don't have to go to multiple different places later in the code
>> and add a teardown2_5().
>>
>> In general, I find that overly dogmatic structuring tends to reduce
>> readability. The "obvious" alternative to the above:
>>
>> if (!setup1()) {
>> if (!setup2()) {
>> if (!setup3()) {
>> /* various stuff */
>> if (!something_went_wrong) {
>> /* more stuff */
>> }
>> teardown3();
>> }
>> teardown2();
>> }
>> teardown1();
>> }
>>
>> is, IMHO, less readable and less maintainable. It's harder to track
>> where you are by looking at indentation, and there's less room on a
>> default-width screen for writing clear code inside /* more stuff */.
>>
>> -s
>
> Guess why C++ added destructors to automatically destroy objects that
> go out of scope.
>
And exceptions :D
|
|
0
|
|
|
|
Reply
|
Vladimir
|
4/29/2010 9:24:05 AM
|
|
Nick Keighley <nick_keighley_nospam@hotmail.com> wrote:
> On 28 Apr, 13:59, "Daniel T." <danie...@earthlink.net> wrote:
> > �SG <s.gesem...@gmail.com> wrote:
> > > On 28 Apr., 11:02, Richard Heathfield wrote:
> > > > Juha Nieminen wrote:
>
> <snip>
>
> > > > > Value_t* MyClass::findValue(const Value_t& value)
> > > > > {
> > > > > for(size_t xInd = 0; xInd < data.size(); ++xInd)
> > > > > for(size_t yInd = 0; yInd < data[xInd].size(); ++yInd)
> > > > > for(size_t zInd = 0; zInd < data[xInd][yInd].size(); ++zInd)
> > > > > {
> > > > > if(data[xInd][yInd][zInd] == value)
> > > > > return &data[xInd][yInd][zInd];
> > > > > }
> > > > > return 0;
> > > > > }
> > >
> > > > In any case, your loop condition expressions do not correctly describe
> > > > the conditions under which the loop will terminate.
> >
> > > This was probably intentional. Expressing it "correctly" forces you to
> > > write slightly more comprex loop conditions which contain some kind of
> > > "i'm done"-flag like this:
> >
> > > � Value_t* MyClass::findValue(const Value_t& value)
> > > � {
> > > � � Value_t* result = 0;
> > > � � for(size_t xInd = 0; !result && xInd < data.size(); ++xInd)
> > > � � � for(size_t yInd = 0; !result && yInd < data[xInd].size();
> > > � � � � � ++yInd)
> > > � � � � for(size_t zInd = 0; !result && zInd < data[xInd]
> > > [yInd].size();
> > > � � � � � � ++zInd)
> > > � � � � {
> > > � � � � � if(data[xInd][yInd][zInd] == value)
> > > � � � � � � result = &data[xInd][yInd][zInd];
> > > � � � � }
> > > � � return result;
> > > � }
> >
> > > I don't know about you but I like the first version better. It's more
> > > concise. I find it easier to see what the loop's doing. Maybe it's
> > > just me. I guess I'm used to these kinds of loops.
> >
> > Since the sample code is obviously in c++, I would rather see something
> > like:
> >
> > Iterator it = data.begin()
> > while(it != data.end() && *it != value)
> > � �++it;
> > return it != data.end();
>
> is a for-loop regarded as poor style in C++?
>
> for (Iterator it = data.begin(); it != data.end() && *it != value; +
> +it)
> ;
No, but I consider an empty statement poor style. In this specific case,
I can't help but wonder what you were planning on returning since you
throw away the result. 'it' doesn't live outside the for loop in C++.
The point of my example was to show that the problem with Juha's code
wasn't that it had multiple exits, but rather that it was at the wrong
level of abstraction and therefore seemed to need multiple exits.
Richard, removed the multiple exits without fixing the abstraction
problem and he ended up with a worse result.
|
|
0
|
|
|
|
Reply
|
Daniel
|
4/29/2010 11:51:19 AM
|
|
Tim Rentsch <txr@alumni.caltech.edu> wrote:
> Keith H Duggar <duggar@alum.mit.edu> writes:
>
> > ... he also added that in his experience it is pointless to argue
> > with the anti-goto mob because it is a religion that ignores all
> > inconvenient empirical evidence.
>
> Essentially the same thing could be said of the pro-goto mob.
I think there are few people that are either anti-, or pro-, goto (and I
try to avoid discussing the issue with those types of people.)
To me 'goto' is very powerful, versatile tool. As the person who started
this thread pointed out, programs can be written using goto instead of
loops, exceptions and functions, and a whole host of other specialized
control flow features that some languages possess. However, it is that
versatility that makes things difficult. When goto is used, it can
sometimes be confusing to the reader what the writer was trying to
accomplish.
As an analogy, if I am using a screwdriver, you can be sure that I am
trying to turn a screw, if I am using a can opener you can be sure I'm
trying to open a can, but if I'm using a swiss army knife, you can't be
sure what it is I'm trying to accomplish without further study. However,
if a corkscrew isn't available, then the swiss army knife is invaluable.
|
|
0
|
|
|
|
Reply
|
daniel_t (1960)
|
4/29/2010 12:57:35 PM
|
|
Keith Thompson wrote:
> Jeff Flinn <TriumphSprint2000@hotmail.com> writes:
>> Keith Thompson wrote:
>>> Seebs <usenet-nospam@seebs.net> writes:
>>>> On 2010-04-28, bart.c <bartc@freeuk.com> wrote:
>>>>> int* findvalue(int value)
>>>>> {int *a=0;
>>>>>
>>>>> for(int xInd = 0; !a && xInd < datasize; ++xInd)
>>>>> for(int yInd = 0; !a && yInd < dataxindsize; ++yInd)
>>>>> for(int zInd = 0; !a && zInd < dataxindyindsize; ++zInd)
>>>>> {
>>>>> if(data[xInd][yInd][zInd] == value)
>>>>> a=&data[xInd][yInd][zInd];
>>>>> }
>>>>>
>>>>> return a;
>>>>> }
>>>> This is noticably slower and less clear. I would not consider it
>>>> an acceptable rewrite -- but I would consider the other form a good
>>>> rewrite of it.
>>> I mostly agree, but -- "noticably slower"? How did you notice?
>> Certainly is for the case data[0][0][0] == value. ;-)
>
> How so?
>
> I'm not arguing that it's not *likely* to be slower, but (a) it's not
> likely to be *noticeably* slower unless the entire loop is executed many
> many times, and (b) it might not be slower at all, depending on how
> clever the compiler is.
>
> (I'm assuming there's not some semantic difference that I haven't
> noticed.)
Have you profiled your 'assign address' version versus the previous
'return when found' version? For different sizes? The 'assign address'
version is effectively doing a std::for_each, alway visiting every
element even if the item found is the 1st one. The 'return when found'
version is analogous to std::find_if. For the case data[0][0][0] ==
value, your algorithm is O(N), while find_if, is O(1).
Jeff
|
|
0
|
|
|
|
Reply
|
Jeff
|
4/29/2010 1:25:19 PM
|
|
Jeff Flinn <TriumphSprint2000@hotmail.com> writes:
> Keith Thompson wrote:
>> Jeff Flinn <TriumphSprint2000@hotmail.com> writes:
>>> Keith Thompson wrote:
>>>> Seebs <usenet-nospam@seebs.net> writes:
>>>>> On 2010-04-28, bart.c <bartc@freeuk.com> wrote:
>>>>>> int* findvalue(int value)
>>>>>> {int *a=0;
>>>>>>
>>>>>> for(int xInd = 0; !a && xInd < datasize; ++xInd)
>>>>>> for(int yInd = 0; !a && yInd < dataxindsize; ++yInd)
>>>>>> for(int zInd = 0; !a && zInd < dataxindyindsize; ++zInd)
>>>>>> {
>>>>>> if(data[xInd][yInd][zInd] == value)
>>>>>> a=&data[xInd][yInd][zInd];
>>>>>> }
>>>>>>
>>>>>> return a;
>>>>>> }
>>>>> This is noticably slower and less clear. I would not consider it
>>>>> an acceptable rewrite -- but I would consider the other form a good
>>>>> rewrite of it.
>>>> I mostly agree, but -- "noticably slower"? How did you notice?
>>> Certainly is for the case data[0][0][0] == value. ;-)
>>
>> How so?
>>
>> I'm not arguing that it's not *likely* to be slower, but (a) it's not
>> likely to be *noticeably* slower unless the entire loop is executed many
>> many times, and (b) it might not be slower at all, depending on how
>> clever the compiler is.
>>
>> (I'm assuming there's not some semantic difference that I haven't
>> noticed.)
>
> Have you profiled your 'assign address' version versus the previous
> 'return when found' version? For different sizes? The 'assign address'
> version is effectively doing a std::for_each, alway visiting every
> element even if the item found is the 1st one. The 'return when found'
> version is analogous to std::find_if. For the case data[0][0][0] ==
> value, your algorithm is O(N), while find_if, is O(1).
Please look again. I'm fairly sure that all the versions I've seen in
this thread terminate after finding the item.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
Keith
|
4/29/2010 4:12:06 PM
|
|
Keith Thompson <kst-u@mib.org> writes:
> Seebs <usenet-nospam@seebs.net> writes:
>> On 2010-04-28, bart.c <bartc@freeuk.com> wrote:
>>> int* findvalue(int value)
>>> {int *a=0;
>>>
>>> for(int xInd = 0; !a && xInd < datasize; ++xInd)
>>> for(int yInd = 0; !a && yInd < dataxindsize; ++yInd)
>>> for(int zInd = 0; !a && zInd < dataxindyindsize; ++zInd)
>>> {
>>> if(data[xInd][yInd][zInd] == value)
>>> a=&data[xInd][yInd][zInd];
>>> }
>>>
>>> return a;
>>> }
>>
>> This is noticably slower and less clear. I would not consider it
>> an acceptable rewrite -- but I would consider the other form a good
>> rewrite of it.
>
> I mostly agree, but -- "noticably slower"? How did you notice?
Certainly a /lot/ slower if the "sizes" are large, data[0][0][0] is 0 and
the search value is zero ...
--
Online waterways route planner | http://canalplan.eu
Plan trips, see photos, check facilities | http://canalplan.org.uk
|
|
0
|
|
|
|
Reply
|
Nick
|
4/29/2010 6:26:00 PM
|
|
Keith Thompson <kst-u@mib.org> writes:
> Jeff Flinn <TriumphSprint2000@hotmail.com> writes:
>> Keith Thompson wrote:
>>> Jeff Flinn <TriumphSprint2000@hotmail.com> writes:
>>>> Keith Thompson wrote:
>>>>> Seebs <usenet-nospam@seebs.net> writes:
>>>>>> On 2010-04-28, bart.c <bartc@freeuk.com> wrote:
>>>>>>> int* findvalue(int value)
>>>>>>> {int *a=0;
>>>>>>>
>>>>>>> for(int xInd = 0; !a && xInd < datasize; ++xInd)
>>>>>>> for(int yInd = 0; !a && yInd < dataxindsize; ++yInd)
>>>>>>> for(int zInd = 0; !a && zInd < dataxindyindsize; ++zInd)
>>>>>>> {
>>>>>>> if(data[xInd][yInd][zInd] == value)
>>>>>>> a=&data[xInd][yInd][zInd];
>>>>>>> }
>>>>>>>
>>>>>>> return a;
>>>>>>> }
>>>>>> This is noticably slower and less clear. I would not consider it
>>>>>> an acceptable rewrite -- but I would consider the other form a good
>>>>>> rewrite of it.
>>>>> I mostly agree, but -- "noticably slower"? How did you notice?
>>>> Certainly is for the case data[0][0][0] == value. ;-)
>>>
>>> How so?
>>>
>>> I'm not arguing that it's not *likely* to be slower, but (a) it's not
>>> likely to be *noticeably* slower unless the entire loop is executed many
>>> many times, and (b) it might not be slower at all, depending on how
>>> clever the compiler is.
>>>
>>> (I'm assuming there's not some semantic difference that I haven't
>>> noticed.)
>>
>> Have you profiled your 'assign address' version versus the previous
>> 'return when found' version? For different sizes? The 'assign address'
>> version is effectively doing a std::for_each, alway visiting every
>> element even if the item found is the 1st one. The 'return when found'
>> version is analogous to std::find_if. For the case data[0][0][0] ==
>> value, your algorithm is O(N), while find_if, is O(1).
>
> Please look again. I'm fairly sure that all the versions I've seen in
> this thread terminate after finding the item.
Not when the item is zero, because that's the "nothing has been found
yet" flag, so the search executes to exhaustion even if the item was
found hours ago.
--
Online waterways route planner | http://canalplan.eu
Plan trips, see photos, check facilities | http://canalplan.org.uk
|
|
0
|
|
|
|
Reply
|
Nick
|
4/29/2010 6:27:09 PM
|
|
Nick <3-nospam@temporary-address.org.uk> writes:
> Keith Thompson <kst-u@mib.org> writes:
>> Jeff Flinn <TriumphSprint2000@hotmail.com> writes:
>>> Keith Thompson wrote:
>>>> Jeff Flinn <TriumphSprint2000@hotmail.com> writes:
>>>>> Keith Thompson wrote:
>>>>>> Seebs <usenet-nospam@seebs.net> writes:
>>>>>>> On 2010-04-28, bart.c <bartc@freeuk.com> wrote:
>>>>>>>> int* findvalue(int value)
>>>>>>>> {int *a=0;
>>>>>>>>
>>>>>>>> for(int xInd = 0; !a && xInd < datasize; ++xInd)
>>>>>>>> for(int yInd = 0; !a && yInd < dataxindsize; ++yInd)
>>>>>>>> for(int zInd = 0; !a && zInd < dataxindyindsize; ++zInd)
>>>>>>>> {
>>>>>>>> if(data[xInd][yInd][zInd] == value)
>>>>>>>> a=&data[xInd][yInd][zInd];
>>>>>>>> }
>>>>>>>>
>>>>>>>> return a;
>>>>>>>> }
>>>>>>> This is noticably slower and less clear. I would not consider it
>>>>>>> an acceptable rewrite -- but I would consider the other form a good
>>>>>>> rewrite of it.
>>>>>> I mostly agree, but -- "noticably slower"? How did you notice?
>>>>> Certainly is for the case data[0][0][0] == value. ;-)
>>>>
>>>> How so?
>>>>
>>>> I'm not arguing that it's not *likely* to be slower, but (a) it's not
>>>> likely to be *noticeably* slower unless the entire loop is executed many
>>>> many times, and (b) it might not be slower at all, depending on how
>>>> clever the compiler is.
>>>>
>>>> (I'm assuming there's not some semantic difference that I haven't
>>>> noticed.)
>>>
>>> Have you profiled your 'assign address' version versus the previous
>>> 'return when found' version? For different sizes? The 'assign address'
>>> version is effectively doing a std::for_each, alway visiting every
>>> element even if the item found is the 1st one. The 'return when found'
>>> version is analogous to std::find_if. For the case data[0][0][0] ==
>>> value, your algorithm is O(N), while find_if, is O(1).
>>
>> Please look again. I'm fairly sure that all the versions I've seen in
>> this thread terminate after finding the item.
>
> Not when the item is zero, because that's the "nothing has been found
> yet" flag, so the search executes to exhaustion even if the item was
> found hours ago.
No, the loops test for ``!a''. ``a'' is a pointer, initialized to 0
(NULL). ``data'' is presumably a 3-D array of int. When the item
is found, a is set to point to the item; even if the item's value
is 0, a is still non-zero (non-NULL).
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
Keith
|
4/29/2010 7:45:59 PM
|
|
Nick <3-nospam@temporary-address.org.uk> writes:
> Keith Thompson <kst-u@mib.org> writes:
>
>> Jeff Flinn <TriumphSprint2000@hotmail.com> writes:
>>> Keith Thompson wrote:
>>>> Jeff Flinn <TriumphSprint2000@hotmail.com> writes:
>>>>> Keith Thompson wrote:
>>>>>> Seebs <usenet-nospam@seebs.net> writes:
>>>>>>> On 2010-04-28, bart.c <bartc@freeuk.com> wrote:
>>>>>>>> int* findvalue(int value)
>>>>>>>> {int *a=0;
>>>>>>>>
>>>>>>>> for(int xInd = 0; !a && xInd < datasize; ++xInd)
>>>>>>>> for(int yInd = 0; !a && yInd < dataxindsize; ++yInd)
>>>>>>>> for(int zInd = 0; !a && zInd < dataxindyindsize; ++zInd)
>>>>>>>> {
>>>>>>>> if(data[xInd][yInd][zInd] == value)
>>>>>>>> a=&data[xInd][yInd][zInd];
>>>>>>>> }
>>>>>>>>
>>>>>>>> return a;
>>>>>>>> }
>>>>>>> This is noticably slower and less clear. I would not consider it
>>>>>>> an acceptable rewrite -- but I would consider the other form a good
>>>>>>> rewrite of it.
>>>>>> I mostly agree, but -- "noticably slower"? How did you notice?
>>>>> Certainly is for the case data[0][0][0] == value. ;-)
>>>>
>>>> How so?
>>>>
>>>> I'm not arguing that it's not *likely* to be slower, but (a) it's not
>>>> likely to be *noticeably* slower unless the entire loop is executed many
>>>> many times, and (b) it might not be slower at all, depending on how
>>>> clever the compiler is.
>>>>
>>>> (I'm assuming there's not some semantic difference that I haven't
>>>> noticed.)
>>>
>>> Have you profiled your 'assign address' version versus the previous
>>> 'return when found' version? For different sizes? The 'assign address'
>>> version is effectively doing a std::for_each, alway visiting every
>>> element even if the item found is the 1st one. The 'return when found'
>>> version is analogous to std::find_if. For the case data[0][0][0] ==
>>> value, your algorithm is O(N), while find_if, is O(1).
>>
>> Please look again. I'm fairly sure that all the versions I've seen in
>> this thread terminate after finding the item.
>
> Not when the item is zero, because that's the "nothing has been found
> yet" flag, so the search executes to exhaustion even if the item was
> found hours ago.
The variable 'a' is a pointer. The test in the for() loops is
'!a', not '!*a'.
|
|
0
|
|
|
|
Reply
|
Tim
|
4/29/2010 8:07:33 PM
|
|
Keith Thompson <kst-u@mib.org> writes:
> Nick <3-nospam@temporary-address.org.uk> writes:
>> Keith Thompson <kst-u@mib.org> writes:
>>> Jeff Flinn <TriumphSprint2000@hotmail.com> writes:
>>>> Keith Thompson wrote:
>>>>> Jeff Flinn <TriumphSprint2000@hotmail.com> writes:
>>>>>> Keith Thompson wrote:
>>>>>>> Seebs <usenet-nospam@seebs.net> writes:
>>>>>>>> On 2010-04-28, bart.c <bartc@freeuk.com> wrote:
>>>>>>>>> int* findvalue(int value)
>>>>>>>>> {int *a=0;
>>>>>>>>>
>>>>>>>>> for(int xInd = 0; !a && xInd < datasize; ++xInd)
>>>>>>>>> for(int yInd = 0; !a && yInd < dataxindsize; ++yInd)
>>>>>>>>> for(int zInd = 0; !a && zInd < dataxindyindsize; ++zInd)
>>>>>>>>> {
>>>>>>>>> if(data[xInd][yInd][zInd] == value)
>>>>>>>>> a=&data[xInd][yInd][zInd];
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> return a;
>>>>>>>>> }
>>>>>>>> This is noticably slower and less clear. I would not consider it
>>>>>>>> an acceptable rewrite -- but I would consider the other form a good
>>>>>>>> rewrite of it.
>>>>>>> I mostly agree, but -- "noticably slower"? How did you notice?
>>>>>> Certainly is for the case data[0][0][0] == value. ;-)
>>>>>
>>>>> How so?
>>>>>
>>>>> I'm not arguing that it's not *likely* to be slower, but (a) it's not
>>>>> likely to be *noticeably* slower unless the entire loop is executed many
>>>>> many times, and (b) it might not be slower at all, depending on how
>>>>> clever the compiler is.
>>>>>
>>>>> (I'm assuming there's not some semantic difference that I haven't
>>>>> noticed.)
>>>>
>>>> Have you profiled your 'assign address' version versus the previous
>>>> 'return when found' version? For different sizes? The 'assign address'
>>>> version is effectively doing a std::for_each, alway visiting every
>>>> element even if the item found is the 1st one. The 'return when found'
>>>> version is analogous to std::find_if. For the case data[0][0][0] ==
>>>> value, your algorithm is O(N), while find_if, is O(1).
>>>
>>> Please look again. I'm fairly sure that all the versions I've seen in
>>> this thread terminate after finding the item.
>>
>> Not when the item is zero, because that's the "nothing has been found
>> yet" flag, so the search executes to exhaustion even if the item was
>> found hours ago.
>
> No, the loops test for ``!a''. ``a'' is a pointer, initialized to 0
> (NULL). ``data'' is presumably a 3-D array of int. When the item
> is found, a is set to point to the item; even if the item's value
> is 0, a is still non-zero (non-NULL).
Bloody hell, so it is. So I want to look for an integer, so I create a
pointer to look for it, just so that I can I use null as a distinct
signal value.
Of course, "a" was a particularly carefully chosen name to make this
clear.
And that's the better and clearer code? Yeah, right!
--
Online waterways route planner | http://canalplan.eu
Plan trips, see photos, check facilities | http://canalplan.org.uk
|
|
0
|
|
|
|
Reply
|
Nick
|
4/30/2010 5:46:29 AM
|
|
On Apr 29, 8:51=A0pm, "Daniel T." <danie...@earthlink.net> wrote:
> Nick Keighley <nick_keighley_nos...@hotmail.com> wrote:
> > On 28 Apr, 13:59, "Daniel T." <danie...@earthlink.net> wrote:
> > > =A0SG <s.gesem...@gmail.com> wrote:
> > > > On 28 Apr., 11:02, Richard Heathfield wrote:
> > > > =A0 Value_t* MyClass::findValue(const Value_t& value)
> > > > =A0 {
> > > > =A0 =A0 Value_t* result =3D 0;
> > > > =A0 =A0 for(size_t xInd =3D 0; !result && xInd < data.size(); ++xIn=
d)
> > > > =A0 =A0 =A0 for(size_t yInd =3D 0; !result && yInd < data[xInd].siz=
e();
> > > > =A0 =A0 =A0 =A0 =A0 ++yInd)
> > > > =A0 =A0 =A0 =A0 for(size_t zInd =3D 0; !result && zInd < data[xInd]
> > > > [yInd].size();
> > > > =A0 =A0 =A0 =A0 =A0 =A0 ++zInd)
> > > > =A0 =A0 =A0 =A0 {
> > > > =A0 =A0 =A0 =A0 =A0 if(data[xInd][yInd][zInd] =3D=3D value)
> > > > =A0 =A0 =A0 =A0 =A0 =A0 result =3D &data[xInd][yInd][zInd];
> > > > =A0 =A0 =A0 =A0 }
> > > > =A0 =A0 return result;
> > > > =A0 }
>
> > > > I don't know about you but I like the first version better. It's mo=
re
> > > > concise. I find it easier to see what the loop's doing. Maybe it's
> > > > just me. I guess I'm used to these kinds of loops.
>
> > > Since the sample code is obviously in c++, I would rather see somethi=
ng
> > > like:
>
> > > Iterator it =3D data.begin()
> > > while(it !=3D data.end() && *it !=3D value)
> > > =A0 =A0++it;
> > > return it !=3D data.end();
> [snip]
> The point of my example was to show that the problem with Juha's code
> wasn't that it had multiple exits, but rather that it was at the wrong
> level of abstraction and therefore seemed to need multiple exits.
> Richard, removed the multiple exits without fixing the abstraction
> problem and he ended up with a worse result.
That's a very insightful point, and in many ways good practice -
particularly if it prevents client code coupling to the implementation
or layout of your container. In this case though, the find function
might be a member of the container - inside the encapsulation - and
coupling quite acceptable. Further, say you want something just
marginally more complicated - like skipping every second value of
yInd: you can't do that with your iterator (the x/y/z boundaries are
lost), but it would be a trivial modification to the explicit loop.
Localisation, concision, directness and simplicity must be balanced
against abstraction - the latter is not always better. So, while I
agree an iterator may sometimes be good, I strongly disagree that the
explicitly nested loops were inherently at the wrong level of
abstraction, yielding a necessarily worse result.
Cheers,
Tony
|
|
0
|
|
|
|
Reply
|
tonydee
|
4/30/2010 8:58:10 AM
|
|
"Nick" <3-nospam@temporary-address.org.uk> wrote in message
news:878w854hmy.fsf@temporary-address.org.uk...
> Keith Thompson <kst-u@mib.org> writes:
>> No, the loops test for ``!a''. ``a'' is a pointer, initialized to 0
>> (NULL). ``data'' is presumably a 3-D array of int. When the item
>> is found, a is set to point to the item; even if the item's value
>> is 0, a is still non-zero (non-NULL).
>
> Bloody hell, so it is. So I want to look for an integer, so I create a
> pointer to look for it, just so that I can I use null as a distinct
> signal value.
Er, yes. Without being able to jump out of the loops, there aren't too many
alternatives. (Perhaps setting each index to the maximum bound, but in this
example the bound expressions were complex.)
Anyway, in this case, the return value from the function *was* a pointer to
the item.
> Of course, "a" was a particularly carefully chosen name to make this
> clear.
>
> And that's the better and clearer code? Yeah, right!
"a" is for "address"...
The claim was that removing the exit from the inner loop would result in a
"MASSIVE" loss of clarity.
However the for-loop was written in such a way, even my slightly streamlined
version, that a short variable like "a" might well get lost in the noise:
for(size_t zInd = 0; zInd < data[xInd][yInd].size(); ++zInd) /* original */
I if I had to write such a loop, in C-style, and in the context of a 10-line
function called "findvalue", it might look like:
for (z=0; z<zsize; ++z)
with zsize set outside the loops. (But then, I wouldn't be bothered myself
about using return, break or goto.)
--
Bartc
|
|
0
|
|
|
|
Reply
|
bart
|
4/30/2010 9:49:29 AM
|
|
On Apr 26, 9:46=A0am, "io_x" <a...@b.c.invalid> wrote:
> > Except that GOTO is a HLL keyword and I'm Asmist and
> > more machine-code oriented than concerned about needs
> > within abstract structured HLL-compilers, I see nothing
> > wrong with GOTO as long it does what a programmer want.
>
> you see all jmp, je, jc etc etc for me they are all gotos
A conditional jump is predicated instruction. I don't see anything
predicative in a goto statement, which isn't to say that the
similarity couldn't be deceiving without thinking about the
differences.
Hmmm.. so anything that changes the IP is a goto? By this defition
"NOP" would be a goto. Actually, this whole thread is glorious waste
of time, seriously guys.. this needs to be asked: WHAT THE FUCK!?!??
|
|
0
|
|
|
|
Reply
|
hanukas
|
4/30/2010 1:06:41 PM
|
|
tonydee <tony_in_da_uk@yahoo.co.uk> wrote:
> On Apr 29, 8:51�pm, "Daniel T." <danie...@earthlink.net> wrote:
> > Nick Keighley <nick_keighley_nos...@hotmail.com> wrote:
> > > On 28 Apr, 13:59, "Daniel T." <danie...@earthlink.net> wrote:
> > > > �SG <s.gesem...@gmail.com> wrote:
> > > > > On 28 Apr., 11:02, Richard Heathfield wrote:
> > > > >
> > > > > � Value_t* MyClass::findValue(const Value_t& value)
> > > > > � {
> > > > > � � Value_t* result = 0;
> > > > > � � for(size_t xInd = 0; !result && xInd < data.size(); ++xInd)
> > > > > � � � for(size_t yInd = 0; !result && yInd < data[xInd].size();
> > > > > � � � � � ++yInd)
> > > > > � � � � for(size_t zInd = 0; !result && zInd < data[xInd]
> > > > > [yInd].size();
> > > > > � � � � � � ++zInd)
> > > > > � � � � {
> > > > > � � � � � if(data[xInd][yInd][zInd] == value)
> > > > > � � � � � � result = &data[xInd][yInd][zInd];
> > > > > � � � � }
> > > > > � � return result;
> > > > > � }
> > > > >
> > > > > I don't know about you but I like the first version better. It's more
> > > > > concise. I find it easier to see what the loop's doing. Maybe it's
> > > > > just me. I guess I'm used to these kinds of loops.
> > > >
> > > > Since the sample code is obviously in c++, I would rather see something
> > > > like:
> > > >
> > > > Iterator it = data.begin()
> > > > while(it != data.end() && *it != value)
> > > > � �++it;
> > > > return it != data.end();
> > [snip]
> > The point of my example was to show that the problem with Juha's code
> > wasn't that it had multiple exits, but rather that it was at the wrong
> > level of abstraction and therefore seemed to need multiple exits.
> > Richard, removed the multiple exits without fixing the abstraction
> > problem and he ended up with a worse result.
>
> That's a very insightful point, and in many ways good practice -
> particularly if it prevents client code coupling to the implementation
> or layout of your container. In this case though, the find function
> might be a member of the container - inside the encapsulation - and
> coupling quite acceptable. Further, say you want something just
> marginally more complicated - like skipping every second value of
> yInd: you can't do that with your iterator (the x/y/z boundaries are
> lost), but it would be a trivial modification to the explicit loop.
> Localisation, concision, directness and simplicity must be balanced
> against abstraction - the latter is not always better. So, while I
> agree an iterator may sometimes be good, I strongly disagree that the
> explicitly nested loops were inherently at the wrong level of
> abstraction, yielding a necessarily worse result.
In this case, the nested for loops were the wrong level, even if the
code was embedded in a member function. For your, rather arbitrary,
modification they may not be, but even there an iterator that knows how
to skip every second value of yInd might be more appropriate IMHO (if
such a construct is needed once for this container type, it probably is
needed in other places and duplicating the nested for loop construct is
even worse than putting it in once.
That said, finding examples where multiple returns are a good idea is
not hard, even with the code I presented something like this:
for (Iterator it = data.begin(); it != data.end(); ++it)
if (*it == value)
return true;
return false;
Here I have removed the extra conditional by introducing an extra
return. It's not how I would write it, but the above is quite acceptable
IMHO.
There is a general pattern here I think. When there are multiple exit
conditions to a loop (there is an && in the exit condition,) and we have
to be able to distinguish after the loop which condition caused it to
exit, then it may be appropriate to have multiple exits from the loop.
I'm just musing here, but what do you guys think?
|
|
0
|
|
|
|
Reply
|
Daniel
|
4/30/2010 2:36:08 PM
|
|
"Daniel T." <daniel_t@earthlink.net> writes:
> There is a general pattern here I think. When there are multiple exit
> conditions to a loop (there is an && in the exit condition,) and we have
> to be able to distinguish after the loop which condition caused it to
> exit, then it may be appropriate to have multiple exits from the loop.
> I'm just musing here, but what do you guys think?
I'm very happy with it. My view is that leaving early is perfectly all
right in at least two circumstances:
a) in a "do I do this at all?" check at the start of some code
b) when you've finished what you came to do (like finding something in a
search function).
For (a), I'd much rather see
enum retval do_something(char *s) {
if(s == NULL)
return no_string;
if(!*s)
return empty_string;
if(strlen(s) < 3)
return short_string;
while(*s) {
if(....)
}
return not_found;
}
than something involving a pile of nested ifs and a variable to hold the
eventual return value. This way you *know* that all's over with,
without reading down to the bottom to check.
--
Online waterways route planner | http://canalplan.eu
Plan trips, see photos, check facilities | http://canalplan.org.uk
|
|
0
|
|
|
|
Reply
|
Nick
|
4/30/2010 6:41:38 PM
|
|
On 04/30/10 23:06, hanukas wrote:
> On Apr 26, 9:46 am, "io_x" <a...@b.c.invalid> wrote:
>>> Except that GOTO is a HLL keyword and I'm Asmist and
>>> more machine-code oriented than concerned about needs
>>> within abstract structured HLL-compilers, I see nothing
>>> wrong with GOTO as long it does what a programmer want.
>>
>> you see all jmp, je, jc etc etc for me they are all gotos
>
> A conditional jump is predicated instruction. I don't see anything
> predicative in a goto statement, which isn't to say that the
> similarity couldn't be deceiving without thinking about the
> differences.
>
> Hmmm.. so anything that changes the IP is a goto? By this defition
> "NOP" would be a goto. Actually, this whole thread is glorious waste
> of time, seriously guys.. this needs to be asked: WHAT THE FUCK!?!??
>
"mov eax, ebx" is a goto to the next machine instruction (ps: it has a
side effect of moving some arbitrary bits around in the memory, but
that's implementation detail, we don't care about that). So, ban mov!
|
|
0
|
|
|
|
Reply
|
Lie
|
4/30/2010 8:15:06 PM
|
|
"James Van Buskirk" <not_valid@comcast.net> wrote in message news:hr1q1g$h5v$1@news.eternal-september.org...
| "Alexei A. Frounze" <alexfrunews@gmail.com> wrote in message
| news:aab23e01-b4d4-44c4-a136-a619da00a3f7@m24g2000prc.googlegroups.com...
|
| > I wish there were distinct breaks for loops and switches as well as
| > multi-level breaks for nested loops. goto's at times are the least
| > evil since they don't require you to implement extra variables to
| > break out of nested loops and they help to simplify function cleanup
| > code (where resources are being freed on various conditions).
|
| Amusing that Fortran has a mechanism to break out of nested loops
| and permits one to use internal subroutines for function cleanup,
| not to mention no fall-through in SELECT CASE constructs.
Thank goodness.
| These uses
| of goto are simply artifacts of the limitations of C-style languages.
|
|
0
|
|
|
|
Reply
|
robin
|
5/1/2010 12:59:53 AM
|
|
On Apr 25, 1:54 am, Andrew Poelstra <apoels...@localhost.localdomain>
wrote:
> On 2010-04-24, James Kanze <james.ka...@gmail.com> wrote:
> > On Apr 24, 1:20 pm, "Leigh Johnston" <le...@i42.co.uk> wrote:
> >> "spinoza1111" <spinoza1...@yahoo.com> wrote in message
> >>news:051fa27d-5cf8-4f7e-94c8-e9e5b26566b7@g34g2000pro.googlegroups.com...
[...]
> > But when do you have to break out of a nested loop? (And of
> > course, the only valid use of break in C++ is to end a case in a
> > switch. Otherwise, it's just a goto in disguise.)
> This is just as true in C, according to some people (myself
> included). The only exception I can think of is when you are
> looping only to set the loop index to something.
> ie,
> for(i = 0; i < 10; ++i)
> if(arr[i].state = READY)
> break;
> /* now use arr[i], or if i is 10, indicate failure. */
> The alternative here, using the loop structure, would be:
> for(i = 0; i < 10 && arr[i].state != READY; ++i)
> ;
> /* now use arr[i], or if i is 10, indicate failure. */
> To me, the latter option looks horrific, plus if you swap the
> operands of &&, you get a very hard-to-spot overrun.
So don't swap them:-).
Seriously, the "standard" idiom is:
i = 0;
while (i < 10 && arr[i].state != READY)
++ i;
This idiom was developped in languages where for was a lot less
flexible, but in this particular case, I don't see any real
reason to switch to a for.
--
James Kanze
|
|
0
|
|
|
|
Reply
|
James
|
5/1/2010 1:16:51 AM
|
|
On Apr 25, 8:02 am, Juha Nieminen <nos...@thanks.invalid> wrote:
> In comp.lang.c++ red floyd <no.spam.h...@its.invalid> wrote:
> > As a purely stylistic matter, my empty loops always look like:
> > for ( begin_expr; test_expr; next_expr)
> > /* do nothing */ ;
> No, the proper way of writing an empty loop is:
> for(begin_expr; test_expr; next_expr) {}
> The empty block makes it explicitly clear that it's intended
> to be empty, and not just a typo. (The empty block could also
> be put in the next line, below the 'for', if so desired. A
> matter of style.)
I'd argue that it's more than just a question of style. What
the loop controls is on a line (or lines) after the loop, and if
it controls nothing, there should be a line which is clearly
"nothing". Either:
for (begin_expr; test_expr; next_expr)
;
or
for (begin_expr; test_expr; next_expr) {
}
(or whatever your coding guideline says with regards to the
placement of the braces).
--
James Kanze
|
|
0
|
|
|
|
Reply
|
James
|
5/1/2010 1:21:25 AM
|
|
On Apr 25, 8:53 am, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
> Juha Nieminen wrote:
[...]
> No, the proper way of writing an empty loop is:
> for(begin_expr; test_expr; next_expr) ;
> The semicolon makes it explicitly clear that it's intended to
> be empty, and not just a typo.
Of course, some (many? most?) shops would not put a space before
a semicolon.
I'd also recommend indenting the following line. (Only half a
:-), since I once used a C beautifier which did just that.)
--
James Kanze
|
|
0
|
|
|
|
Reply
|
James
|
5/1/2010 1:23:57 AM
|
|
On Apr 28, 8:26 am, Nick Keighley <nick_keighley_nos...@hotmail.com>
wrote:
> On 25 Apr, 08:02, Juha Nieminen <nos...@thanks.invalid> wrote:
[...]
> > The empty block makes it explicitly clear that it's intended to be empty,
> > and not just a typo. (The empty block could also be put in the next line,
> > below the 'for', if so desired. A matter of style.)
> for (begin_expr; test_expr; next_expr)
> ;
> is my usual form. And I cam across this and was taken with it
> for (begin_expr; test_expr; next_expr)
> continue;
> (the place I'd comtemplate a continue)
I'll bet the programmer who invented that one was an
ex-Fortran'er.
--
James Kanze
|
|
0
|
|
|
|
Reply
|
James
|
5/1/2010 1:26:14 AM
|
|
On Apr 25, 12:17 pm, Phil Carmody <thefatphil_demun...@yahoo.co.uk>
wrote:
> James Kanze <james.ka...@gmail.com> writes:
> > On Apr 24, 1:20 pm, "Leigh Johnston" <le...@i42.co.uk> wrote:
> >> "spinoza1111" <spinoza1...@yahoo.com> wrote in message
[...]
> >> Because break only breaks out of the innermost loop, using
> >> goto to break out of nested loops is one of the few sensible
> >> uses of goto.
> > But when do you have to break out of a nested loop?
> For the same reason you want to break out of a single loop.
> Do you have issues with people breaking out of single loops?
I've never really seen a case where it was appropriate (if by
"breaking out", you mean using the break statement to obfuscate
the code by hiding the actual program flow).
> > (And of course, the only valid use of break in C++ is to end
> > a case in a switch. Otherwise, it's just a goto in
> > disguise.)
> What do you mean by 'otherwise' - even that's just a goto in
> disguise?
Yes, because switch is fairly broken. On the other hand, the
language doesn't provide anything better. One of the most
structured programs I ever saw was full of goto's. Because it
was written in Fortran IV, and the language didn't provide any
of the necessary structures natively. In the case of C/C++,
about the only useful flow control structure that isn't provided
natively is a true switch or case statement, so we have to use
the one provided.
--
James Kanze
|
|
0
|
|
|
|
Reply
|
James
|
5/1/2010 1:31:53 AM
|
|
James Kanze wrote:
> On Apr 28, 8:26 am, Nick Keighley <nick_keighley_nos...@hotmail.com>
> wrote:
>> On 25 Apr, 08:02, Juha Nieminen <nos...@thanks.invalid> wrote:
>
> [...]
>>> The empty block makes it explicitly clear that it's intended to be empty,
>>> and not just a typo. (The empty block could also be put in the next line,
>>> below the 'for', if so desired. A matter of style.)
>
>> for (begin_expr; test_expr; next_expr)
>> ;
>
>> is my usual form. And I cam across this and was taken with it
>
>> for (begin_expr; test_expr; next_expr)
>> continue;
>
>> (the place I'd comtemplate a continue)
>
> I'll bet the programmer who invented that one was an
> ex-Fortran'er.
>
> --
> James Kanze
Fortran uses cycle to get to the end of a loop.
|
|
0
|
|
|
|
Reply
|
Sjouke
|
5/1/2010 1:57:51 AM
|
|
"Richard Heathfield" <rjh@see.sig.invalid>
>> Exactly how do you exit out of a set of nested loops with a "break"?
>
> I don't. I exit out of a set of nested loops using the conditions in the
> loop controllers.
Oh yeah, that is the very "cure" that is so much worse than the disease. And
very common too.
Old schools used to teach "assignment to data flow is same as goto to
control flow", just the former is ways harder to follow and mess up.
|
|
0
|
|
|
|
Reply
|
Balog
|
5/1/2010 5:58:59 AM
|
|
"hanukas" ha scritto nel messaggio:
--------------------
On Apr 26, 9:46 am, "io_x" <a...@b.c.invalid> wrote:
> > Except that GOTO is a HLL keyword and I'm Asmist and
> > more machine-code oriented than concerned about needs
> > within abstract structured HLL-compilers, I see nothing
> > wrong with GOTO as long it does what a programmer want.
>
> you see all jmp, je, jc etc etc for me they are all gotos
A conditional jump is predicated instruction. I don't see anything
predicative in a goto statement, which isn't to say that the
similarity couldn't be deceiving without thinking about the
differences.
Hmmm.. so anything that changes the IP is a goto? By this defition
"NOP" would be a goto. Actually, this whole thread is glorious waste
of time, seriously guys.. this needs to be asked: WHAT THE FUCK!?!??
--------------------
yes "je .1" would it mean "if zero flag == 1 goto .1";
"je" is a 'conditional' goto;
jmp is a goto.
|
|
0
|
|
|
|
Reply
|
io_x
|
5/1/2010 6:08:25 AM
|
|
io_x wrote:
....
> --------------------
> yes "je .1" would it mean "if zero flag == 1 goto .1";
> "je" is a 'conditional' goto;
> jmp is a goto.
Whereas "break", in my world, is an "OS thing" and has to do with
memory, not flow-control. I wanna use 'em both!
Best,
Frank
|
|
0
|
|
|
|
Reply
|
Frank
|
5/1/2010 6:36:21 AM
|
|
>"Tim Rentsch" <txr@alumni.caltech.edu>
>> Keith H Duggar <duggar@alum.mit.edu> writes:
>> Subsequently I discussed that flame war with one of the worlds
>> genius compiler writers who confirmed the necessity of the inlining
>> etc controls explained above. However, he also added that in his
>> experience it is pointless to argue with the anti-goto mob because
>> it is a religion that ignores all inconvenient empirical evidence.
Thir fairly match my experience.
> Essentially the same thing could be said of the pro-goto mob.
Not at all. To start, even the 'pro-goto', is a lie^W misstatement. One
camp tries to ban an element of language that hs proven good use. The othet
points out how stupid that ban is. It does not promote goto usage in
*general*. And start stating that cases where goto is called for are quite
rare in some languages (i.e. C++).
|
|
0
|
|
|
|
Reply
|
Balog
|
5/1/2010 7:28:25 AM
|
|
On Wed, 28 Apr 2010 05:18:41 +1000, Lie Ryan wrote:
> On 04/25/10 16:19, red floyd wrote:
>> On 4/24/2010 5:54 PM, Andrew Poelstra wrote:
>>
>>> The alternative here, using the loop structure, would be:
>>>
>>> for(i = 0; i< 10&& arr[i].state != READY; ++i)
>>> ;
>>> /* now use arr[i], or if i is 10, indicate failure. */
>>>
>>>
>> As a purely stylistic matter, my empty loops always look like:
>>
>>
>> for ( begin_expr; test_expr; next_expr)
>> /* do nothing */ ;
>>
>> That is, I always explicitly comment the empty loop so that it's clear
>> that I wanted the loop to be empty.
>>
>>
> Stylistically, I would put an empty { } to the side, containing a single
> space:
>
> for ( begin_expr; test_expr; next_expr) { }
>
> instead of semicolons. Most brace-language programmer would
> unconsciously filter out semicolons from the end of lines, while { } is
> much more visible since it's more unusual to open a block only to close
> it again.
Personally I tend to use:
for ( begin_expr; test_expr; next_expr) {;}
, which immediately makes clear that the empty loop is intended.
AvK
|
|
0
|
|
|
|
Reply
|
Moi
|
5/1/2010 8:24:28 AM
|
|
James Kanze <james.kanze@gmail.com> writes:
> On Apr 25, 8:02 am, Juha Nieminen <nos...@thanks.invalid> wrote:
>> In comp.lang.c++ red floyd <no.spam.h...@its.invalid> wrote:
>
>> > As a purely stylistic matter, my empty loops always look like:
>
>> > for ( begin_expr; test_expr; next_expr)
>> > /* do nothing */ ;
>
>> No, the proper way of writing an empty loop is:
>
>> for(begin_expr; test_expr; next_expr) {}
>
>> The empty block makes it explicitly clear that it's intended
>> to be empty, and not just a typo. (The empty block could also
>> be put in the next line, below the 'for', if so desired. A
>> matter of style.)
>
> I'd argue that it's more than just a question of style. What
> the loop controls is on a line (or lines) after the loop,
Bollocks. What the loop controls is the statement that follows
it. (Or in the case of a do-while, the statement between the do
and the while.) By the time the C parser is interpreting the
loop construct, there's no such thing as a 'line'.
You're addressing _nothing_ but style, stop pretending otherwise.
However, thanks for making me peek into the documentation itself,
I've discovered a horribly misleading sentence in the standard,
so shall propose a correction.
Phil
--
I find the easiest thing to do is to k/f myself and just troll away
-- David Melville on r.a.s.f1
|
|
0
|
|
|
|
Reply
|
Phil
|
5/1/2010 9:49:02 AM
|
|
In comp.lang.c++ Moi <root@invalid.address.org> wrote:
> Personally I tend to use:
>
> for ( begin_expr; test_expr; next_expr) {;}
>
> , which immediately makes clear that the empty loop is intended.
And causes a compiler warning due to a lone ';' if enough warning flags
are used.
What's wrong with {}?
|
|
0
|
|
|
|
Reply
|
Juha
|
5/1/2010 10:15:21 AM
|
|
On May 1, 12:49=A0pm, Phil Carmody <thefatphil_demun...@yahoo.co.uk>
wrote:
> James Kanze <james.ka...@gmail.com> writes:
> > On Apr 25, 8:02 am, Juha Nieminen <nos...@thanks.invalid> wrote:
> >> In comp.lang.c++ red floyd <no.spam.h...@its.invalid> wrote:
>
> >> > As a purely stylistic matter, my empty loops always look like:
>
> >> > for ( begin_expr; test_expr; next_expr)
> >> > =A0 =A0/* do nothing */ ;
>
> >> No, the proper way of writing an empty loop is:
>
> >> for(begin_expr; test_expr; next_expr) {}
>
> >> The empty block makes it explicitly clear that it's intended
> >> to be empty, and not just a typo. (The empty block could also
> >> be put in the next line, below the 'for', if so desired. A
> >> matter of style.)
>
> > I'd argue that it's more than just a question of style. =A0What
> > the loop controls is on a line (or lines) after the loop,
>
> Bollocks. What the loop controls is the statement that follows
> it. (Or in the case of a do-while, the statement between the do
> and the while.) By the time the C parser is interpreting the
> loop construct, there's no such thing as a 'line'.
>
> You're addressing _nothing_ but style, stop pretending otherwise.
Correct. Style is anyway extremely important. For example if to read
the posts in this group then some (like these of Kanze and Steinbach)
are very easy to read thanks to good style, even on occasions when the
information provided is incorrect or arguable.
Style is even more important for writings written in C++ (source
code), because C++ is never native tongue of writer.
> However, thanks for making me peek into the documentation itself,
> I've discovered a horribly misleading sentence in the standard,
> so shall propose a correction.
Which one?
|
|
0
|
|
|
|
Reply
|
ISO
|
5/1/2010 11:23:09 AM
|
|
"Balog Pal" <pasa@lib.hu> wrote:
> >"Tim Rentsch" <txr@alumni.caltech.edu>
> > > Keith H Duggar <duggar@alum.mit.edu> writes:
> > >
> > > Subsequently I discussed that flame war with one of the worlds
> > > genius compiler writers who confirmed the necessity of the
> > > inlining etc controls explained above. However, he also added that
> > > in his experience it is pointless to argue with the anti-goto mob
> > > because it is a religion that ignores all inconvenient empirical
> > > evidence.
>
> Thir fairly match my experience.
>
> > Essentially the same thing could be said of the pro-goto mob.
>
> Not at all. To start, even the 'pro-goto', is a lie^W misstatement.
> One camp tries to ban an element of language that hs proven good use.
> The othet points out how stupid that ban is. It does not promote
> goto usage in *general*. And start stating that cases where goto is
> called for are quite rare in some languages (i.e. C++).
No, one camp believes that goto is overused, while the other camp
insists that it is not. To my perception, nobody is trying to ban
anything. (If I'm wrong, maybe one of the proponents of banning goto
could respond?)
|
|
0
|
|
|
|
Reply
|
Daniel
|
5/1/2010 1:49:51 PM
|
|
Juha Nieminen <nospam@thanks.invalid> writes:
> In comp.lang.c++ Moi <root@invalid.address.org> wrote:
>> Personally I tend to use:
>>
>> for ( begin_expr; test_expr; next_expr) {;}
>>
>> , which immediately makes clear that the empty loop is intended.
>
> And causes a compiler warning due to a lone ';' if enough warning flags
> are used.
It does? A lone semicolon in this context is a null statement, which is
perfectly legal. Compilers can certainly warn about anything they like,
but I don't see why it would warn about this.
> What's wrong with {}?
Nothing that I can see.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
Keith
|
5/1/2010 5:03:18 PM
|
|
On Sat, 01 May 2010 10:03:18 -0700, Keith Thompson wrote:
> Juha Nieminen <nospam@thanks.invalid> writes:
>
>> What's wrong with {}?
>
> Nothing that I can see.
It resembles badly aligned tits.
;-}
AvK
|
|
0
|
|
|
|
Reply
|
Moi
|
5/1/2010 5:23:06 PM
|
|
On Apr 25, 8:19=A0am, red floyd <no.spam.h...@its.invalid> wrote:
> As a purely stylistic matter, my empty loops always look like:
>
> for ( begin_expr; test_expr; next_expr)
> =A0 =A0 /* do nothing */ ;
>
> That is, I always explicitly comment the empty loop so that
> it's clear that I wanted the loop to be empty.
>
> Makes life easier later on down the line.
Funnily, a language's designers have thought to have the "do nothing"
in the language, certainly for the same reason.
E.g.
for i in Some_range loop
null;
end loop;
G.
|
|
0
|
|
|
|
Reply
|
gautier_niouzes (328)
|
5/1/2010 5:44:19 PM
|
|
On 5/1/2010 1:03 PM, Keith Thompson wrote:
> Juha Nieminen<nospam@thanks.invalid> writes:
>> In comp.lang.c++ Moi<root@invalid.address.org> wrote:
>>> Personally I tend to use:
>>>
>>> for ( begin_expr; test_expr; next_expr) {;}
>>>
>>> , which immediately makes clear that the empty loop is intended.
>>
>> And causes a compiler warning due to a lone ';' if enough warning flags
>> are used.
>
> It does? A lone semicolon in this context is a null statement, which is
> perfectly legal. Compilers can certainly warn about anything they like,
> but I don't see why it would warn about this.
[...]
Consider:
for ( begin_expr ; test_expr ; next_expr );
do_something();
The "lone semicolon" could easily be a typo, and not easy to spot at times.
(Which is sort of what this sub-thread is all about.)
--
Kenneth Brody
|
|
0
|
|
|
|
Reply
|
Kenneth
|
5/2/2010 2:32:04 AM
|
|
Kenneth Brody <kenbrody@spamcop.net> writes:
> On 5/1/2010 1:03 PM, Keith Thompson wrote:
>> Juha Nieminen<nospam@thanks.invalid> writes:
>>> In comp.lang.c++ Moi<root@invalid.address.org> wrote:
>>>> Personally I tend to use:
>>>>
>>>> for ( begin_expr; test_expr; next_expr) {;}
>>>>
>>>> , which immediately makes clear that the empty loop is intended.
>>>
>>> And causes a compiler warning due to a lone ';' if enough warning flags
>>> are used.
>>
>> It does? A lone semicolon in this context is a null statement, which is
>> perfectly legal. Compilers can certainly warn about anything they like,
>> but I don't see why it would warn about this.
> [...]
>
> Consider:
>
> for ( begin_expr ; test_expr ; next_expr );
> do_something();
>
> The "lone semicolon" could easily be a typo, and not easy to spot at times.
> (Which is sort of what this sub-thread is all about.)
Sure, and a warning about that empty statement would be reasonable.
A warning about "{;}" would IMHO be less reasonable (there's not
much chance of it being a typo), and would likely be produced only
if the compiler warns about *all* null statements.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
Keith
|
5/2/2010 4:02:01 AM
|
|
Juha Nieminen wrote:
> In comp.lang.c++ Richard Heathfield <rjh@see.sig.invalid> wrote:
>> If the data are sorted, bsearch.
>>
>> If not, why not?
>>
>> In any case, your loop condition expressions do not correctly describe
>> the conditions under which the loop will terminate. Please rewrite your
>> example so that they do, and then by all means ask me again if you wish.
>
> No offense, but it always amuses me how some C programmers try to
> wiggle themselves out of actually giving honest answers when they are
> presented with problematic situations related to their coding style, C,
> or both.
Your paragraph, above, is a classic example.
<snip>
> And I have no idea what you mean by "your loop condition expressions do
> not correctly describe the conditions under which the loop will terminate".
That's the problem.
> Of course they do.
No, they don't.
> Is this just another attempt at wiggling yourself out
> of actually giving the answer?
No, it's an attempt at wiggling *your*self out of fixing your code.
> Is it *really* that hard to simply say "yes, in this particular example
> the 'return' is indeed the simplest way"? Does it hurt your pride or
> something?
What has pride got to do with it? It's common sense, that's all. The
simplest way (and one of the fastest) to get from Tower Bridge Approach
to St Katharine's Way is to jump off the bridge, but that doesn't
necessarily mean it's the /best/ way.
--
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
|
|
0
|
|
|
|
Reply
|
Richard
|
5/2/2010 7:13:06 AM
|
|
On 05/02/10 17:13, Richard Heathfield wrote:
> Juha Nieminen wrote:
>> In comp.lang.c++ Richard Heathfield <rjh@see.sig.invalid> wrote:
>>> If the data are sorted, bsearch.
>>>
>>> If not, why not?
>>>
>>> In any case, your loop condition expressions do not correctly
>>> describe the conditions under which the loop will terminate. Please
>>> rewrite your example so that they do, and then by all means ask me
>>> again if you wish.
>>
>> No offense, but it always amuses me how some C programmers try to
>> wiggle themselves out of actually giving honest answers when they are
>> presented with problematic situations related to their coding style, C,
>> or both.
>
> Your paragraph, above, is a classic example.
I think Juha's point is that, if you write the for-loop's conditionals
so they (using your terms) "describe the condition which the loop will
terminate", that will severely complicate the conditionals (compared to
simply hopping out using return). So Juha's challenging you to rewrite
the looping conditionals without obfuscating them.
|
|
0
|
|
|
|
Reply
|
Lie
|
5/2/2010 7:25:33 AM
|
|
Seebs wrote:
> On 2010-04-28, Richard Heathfield <rjh@see.sig.invalid> wrote:
<snip>
>> If the data are sorted, bsearch.
>
>> If not, why not?
>
> I do not normally expect something structured like a three-dimensional
> array to be sorted, I expect it to be a representation of objects.
Then how on earth do you /find/ anything? It's O(N^3), for pity's sake!
>> In any case, your loop condition expressions do not correctly describe
>> the conditions under which the loop will terminate. Please rewrite your
>> example so that they do, and then by all means ask me again if you wish.
>
> I think the point was that he was asking *you* to rewrite the example
> so that the loop conditions correctly describe the conditions under which
> the loop will terminate.
And we all know how that will go.
This is really an argument about programming philosophy. Juha seems to
be in favour of the shortest code that does the job. I'm in favour of
code that accurately describes what it's doing. while(i < j) is not an
accurate description of the loop if you bomb out as soon as a[i] is 42.
Why not just write while(i < j && a[i] != 42)?
<snip>
--
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
|
|
0
|
|
|
|
Reply
|
Richard
|
5/2/2010 7:34:55 AM
|
|
Willem wrote:
> Richard Heathfield wrote:
> ) In any case, your loop condition expressions do not correctly describe
> ) the conditions under which the loop will terminate. Please rewrite your
> ) example so that they do, and then by all means ask me again if you wish.
>
> Don't be silly.
>
> 'loop conditions should correctly describe the conditions under
> which the loop will terminate' is a requirement that is roughly
> equivalent to 'you should never exit from within a loop'.
>
> In other words, you're begging the question.
Yes, and this question-begging is perfectly in keeping with the
requirement that one should never exit from within a loop. (It is, after
all, an argument about loops.)
--
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
|
|
0
|
|
|
|
Reply
|
Richard
|
5/2/2010 7:40:06 AM
|
|
In comp.lang.c++ Richard Heathfield <rjh@see.sig.invalid> wrote:
> Juha Nieminen wrote:
>> In comp.lang.c++ Richard Heathfield <rjh@see.sig.invalid> wrote:
>>> If the data are sorted, bsearch.
>>>
>>> If not, why not?
>>>
>>> In any case, your loop condition expressions do not correctly describe
>>> the conditions under which the loop will terminate. Please rewrite your
>>> example so that they do, and then by all means ask me again if you wish.
>>
>> No offense, but it always amuses me how some C programmers try to
>> wiggle themselves out of actually giving honest answers when they are
>> presented with problematic situations related to their coding style, C,
>> or both.
>
> Your paragraph, above, is a classic example.
You know, an answer of "no, you are" is rather childish. How about
presenting some actual arguments instead?
I gave you a piece of code and asked you to modify it to conform to
your principles. You did not do that. Who is trying to avoid answering
to a challenge here?
>> And I have no idea what you mean by "your loop condition expressions do
>> not correctly describe the conditions under which the loop will terminate".
>
> That's the problem.
>
>> Of course they do.
>
> No, they don't.
Then why do you refuse to tell how the loops should have been written
to conform to your specifications? I explicitly asked you to modify the
code so that it would. Why are you refusing to do so?
>> Is this just another attempt at wiggling yourself out
>> of actually giving the answer?
>
> No, it's an attempt at wiggling *your*self out of fixing your code.
Fixing my code? Oh, so there's a bug in it? Kindly point out what the
bug is, please.
Or are you using the word "fixing" to mean "convert it to conform my
views of how loops should be written"? If yes, then why are you asking
*me* to do that? I don't know what *you* want the loops to look like.
I'm *asking* you to explain it to me, with an actual example. Why are
you refusing to do so? Why are you demanding me to guess wildly what is
it that you want the code to look like?
Can you even answer that question? Why are you refusing to show me your
way of writing those loops?
>> Is it *really* that hard to simply say "yes, in this particular example
>> the 'return' is indeed the simplest way"? Does it hurt your pride or
>> something?
>
> What has pride got to do with it? It's common sense, that's all. The
> simplest way (and one of the fastest) to get from Tower Bridge Approach
> to St Katharine's Way is to jump off the bridge, but that doesn't
> necessarily mean it's the /best/ way.
Then kindly show me this "best way".
|
|
0
|
|
|
|
Reply
|
Juha
|
5/2/2010 7:58:17 AM
|
|
In comp.lang.c++ Richard Heathfield <rjh@see.sig.invalid> wrote:
> Seebs wrote:
>> On 2010-04-28, Richard Heathfield <rjh@see.sig.invalid> wrote:
>
> <snip>
>
>>> If the data are sorted, bsearch.
>>
>>> If not, why not?
>>
>> I do not normally expect something structured like a three-dimensional
>> array to be sorted, I expect it to be a representation of objects.
>
> Then how on earth do you /find/ anything? It's O(N^3), for pity's sake!
Are you saying that if an algorithm is O(N^3) it cannot find anything?
Because that's exactly how I'm interpreting your sentence above.
I would really like to see some kind of proof of that.
(And what exactly does the computational complexity have to do with
how you exit nested loops cleanly? Is this some kind of intentional
sidetracking in order to get away from the actual subject?)
>> I think the point was that he was asking *you* to rewrite the example
>> so that the loop conditions correctly describe the conditions under which
>> the loop will terminate.
>
> And we all know how that will go.
So you really are refusing to answer my question and instead demanding
me to guess what is it that you mean?
> This is really an argument about programming philosophy. Juha seems to
> be in favour of the shortest code that does the job. I'm in favour of
> code that accurately describes what it's doing. while(i < j) is not an
> accurate description of the loop if you bomb out as soon as a[i] is 42.
> Why not just write while(i < j && a[i] != 42)?
Because in many cases it makes the code more complicated than would be
necessary, and in some cases even less efficient, for no obvious benefit?
Are you seriously telling me that you have hard time understanding what
my example code is doing, and that it would be much easier to understand
in your way (whatever that might be)?
|
|
0
|
|
|
|
Reply
|
Juha
|
5/2/2010 8:04:31 AM
|
|
In comp.lang.c++ Richard Heathfield <rjh@see.sig.invalid> wrote:
> Yes, and this question-begging is perfectly in keeping with the
> requirement that one should never exit from within a loop. (It is, after
> all, an argument about loops.)
Out of curiosity: Why have the requirement that one should never exit
from within a loop? Is there a rational reason to enforce this requirement
even in cases where exiting from inside a loop would actually make the
code simpler and easier to understand (and possibly more efficient)?
It sounds to me like you are advocating a certain kind of programming
paradigm as the silver bullet for all problems. As if sticking very
strictly to that paradigm would always make your code better.
There exists no such programming paradigm.
|
|
0
|
|
|
|
Reply
|
Juha
|
5/2/2010 8:07:56 AM
|
|
Richard Heathfield <rjh@see.sig.invalid> writes:
> Seebs wrote:
>> On 2010-04-28, Richard Heathfield <rjh@see.sig.invalid> wrote:
[...]
>>> In any case, your loop condition expressions do not correctly describe
>>> the conditions under which the loop will terminate. Please rewrite your
>>> example so that they do, and then by all means ask me again if you wish.
>>
>> I think the point was that he was asking *you* to rewrite the example
>> so that the loop conditions correctly describe the conditions under which
>> the loop will terminate.
>
> And we all know how that will go.
I get the impression that you're implying something that you think is
obvious, but I don't know what it is.
We don't all know how that will go. In particular, I don't know how it
will go, because you haven't shown us how you would write the loop.
I'm curious.
[...]
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
Keith
|
5/2/2010 8:46:36 AM
|
|
Richard Heathfield <rjh@see.sig.invalid> writes:
> Yes, and this question-begging is perfectly in keeping with the
> requirement that one should never exit from within a loop. (It is,
> after all, an argument about loops.)
What requirement?
If there was such a requirement, why is "break" allowed in any loop?
Why is "return" allowed other that in the outermost block within a
function. Either could easily have been made part of the standard if
there was such a requirement.
--
Online waterways route planner | http://canalplan.eu
Plan trips, see photos, check facilities | http://canalplan.org.uk
|
|
0
|
|
|
|
Reply
|
Nick
|
5/2/2010 9:13:55 AM
|
|
"Nick" <3-nospam@temporary-address.org.uk> wrote in message
news:87iq76zmwc.fsf@temporary-address.org.uk...
> Richard Heathfield <rjh@see.sig.invalid> writes:
>
>> Yes, and this question-begging is perfectly in keeping with the
>> requirement that one should never exit from within a loop. (It is,
>> after all, an argument about loops.)
>
> What requirement?
>
> If there was such a requirement, why is "break" allowed in any loop?
> Why is "return" allowed other that in the outermost block within a
> function. Either could easily have been made part of the standard if
> there was such a requirement.
It would have broken too much existing code. That's the usual reason.
--
Bartc
|
|
0
|
|
|
|
Reply
|
bart
|
5/2/2010 9:56:24 AM
|
|
On May 2, 8:34 am, Richard Heathfield <r...@see.sig.invalid> wrote:
> Seebs wrote:
[...]
> Why not just write while(i < j && a[i] != 42)?
Because it states the loop invariants up front, in a single
statement, rather than making the maintenance programmer have to
figure them out for himself. Maintenance programmers have it
too easy.
--
James Kanze
|
|
0
|
|
|
|
Reply
|
James
|
5/2/2010 10:07:39 AM
|
|
On May 2, 9:07 am, Juha Nieminen <nos...@thanks.invalid> wrote:
> In comp.lang.c++ Richard Heathfield <r...@see.sig.invalid> wrote:
> > Yes, and this question-begging is perfectly in keeping with
> > the requirement that one should never exit from within a
> > loop. (It is, after all, an argument about loops.)
> Out of curiosity: Why have the requirement that one should
> never exit from within a loop? Is there a rational reason to
> enforce this requirement even in cases where exiting from
> inside a loop would actually make the code simpler and easier
> to understand (and possibly more efficient)?
The argument is that such cases don't exist. I'll admit that
I've never seen one. And there are really two separate
arguments, which hasn't been made clear. One school of thought
is that the loop conditions should express the loop invariants
entirely, and be clearly stated up front, where anyone reading
the code can easily see them. Another school of thought is more
relaxed: it says, basically, that you can only have one exit
from a loop, and allows the classical "loop and a half" idiom,
where that sole exit is in the middle of the loop (and you have
two sets of invariants, one empty, for the start of the loop,
and one which isn't empty, for the end).
There is, of course, also a third school of thought, which
basically comes down to: tough shit for the maintenance
programmer (or the code reviewer, or anyone else who has to read
the code):-).
> It sounds to me like you are advocating a certain kind of
> programming paradigm as the silver bullet for all problems.
It sounds to me almost the opposite. He's not really advocating
a programming paradigm, as condemning one which definitely makes
the code more difficult to understand.
Having said that: when all is said and done, if your functions
and loops are large enough for it to make a significant
difference, that's a problem in itself. I favor the SESE style,
but I'd rather deal with an exit from a small (two or three
line) loop than a 100 line loop in SESE. And I readily accept
the fact that there are certain "idioms" which might formally
violate the rule.
> As if sticking very strictly to that paradigm would always
> make your code better.
> There exists no such programming paradigm.
No, but there are paradigms which will always make your code
worse:-).
--
James Kanze
|
|
0
|
|
|
|
Reply
|
James
|
5/2/2010 10:17:07 AM
|
|
James Kanze <james.kanze@gmail.com> writes:
> On May 2, 9:07 am, Juha Nieminen <nos...@thanks.invalid> wrote:
<snip>
>> Out of curiosity: Why have the requirement that one should
>> never exit from within a loop? Is there a rational reason to
>> enforce this requirement even in cases where exiting from
>> inside a loop would actually make the code simpler and easier
>> to understand (and possibly more efficient)?
>
> The argument is that such cases don't exist. I'll admit that
> I've never seen one. And there are really two separate
> arguments, which hasn't been made clear. One school of thought
> is that the loop conditions should express the loop invariants
> entirely, and be clearly stated up front, where anyone reading
> the code can easily see them. Another school of thought is more
> relaxed: it says, basically, that you can only have one exit
> from a loop, and allows the classical "loop and a half" idiom,
> where that sole exit is in the middle of the loop (and you have
> two sets of invariants, one empty, for the start of the loop,
> and one which isn't empty, for the end).
I think you may be using the wrong term here. For me, a loop invariant
is a condition that is quite separate from the loop's controlling
condition. It is true both before and after the loop (as well as being
true when the loop's control is tested) and is chosen so that combining
it with the negation of the loop's control gives the result we want to
assert about the loop.
For example, in a sorting loop one might choose the invariant:
I = A holds a permutation of the original data /\
A[0]..A[i-1] is sorted
If the loop's controlling condition, C, is i < N we can deduce that loop
termination implies !C /\ I which is enough to show what we need to show
about the result in A.
Having "internal" exit points will often have no effect on what makes a
useful invariant, and it often has no effect on the ease or difficulty
of proving it. What it may do it complicate the business of choosing
and proving the termination condition.
I think you have been talking about the terminating condition rather
than a loop invariant.
<snip>
--
Ben.
|
|
0
|
|
|
|
Reply
|
Ben
|
5/2/2010 12:37:33 PM
|
|
Kenneth Brody <kenbrody@spamcop.net> writes:
> On 5/1/2010 1:03 PM, Keith Thompson wrote:
>> Juha Nieminen<nospam@thanks.invalid> writes:
>>> In comp.lang.c++ Moi<root@invalid.address.org> wrote:
>>>> Personally I tend to use:
>>>>
>>>> for ( begin_expr; test_expr; next_expr) {;}
>>>>
>>>> , which immediately makes clear that the empty loop is intended.
>>>
>>> And causes a compiler warning due to a lone ';' if enough warning flags
>>> are used.
>>
>> It does? A lone semicolon in this context is a null statement, which is
>> perfectly legal. Compilers can certainly warn about anything they like,
>> but I don't see why it would warn about this.
> [...]
>
> Consider:
>
> for ( begin_expr ; test_expr ; next_expr );
> do_something();
>
> The "lone semicolon" could easily be a typo, and not easy to spot at
> times. (Which is sort of what this sub-thread is all about.)
The merits of various styles for empty loop bodies is frequently debated
here, but here's a thought: does it actually matter? Has anyone ever
encountered a hard bug caused by either the accidental inclusion of a
semicolon (thereby excluding the while loop body) or by the omission of
a null body (thereby sucking the following statement into the loop)? I
don't think I ever have. I certainly don't recall one.
I say "hard bug" because (of course) bugs are caused by this issue, one
way or the other, but I imagine that they are always so detrimental to
the intent of the code that they show up at the first test. Such bugs
are not so different from syntax errors -- the compiler tests the syntax
and your own tests test the basic functioning of a code fragment.
Does anyone have a recollection of such a hard to find bug and, if so,
do you recall enough to explain how it came about?
For the record, I have no objection to this being discussed often and at
length; I am just explaining why I find it hard to care. I've used most
of the methods suggested at one time or another, but I was never able to
conclude that one was better than the others.
--
Ben.
|
|
0
|
|
|
|
Reply
|
Ben
|
5/2/2010 12:58:55 PM
|
|
On May 2, 3:58=A0pm, Juha Nieminen <nos...@thanks.invalid> wrote:
> In comp.lang.c++ Richard Heathfield <r...@see.sig.invalid> wrote:
>
>
>
>
>
> > Juha Nieminen wrote:
> >> In comp.lang.c++ Richard Heathfield <r...@see.sig.invalid> wrote:
> >>> If the data are sorted, bsearch.
>
> >>> If not, why not?
>
> >>> In any case, your loop condition expressions do not correctly describ=
e
> >>> the conditions under which the loop will terminate. Please rewrite yo=
ur
> >>> example so that they do, and then by all means ask me again if you wi=
sh.
>
> >> =A0 No offense, but it always amuses me how some C programmers try to
> >> wiggle themselves out of actually giving honest answers when they are
> >> presented with problematic situations related to their coding style, C=
,
> >> or both.
>
> > Your paragraph, above, is a classic example.
>
> =A0 You know, an answer of "no, you are" is rather childish. How about
> presenting some actual arguments instead?
>
> =A0 I gave you a piece of code and asked you to modify it to conform to
> your principles. You did not do that. Who is trying to avoid answering
> to a challenge here?
>
> >> =A0 And I have no idea what you mean by "your loop condition expressio=
ns do
> >> not correctly describe the conditions under which the loop will termin=
ate".
>
> > That's the problem.
>
> >> Of course they do.
>
> > No, they don't.
>
> =A0 Then why do you refuse to tell how the loops should have been written
> to conform to your specifications? I explicitly asked you to modify the
> code so that it would. Why are you refusing to do so?
>
> >> Is this just another attempt at wiggling yourself out
> >> of actually giving the answer?
>
> > No, it's an attempt at wiggling *your*self out of fixing your code.
>
> =A0 Fixing my code? Oh, so there's a bug in it? Kindly point out what the
> bug is, please.
>
> =A0 Or are you using the word "fixing" to mean "convert it to conform my
> views of how loops should be written"? If yes, then why are you asking
> *me* to do that? I don't know what *you* want the loops to look like.
> I'm *asking* you to explain it to me, with an actual example. Why are
> you refusing to do so? Why are you demanding me to guess wildly what is
> it that you want the code to look like?
>
> =A0 Can you even answer that question? Why are you refusing to show me yo=
ur
> way of writing those loops?
>
> >> =A0 Is it *really* that hard to simply say "yes, in this particular ex=
ample
> >> the 'return' is indeed the simplest way"? Does it hurt your pride or
> >> something?
>
> > What has pride got to do with it? It's common sense, that's all. The
> > simplest way (and one of the fastest) to get from Tower Bridge Approach
> > to St Katharine's Way is to jump off the bridge, but that doesn't
> > necessarily mean it's the /best/ way.
>
> =A0 Then kindly show me this "best way".
Juha, this guy is afraid to make a positive response, because he
bullies people who make "mistakes" and he's afraid of eating his own
dog food.
|
|
0
|
|
|
|
Reply
|
spinoza1111
|
5/2/2010 1:37:12 PM
|
|
On Sun, 02 May 2010 13:58:55 +0100, Ben Bacarisse
<ben.usenet@bsb.me.uk> wrote:
>Kenneth Brody <kenbrody@spamcop.net> writes:
>
>> On 5/1/2010 1:03 PM, Keith Thompson wrote:
>>> Juha Nieminen<nospam@thanks.invalid> writes:
>>>> In comp.lang.c++ Moi<root@invalid.address.org> wrote:
>>>>> Personally I tend to use:
>>>>>
>>>>> for ( begin_expr; test_expr; next_expr) {;}
>>>>>
>>>>> , which immediately makes clear that the empty loop is intended.
>>>>
>>>> And causes a compiler warning due to a lone ';' if enough warning flags
>>>> are used.
>>>
>>> It does? A lone semicolon in this context is a null statement, which is
>>> perfectly legal. Compilers can certainly warn about anything they like,
>>> but I don't see why it would warn about this.
>> [...]
>>
>> Consider:
>>
>> for ( begin_expr ; test_expr ; next_expr );
>> do_something();
>>
>> The "lone semicolon" could easily be a typo, and not easy to spot at
>> times. (Which is sort of what this sub-thread is all about.)
On the converse, the lack of a semicolon would be a typo.
Without it the code is not properly indented.
>
>The merits of various styles for empty loop bodies is frequently debated
>here, but here's a thought: does it actually matter? Has anyone ever
>encountered a hard bug caused by either the accidental inclusion of a
>semicolon (thereby excluding the while loop body) or by the omission of
>a null body (thereby sucking the following statement into the loop)? I
>don't think I ever have. I certainly don't recall one.
>
>I say "hard bug" because (of course) bugs are caused by this issue, one
>way or the other, but I imagine that they are always so detrimental to
>the intent of the code that they show up at the first test. Such bugs
>are not so different from syntax errors -- the compiler tests the syntax
>and your own tests test the basic functioning of a code fragment.
>
>Does anyone have a recollection of such a hard to find bug and, if so,
>do you recall enough to explain how it came about?
>
>For the record, I have no objection to this being discussed often and at
>length; I am just explaining why I find it hard to care. I've used most
>of the methods suggested at one time or another, but I was never able to
>conclude that one was better than the others.
What I have seen are bugs caused by not noticing that the
indentation is inconsistent with the code. Thus:
if (rare_condition)
take_special_action();
In the fullness of time our hero adds a statement to the block to
produce:
if (rare_condition_
take_special_action();
increment_error_count();
where the error count is incremented whenever an error occurs in
the system. When the error count gets too high the system goes
into error recovery mode and slows way down. The results are
still correct but the performance degrades. (The example is
contrived but I have seen this sort of thing happen.)
In my view all of these fiddles with an empty loop body are
pointless, and, if anything, make the code harder to read and
offer more room for error.
Richard Harter, cri@tiac.net
http://home.tiac.net/~cri, http://www.varinoma.com
It's not much to ask of the universe that it be fair;
it's not much to ask but it just doesn't happen.
|
|
0
|
|
|
|
Reply
|
cri
|
5/2/2010 2:26:16 PM
|
|
cri@tiac.net (Richard Harter) writes:
> On Sun, 02 May 2010 13:58:55 +0100, Ben Bacarisse
> <ben.usenet@bsb.me.uk> wrote:
<snip>
>> Has anyone ever
>>encountered a hard bug caused by either the accidental inclusion of a
>>semicolon (thereby excluding the while loop body) or by the omission of
>>a null body (thereby sucking the following statement into the loop)? I
>>don't think I ever have. I certainly don't recall one.
<snip>
> What I have seen are bugs caused by not noticing that the
> indentation is inconsistent with the code. Thus:
>
> if (rare_condition)
> take_special_action();
>
> In the fullness of time our hero adds a statement to the block to
> produce:
>
> if (rare_condition) /* corrected typo: missing ) */
> take_special_action();
> increment_error_count();
>
> where the error count is incremented whenever an error occurs in
> the system. When the error count gets too high the system goes
> into error recovery mode and slows way down. The results are
> still correct but the performance degrades. (The example is
> contrived but I have seen this sort of thing happen.)
I agree. I'd say that indentation if more important than how an empty
body is written, but since there are tools to help with this I am not
convinced it is all that significant. Sadly they are separate tools so
they may get forgotten. I'd be happy to see warnings from a compiler
about incorrect indentation because they so often indicate a serious
problem.
<snip>
--
Ben.
|
|
0
|
|
|
|
Reply
|
Ben
|
5/2/2010 2:59:02 PM
|
|
Moi wrote:
>
> Personally I tend to use:
>
> for ( begin_expr; test_expr; next_expr) {;}
>
> , which immediately makes clear that the empty loop is intended.
>
> AvK
The "comments are unnecessary" people aren't going to like this but...
for ( begin_expr; test_expr; next_expr) { /* Do nothing */}
for ( begin_expr; test_expr; /* no increment */)
{
}
work for me.
Andy
|
|
0
|
|
|
|
Reply
|
Andy
|
5/2/2010 4:02:14 PM
|
|
"Red Rooster" ha scritto nel messaggio
> On Sat, 1 May 2010 08:12:33 +0200, "io_x" <a@b.c.invalid> wrote:
....
>> Actually, this whole thread is glorious waste
>>of time, seriously guys.. this needs to be asked: WHAT THE FUCK!?!??
> EXACTLY!
> Why did you even start it a week ago?
because the "seriously guys" don't understand
goto manifest itself in so not easy form
because their respective languages asm, c, c++, basic, etc
see it in the wrong manner.
I advise them it could be not always so,
there could be one language in wicht goto is easy :)
> RR
|
|
0
|
|
|
|
Reply
|
io_x
|
5/2/2010 4:11:15 PM
|
|
On 2010-05-02, Richard Heathfield <rjh@see.sig.invalid> wrote:
>> I do not normally expect something structured like a three-dimensional
>> array to be sorted, I expect it to be a representation of objects.
> Then how on earth do you /find/ anything? It's O(N^3), for pity's sake!
Yup.
If you have, say, a representation of a three-dimensional object, where each
point holds information about a particular point in three-space, it is quite
possible that the most significant sorting is "sorted by location" rather
than "sorted by value".
> This is really an argument about programming philosophy. Juha seems to
> be in favour of the shortest code that does the job. I'm in favour of
> code that accurately describes what it's doing. while(i < j) is not an
> accurate description of the loop if you bomb out as soon as a[i] is 42.
> Why not just write while(i < j && a[i] != 42)?
Because, in some cases, the checks against a[i] make it harder to follow
the code.
I guess it's a question of how you do the translation.
for (i = 0; i < n; ++i)
if (long_funky_expression(a[i]) && more_stuff[i])
break;
if (i == n)
...
I don't see this as necessarily less clear than
for (i = 0; i < n && !(long_funky_expression(a[i]) && more_stuff[i]); ++i;
;
In general, in fact, I prefer the former. The loop is "iterate through
a". In this case, the idiomatic clarity of "we are looping from 0 to n-1"
is so much greater that "we are looping from 0 to n-1, and the operation
is to stop prematurely if..." is much clearer than "we are looping from 0
to either n-1 or the first value such that....".
A lot of it is just the strength of idiom when communicating. The reader
will be able to chunk the simple loops into single things rather than
complicated relationships, making it easier to read the code. My guess
is that, if you were to compare human responses to the two descriptions
above, you'd find that people were much more likely to correctly divine the
expected results of the first.
In short... It's like knowing that you can put a couple of case labels in
a row in C. Every user of C is aware that C provides for breaking out of
loops. A C programmer won't be surprised by it, and it is in fact the
canonical idiom for a large number of operations. Your style confuses the
user by conflating two unrelated tests. They really are unrelated; one is
expressing the range we're searching, the other is expressing what we're
searching for. Combining them into a single test obfuscates the loop,
even though it is possible to describe it as though it were simpler.
-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
|
|
0
|
|
|
|
Reply
|
Seebs
|
5/2/2010 4:54:25 PM
|
|
On 2010-05-02, James Kanze <james.kanze@gmail.com> wrote:
> It sounds to me almost the opposite. He's not really advocating
> a programming paradigm, as condemning one which definitely makes
> the code more difficult to understand.
Except he hasn't established that the other paradigm *definitely* makes
the code more difficult to understand.
And empirically, when someone converted a program using the condemned
paradigm, which everyone understood at first read, to one using his
preferred paradigm, several experienced programmers tripped over it,
because the resulting program was harder to understand. It's easier to
understand a simple rule with an exception than to understand a complicated
rule.
-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
|
|
0
|
|
|
|
Reply
|
Seebs
|
5/2/2010 4:57:17 PM
|
|
Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
> Kenneth Brody <kenbrody@spamcop.net> writes:
>> On 5/1/2010 1:03 PM, Keith Thompson wrote:
>>> Juha Nieminen<nospam@thanks.invalid> writes:
>>>> In comp.lang.c++ Moi<root@invalid.address.org> wrote:
>>>>> Personally I tend to use:
>>>>>
>>>>> for ( begin_expr; test_expr; next_expr) {;}
>>>>>
>>>>> , which immediately makes clear that the empty loop is intended.
>>>>
>>>> And causes a compiler warning due to a lone ';' if enough warning flags
>>>> are used.
>>>
>>> It does? A lone semicolon in this context is a null statement, which is
>>> perfectly legal. Compilers can certainly warn about anything they like,
>>> but I don't see why it would warn about this.
>> [...]
>>
>> Consider:
>>
>> for ( begin_expr ; test_expr ; next_expr );
>> do_something();
>>
>> The "lone semicolon" could easily be a typo, and not easy to spot at
>> times. (Which is sort of what this sub-thread is all about.)
>
> The merits of various styles for empty loop bodies is frequently debated
> here, but here's a thought: does it actually matter? Has anyone ever
> encountered a hard bug caused by either the accidental inclusion of a
> semicolon (thereby excluding the while loop body) or by the omission of
> a null body (thereby sucking the following statement into the loop)? I
> don't think I ever have. I certainly don't recall one.
>
> I say "hard bug" because (of course) bugs are caused by this issue, one
> way or the other, but I imagine that they are always so detrimental to
> the intent of the code that they show up at the first test. Such bugs
> are not so different from syntax errors -- the compiler tests the syntax
> and your own tests test the basic functioning of a code fragment.
>
> Does anyone have a recollection of such a hard to find bug and, if so,
> do you recall enough to explain how it came about?
[...]
I have a vague recollection of a bug, discussed here, involving some
kind of iterative mathematical calculation, where each iteration
would yield a more accurate result. A lone semicolon on a loop
(could have been a either a for or a while) caused iterations after
the first not to be executed. The resulting answers were imprecise,
but not obviously wrong.
Something like this:
answer = first_approximation;
while (... more precision is needed ...); /* <-- OOPS! */
{
answer = better_approximation_of(answer);
}
Note that the indentation is still correct, and a typical compiler
probably wouldn't warn about it if the while condition might have
side effects.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
Keith
|
5/2/2010 6:21:23 PM
|
|
On May 2, 1:37 pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
> James Kanze <james.ka...@gmail.com> writes:
> > On May 2, 9:07 am, Juha Nieminen <nos...@thanks.invalid> wrote:
> <snip>
> I think you may be using the wrong term here. For me, a loop
> invariant is a condition that is quite separate from the
> loop's controlling condition.
Yes and no. As you correctly point out, there can be loop
invariants which aren't expressed by the controlling condition,
and they play an important role in evaluating the correctness of
the loop. It does, however, facilitate comprehension of the
loop if one of the invariants is that the loops termination
conditions haven't been met.
--
James Kanze
|
|
0
|
|
|
|
Reply
|
James
|
5/2/2010 10:39:51 PM
|
|
On May 2, 5:57 pm, Seebs <usenet-nos...@seebs.net> wrote:
> On 2010-05-02, James Kanze <james.ka...@gmail.com> wrote:
>
> > It sounds to me almost the opposite. He's not really advocating
> > a programming paradigm, as condemning one which definitely makes
> > the code more difficult to understand.
>
> Except he hasn't established that the other paradigm *definitely* makes
> the code more difficult to understand.
>
> And empirically, when someone converted a program using the condemned
> paradigm, which everyone understood at first read, to one using his
> preferred paradigm, several experienced programmers tripped over it,
> because the resulting program was harder to understand. It's easier to
> understand a simple rule with an exception than to understand a complicated
> rule.
>
> -s
> --
> Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nos...@seebs.nethttp://www.seebs.net/log/<-- lawsuits, religion, and funny pictureshttp://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
|
|
0
|
|
|
|
Reply
|
James
|
5/2/2010 10:42:20 PM
|
|
On May 2, 5:57 pm, Seebs <usenet-nos...@seebs.net> wrote:
> On 2010-05-02, James Kanze <james.ka...@gmail.com> wrote:
> > It sounds to me almost the opposite. He's not really advocating
> > a programming paradigm, as condemning one which definitely makes
> > the code more difficult to understand.
> Except he hasn't established that the other paradigm
> *definitely* makes the code more difficult to understand.
No. The only thing that's been conclusively proven is that the
SESE idiom never makes the code more difficult to understand.
If the loops (and the functions that contain them) are
reasonably short, the difference between the two should be
minimal.
--
James Kanze
|
|
0
|
|
|
|
Reply
|
James
|
5/2/2010 10:42:41 PM
|
|
James Kanze wrote:
> On May 2, 5:57 pm, Seebs <usenet-nos...@seebs.net> wrote:
>> On 2010-05-02, James Kanze <james.ka...@gmail.com> wrote:
>
>> > It sounds to me almost the opposite. He's not really advocating
>> > a programming paradigm, as condemning one which definitely makes
>> > the code more difficult to understand.
>
>> Except he hasn't established that the other paradigm
>> *definitely* makes the code more difficult to understand.
>
> No. The only thing that's been conclusively proven is that the
> SESE idiom never makes the code more difficult to understand.
[...]
Just curious: could you provide a reference, where I can read up on that
proof? I vaguely remember a theorem to the effect that there is a family of
programs such that rewriting them into SESE either makes the code size grow
exponentially or degrades efficiency of execution by a logarithmic factor;
but I would have to look that up for a precise statement. Anyway, that does
not directly contradict your statement above; but it would be interesting to
compare the two theorems.
Best
Kai-Uwe Bux
|
|
0
|
|
|
|
Reply
|
Kai
|
5/2/2010 10:54:46 PM
|
|
On 2010-05-02, James Kanze <james.kanze@gmail.com> wrote:
> On May 2, 5:57 pm, Seebs <usenet-nos...@seebs.net> wrote:
>> Except he hasn't established that the other paradigm
>> *definitely* makes the code more difficult to understand.
> No. The only thing that's been conclusively proven is that the
> SESE idiom never makes the code more difficult to understand.
That has not been proven.
And, in fact, in the recent example, we saw conclusively that the SESE
version was misunderstood by more than one reader, while the other version
was not misunderstood by anyone.
Demonstrably, SESE *can* make code more difficult to understand.
> If the loops (and the functions that contain them) are
> reasonably short, the difference between the two should be
> minimal.
Again, empiricism wins; empirically, the SESE version of the scan of a
three-dimensional array was less understandable, in that more than one
person, reading it, misunderstood what its effects would be.
There is no way you can go from "people misunderstand B, but not A" to
"conclusively proven that B is not more difficult to understand".
-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
|
|
0
|
|
|
|
Reply
|
Seebs
|
5/2/2010 10:59:48 PM
|
|
James Kanze <james.kanze@gmail.com> writes:
> On May 2, 1:37 pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
>> James Kanze <james.ka...@gmail.com> writes:
>> > On May 2, 9:07 am, Juha Nieminen <nos...@thanks.invalid> wrote:
>> <snip>
>
>> I think you may be using the wrong term here. For me, a loop
>> invariant is a condition that is quite separate from the
>> loop's controlling condition.
>
> Yes and no. As you correctly point out, there can be loop
> invariants which aren't expressed by the controlling condition,
> and they play an important role in evaluating the correctness of
> the loop. It does, however, facilitate comprehension of the
> loop if one of the invariants is that the loops termination
> conditions haven't been met.
That's not what most people call a loop invariant. The term refers to
any predicate[1] that is always true at the point at which the loop
condition is evaluated -- even when that condition is false.
You seem to be extending the term in a way that will confuse someone
trying to understand invariants. A predicate that expresses that fact
that the loop's termination conditions haven't been met can't be an
invariant in the sense the term is usually used.
[1] The trick of course is picking a useful one. That's why people
often talk about "the invariant" because there is often a minimal one
that clearly helps to establish the correctness of the loop.
--
Ben.
|
|
0
|
|
|
|
Reply
|
Ben
|
5/2/2010 11:13:00 PM
|
|
On May 2, 7:19=A0pm, "io_x" <a...@b.c.invalid> wrote:
> "Red Rooster" ha scritto nel messaggio
>
> > On Sat, 1 May 2010 08:12:33 +0200, "io_x" <a...@b.c.invalid> wrote:
> ...
> >> Actually, this whole thread is glorious waste
> >>of time, seriously guys.. this needs to be asked: WHAT THE FUCK!?!??
> > EXACTLY!
> > Why did you even start it a week ago?
>
> because the "seriously guys" don't understand
> goto manifest itself in so not easy form
> because their respective languages asm, c, c++, basic, etc
> see it in the wrong manner.
I don't think you have enough data to establish conclusion like that
on firm grounds. Add Ocaml to the respective languages list for me,
thanks a lot mate.
|
|
0
|
|
|
|
Reply
|
hanukas
|
5/3/2010 9:48:29 AM
|
|
In comp.programming Richard Heathfield <rjh@see.sig.invalid> wrote:
>
> Then how on earth do you /find/ anything? It's O(N^3), for pity's sake!
No, it isn't. It's O( N ).
(Hint: What's N the count of?)
--
Leif Roar Moldskred
|
|
0
|
|
|
|
Reply
|
Leif
|
5/3/2010 2:50:48 PM
|
|
On 2 May, 14:37, spinoza1111 <spinoza1...@yahoo.com> wrote:
> Juha, this guy is afraid to make a positive response, because he
> bullies people who make "mistakes" and he's afraid of eating his own
> dog food.
this is a misuse of the term. You probably mean "take his own
medicine"
|
|
0
|
|
|
|
Reply
|
Nick
|
5/3/2010 3:27:20 PM
|
|
On 3 mai, 01:54, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
> James Kanze wrote:
> > On May 2, 5:57 pm, Seebs <usenet-nos...@seebs.net> wrote:
> >> On 2010-05-02, James Kanze <james.ka...@gmail.com> wrote:
>
> >> > It sounds to me almost the opposite. =A0He's not really advocating
> >> > a programming paradigm, as condemning one which definitely makes
> >> > the code more difficult to understand.
>
> >> Except he hasn't established that the other paradigm
> >> *definitely* makes the code more difficult to understand.
>
> > No. =A0The only thing that's been conclusively proven is that the
> > SESE idiom never makes the code more difficult to understand.
>
> [...]
>
> Just curious: could you provide a reference, where I can read up on that
> proof? I vaguely remember a theorem to the effect that there is a family =
of
> programs such that rewriting them into SESE either makes the code size gr=
ow
> exponentially or degrades efficiency of execution by a logarithmic factor=
;
> but I would have to look that up for a precise statement. Anyway, that do=
es
> not directly contradict your statement above; but it would be interesting=
to
> compare the two theorems.
Possibly the cyclomatic complexity of procedures in such programs has
to be reduced with other refactorings first to make that SESE to not
hit them too hard. It is usually possible. Both proofs sound actually
like something that is very hard to imagine without additional
constraints/assumptions.
|
|
0
|
|
|
|
Reply
|
ISO
|
5/3/2010 9:16:32 PM
|
|
On May 2, 11:42=A0pm, James Kanze <james.ka...@gmail.com> wrote:
> The only thing that's been conclusively proven is that the
> SESE idiom never makes the code more difficult to understand.
That is not a true statement.
|
|
0
|
|
|
|
Reply
|
gwowen
|
5/4/2010 9:00:40 AM
|
|
On Apr 28, 1:16=A0am, Juha Nieminen <nos...@thanks.invalid> wrote:
> In comp.lang.c++ Richard Heathfield <r...@see.sig.invalid> wrote:
>
> > Juha Nieminen wrote:
> >> In comp.lang.c++ Richard Heathfield <r...@see.sig.invalid> wrote:
> >>>> =A0 Exactly how do you exit out of a set of nested loops with a "bre=
ak"?
> >>> I don't. I exit out of a set of nested loops using the conditions in =
the
> >>> loop controllers.
>
> >> =A0 The idea was to make the code simpler, cleaner and easier to follo=
w, not
> >> more complicated and contrived.
>
> > Yes. That's precisely why I use the conditions in the loop controllers.
>
> =A0 Care to show an actual example of your "simpler, cleaner and easier t=
o
> follow" version of exiting a nested loop by meddling with the loop
> conditions instead of using 'return'? For example, modify the following
> code to conform to your specifications:
>
> Value_t* MyClass::findValue(const Value_t& value)
> {
> =A0 =A0 for(size_t xInd =3D 0; xInd < data.size(); ++xInd)
> =A0 =A0 =A0 =A0 for(size_t yInd =3D 0; yInd < data[xInd].size(); ++yInd)
> =A0 =A0 =A0 =A0 =A0 =A0 for(size_t zInd =3D 0; zInd < data[xInd][yInd].si=
ze(); ++zInd)
> =A0 =A0 =A0 =A0 =A0 =A0 {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if(data[xInd][yInd][zInd] =3D=3D value)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return &data[xInd][yInd][zInd];
> =A0 =A0 =A0 =A0 =A0 =A0 }
>
> =A0 =A0 return 0;
>
> }
Hi Juha,
I think that you either copied this from a poorly-written beginner C++
book or you failed to understand what the author was attempting to
demonstrate with that kind of code and that you did not 'catch on'
that it is not (in any way) demonstrative of how one walks a series of
sequential cells in the real world.
Why do you insist on writing control structures that serve little
actual purpose? For instance, it should be obvious that you only
require ONE loop and a few conditionals to achieve your desired (or
assumed) goal. E.G...
,---
result =3D value
xInd =3D 0
yInd =3D 0
zInd =3D 0
while ( data[xInd][yInd][zInd] !=3D value && result !=3D 0)
{
++zInd;
if (( zInd < data[xInd][yInd].size() ) !=3D true ) { zInd =3D 0; +
+yInd};
if (( yInd < data[xInd].size() ) !=3D true ) { yInd =3D 0; ++xInd};
if (( xInd < data.size() ) !=3D true ) { result =3D 0 };
}
return result
`---
Of course, this is a rather useless (maybe even retarded) function to
begin with, because it only tells you IF the 'value' is located
"somewhere" within that array -- it gives you absolutely no indication
of "where" in that array you might be able to access the item which
matches your search criteria.
Please pardon any butchering of C++ syntax in my pseudo snippet above
-- I totally lack any C++ training. But we alt.lang.asm folk *do*
have an inkling of how to actually code our way out of a paper bag...
I do believe.
Nathan.
|
|
0
|
|
|
|
Reply
|
Nathan
|
5/6/2010 5:36:41 AM
|
|
On May 6, 2:36=A0pm, Nathan <nathancba...@gmail.com> wrote:
> On Apr 28, 1:16=A0am, Juha Nieminen <nos...@thanks.invalid> wrote:
> > =A0 Care to show an actual example of your "simpler, cleaner and easier=
to
> > follow" version of exiting a nested loop by meddling with the loop
> > conditions instead of using 'return'? For example, modify the following
> > code to conform to your specifications:
>
> > Value_t* MyClass::findValue(const Value_t& value)
> > {
> > =A0 =A0 for(size_t xInd =3D 0; xInd < data.size(); ++xInd)
> > =A0 =A0 =A0 =A0 for(size_t yInd =3D 0; yInd < data[xInd].size(); ++yInd=
)
> > =A0 =A0 =A0 =A0 =A0 =A0 for(size_t zInd =3D 0; zInd < data[xInd][yInd].=
size(); ++zInd)
> > =A0 =A0 =A0 =A0 =A0 =A0 {
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if(data[xInd][yInd][zInd] =3D=3D value)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return &data[xInd][yInd][zInd];
> > =A0 =A0 =A0 =A0 =A0 =A0 }
> > =A0 =A0 return 0;
> > }
>
> Hi Juha,
>
> I think that you either copied this from a poorly-written beginner C++
> book or you failed to understand what the author was attempting to
> demonstrate with that kind of code and that you did not 'catch on'
> that it is not (in any way) demonstrative of how one walks a series of
> sequential cells in the real world.
>
> Why do you insist on writing control structures that serve little
> actual purpose? =A0For instance, it should be obvious that you only
> require ONE loop and a few conditionals to achieve your desired (or
> assumed) goal. =A0E.G...
>
> ,---
> result =3D value
> xInd =3D 0
> yInd =3D 0
> zInd =3D 0
> while ( data[xInd][yInd][zInd] !=3D value && result !=3D 0)
> {
> =A0 =A0 ++zInd;
> =A0 =A0 if (( zInd < data[xInd][yInd].size() ) !=3D true ) { zInd =3D 0; =
+
> +yInd};
> =A0 =A0 if (( yInd < data[xInd].size() ) !=3D true ) { yInd =3D 0; ++xInd=
};
> =A0 =A0 if (( xInd < data.size() ) !=3D true ) { result =3D 0 };}
>
> return result
> `---
Juha did ask for something "simpler, cleaner and easier to follow",
which your single loop is not. Perhaps because of that, your code
needlessly compares yInd and xInd to their respective limits on every
iteration, rather than something like...
while ( data[xInd][yInd][zInd] !=3D value && result !=3D 0)
{
if {++zInd =3D=3D data[xInd][yInd].size()) {
zInd =3D 0;
if (++yInd =3D=3D data[xInd].size()) {
yInd =3D 0;
if (++xInd =3D=3D data.size())
result =3D 0;
}
}
...
More importantly, it can dereference index [0] before checking size(),
so produces undefined behaviour. Anyway, IMHO it's far less clear
(=3Dself-evidently correct & efficient as well as maintainable) than
Juha's code.
> Of course, this is a rather useless (maybe even retarded) function to
> begin with, because it only tells you IF the 'value' is located
> "somewhere" within that array -- it gives you absolutely no indication
> of "where" in that array you might be able to access the item which
> matches your search criteria.
You missed that the original function was returning a pointer to the
matching cell, allowing a change to be made at that location,
considerably more useful than the search-term-else-0-sentinel version
you coded.
> Please pardon any butchering of C++ syntax in my pseudo snippet above
> -- I totally lack any C++ training.
Fair enough... no worries.
>=A0But we alt.lang.asm folk *do*
> have an inkling of how to actually code our way out of a paper bag...
> I do believe.
>
> Nathan.
Your central point that a single loop can serve contributes an
interesting alternative, which I'm sure the readers here will
appreciate, if they bother to look past your smug attitude (which is
quite unwarranted given the serious errors in your implementation)....
Cheers,
Tony
|
|
0
|
|
|
|
Reply
|
tonydee
|
5/6/2010 6:11:11 AM
|
|
On May 6, 2:11=A0am, tonydee <tony_in_da...@yahoo.co.uk> wrote:
> On May 6, 2:36=A0pm, Nathan <nathancba...@gmail.com> wrote:
>
>
>
> > On Apr 28, 1:16=A0am, Juha Nieminen <nos...@thanks.invalid> wrote:
> > > =A0 Care to show an actual example of your "simpler, cleaner and easi=
er to
> > > follow" version of exiting a nested loop by meddling with the loop
> > > conditions instead of using 'return'? For example, modify the followi=
ng
> > > code to conform to your specifications:
>
> > > Value_t* MyClass::findValue(const Value_t& value)
> > > {
> > > =A0 =A0 for(size_t xInd =3D 0; xInd < data.size(); ++xInd)
> > > =A0 =A0 =A0 =A0 for(size_t yInd =3D 0; yInd < data[xInd].size(); ++yI=
nd)
> > > =A0 =A0 =A0 =A0 =A0 =A0 for(size_t zInd =3D 0; zInd < data[xInd][yInd=
].size(); ++zInd)
> > > =A0 =A0 =A0 =A0 =A0 =A0 {
> > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if(data[xInd][yInd][zInd] =3D=3D valu=
e)
> > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 return &data[xInd][yInd][zInd=
];
> > > =A0 =A0 =A0 =A0 =A0 =A0 }
> > > =A0 =A0 return 0;
> > > }
>
> > Hi Juha,
>
> > I think that you either copied this from a poorly-written beginner C++
> > book or you failed to understand what the author was attempting to
> > demonstrate with that kind of code and that you did not 'catch on'
> > that it is not (in any way) demonstrative of how one walks a series of
> > sequential cells in the real world.
>
> > Why do you insist on writing control structures that serve little
> > actual purpose? =A0For instance, it should be obvious that you only
> > require ONE loop and a few conditionals to achieve your desired (or
> > assumed) goal. =A0E.G...
>
> > ,---
> > result =3D value
> > xInd =3D 0
> > yInd =3D 0
> > zInd =3D 0
> > while ( data[xInd][yInd][zInd] !=3D value && result !=3D 0)
> > {
> > =A0 =A0 ++zInd;
> > =A0 =A0 if (( zInd < data[xInd][yInd].size() ) !=3D true ) { zInd =3D 0=
; +
> > +yInd};
> > =A0 =A0 if (( yInd < data[xInd].size() ) !=3D true ) { yInd =3D 0; ++xI=
nd};
> > =A0 =A0 if (( xInd < data.size() ) !=3D true ) { result =3D 0 };}
>
> > return result
> > `---
>
> Juha did ask for something "simpler, cleaner and easier to follow",
> which your single loop is not.
Well, 'y < x' must evaluate as 'true' in order for something to be
classified as simpler. So, because *one loop* < *three loops*, my
version certainly looks simpler. [e.g. less opcodes in the generated
binary ]
>=A0Perhaps because of that, your code
> needlessly compares yInd and xInd to their respective limits on every
> iteration, rather than something like...
>
> =A0 while ( data[xInd][yInd][zInd] !=3D value && result !=3D 0)
> =A0 {
> =A0 =A0 =A0 if {++zInd =3D=3D data[xInd][yInd].size()) {
> =A0 =A0 =A0 =A0 =A0 zInd =3D 0;
> =A0 =A0 =A0 =A0 =A0 if (++yInd =3D=3D data[xInd].size()) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 yInd =3D 0;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (++xInd =3D=3D data.size())
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 result =3D 0;
> =A0 =A0 =A0 =A0 =A0 }
> =A0 =A0 =A0 }
> =A0 ...
>
> More importantly, it can dereference index [0] before checking size(),
> so produces undefined behaviour. =A0Anyway, IMHO it's far less clear
> (=3Dself-evidently correct & efficient as well as maintainable) than
> Juha's code.
>
More maintainable by the original coder... or more maintainable by
someone 'new' to the code??? If this function were many screens in
length, and someone 'new' decides to have it perform an extra task
'just' before returning, wouldn't that person have a "devil of a time"
debugging the program if he were not aware of the hidden alternative
'return' route tucked-away in that nest?
> > Of course, this is a rather useless (maybe even retarded) function to
> > begin with, because it only tells you IF the 'value' is located
> > "somewhere" within that array -- it gives you absolutely no indication
> > of "where" in that array you might be able to access the item which
> > matches your search criteria.
>
> You missed that the original function was returning a pointer to the
> matching cell, allowing a change to be made at that location,
> considerably more useful than the search-term-else-0-sentinel version
> you coded.
>
Ah, the '&' sign, I see it now. I should have "result =3D &data[xInd]
[yInd][zInd]" in the third IF.
> > Please pardon any butchering of C++ syntax in my pseudo snippet above
> > -- I totally lack any C++ training.
>
> Fair enough... no worries.
>
> >=A0But we alt.lang.asm folk *do*
> > have an inkling of how to actually code our way out of a paper bag...
> > I do believe.
>
> > Nathan.
>
> Your central point that a single loop can serve contributes an
> interesting alternative, which I'm sure the readers here will
> appreciate,
Yes, rather than waste one's time bickering about the various esteemed
implementation alternatives of a particular algo, why not consider an
algo that renders those salient points mute?
> if they bother to look past your smug attitude (which is
> quite unwarranted given the serious errors in your implementation)....
>
This is Usenet, we do not charge for the entertainment value. :)
Nathan.
|
|
0
|
|
|
|
Reply
|
Nathan
|
5/6/2010 7:15:38 AM
|
|
Nathan <nathancbaker@gmail.com> writes:
[...]
> ,---
> result = value
> xInd = 0
> yInd = 0
> zInd = 0
> while ( data[xInd][yInd][zInd] != value && result != 0)
> {
> ++zInd;
> if (( zInd < data[xInd][yInd].size() ) != true ) { zInd = 0; +
> +yInd};
> if (( yInd < data[xInd].size() ) != true ) { yInd = 0; ++xInd};
> if (( xInd < data.size() ) != true ) { result = 0 };
> }
> return result
> `---
[...]
A style point: comparisons to true and false are almost always
superfluous. Rather than
if (( xInd < data.size() ) != true )
just write
if ( xInd <= data.size() )
As for the overall structure of your proposed replacement, you've
replaced three nested loops with one loop and three if statements.
Furthermore, the original version only tests zInd on most iterations;
your version tests zInd, yInd, and xInd on every iteration.
The original problem is to traverse a 3-dimensional array. A triple
nested loop is the most obvious way to do that. There might be
some advantages in converting it to a single loop, but clarity
isn't one of them, at least in this case.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
Keith
|
5/6/2010 7:50:26 AM
|
|
"Keith Thompson" <kst-u@mib.org> wrote in message
news:ln4oilxyd9.fsf@nuthaus.mib.org...
>
> A style point: comparisons to true and false are almost always
> superfluous. Rather than
> if (( xInd < data.size() ) != true )
> just write
> if ( xInd <= data.size() )
>
A true point. But I guess, for comparison sake, it is superfluous. :)
> The original problem is to traverse a 3-dimensional array. A triple
> nested loop is the most obvious way to do that. There might be
> some advantages in converting it to a single loop, but clarity
> isn't one of them, at least in this case.
>
I guess, the dragon that I am pointing at, is that CircuitCity does not yet
sell 3-dinensional RAM. So, why not just do...
,---
xyzMax = data[xInd][yInd].size() + data[xInd].size() + data.size();
result = 0;
i = -1;
while ( i < xyzMax )
{
++i;
if ( data[i] = value );
{
result = &data[i];
i = xyzMax;
}
}
return result;
`---
....a linear solution to a linear problem???
Nathan.
|
|
0
|
|
|
|
Reply
|
Nathan
|
5/6/2010 8:51:05 AM
|
|
In article <ln4oilxyd9.fsf@nuthaus.mib.org>,
Keith Thompson <kst-u@mib.org> wrote:
>A style point: comparisons to true and false are almost always
>superfluous. Rather than
> if (( xInd < data.size() ) != true )
>just write
> if ( xInd <= data.size() )
It's not the same thing (``<='' should be ``>='').
>
>As for the overall structure of your proposed replacement, you've
>replaced three nested loops with one loop and three if statements.
>Furthermore, the original version only tests zInd on most iterations;
>your version tests zInd, yInd, and xInd on every iteration.
>
>The original problem is to traverse a 3-dimensional array. A triple
>nested loop is the most obvious way to do that. There might be
>some advantages in converting it to a single loop, but clarity
>isn't one of them, at least in this case.
>
>--
>Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
>Nokia
>"We must do something. This is something. Therefore, we must do this."
> -- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
ike
|
5/6/2010 8:59:42 AM
|
|
"Nathan Baker" <nathancbaker@gmail.com> wrote in message
news:NamdnYqxi6pkH3_WnZ2dnUVZ_oydnZ2d@giganews.com...
> "Keith Thompson" <kst-u@mib.org> wrote in message
> news:ln4oilxyd9.fsf@nuthaus.mib.org...
>>
>> A style point: comparisons to true and false are almost always
>> superfluous. Rather than
>> if (( xInd < data.size() ) != true )
>> just write
>> if ( xInd <= data.size() )
>>
>
> A true point. But I guess, for comparison sake, it is superfluous. :)
>
>> The original problem is to traverse a 3-dimensional array. A triple
>> nested loop is the most obvious way to do that. There might be
>> some advantages in converting it to a single loop, but clarity
>> isn't one of them, at least in this case.
>>
>
> I guess, the dragon that I am pointing at, is that CircuitCity does not
> yet
> sell 3-dinensional RAM.
From the point of a view of program code, memory *is* 3-dimensional. That's
why C's gone to the trouble of providing 3-dimensional arrays.
> xyzMax = data[xInd][yInd].size() + data[xInd].size() + data.size();
> result = 0;
> i = -1;
> while ( i < xyzMax )
> {
> ++i;
> if ( data[i] = value );
> {
> result = &data[i];
> i = xyzMax;
> }
> }
> return result;
> `---
>
> ...a linear solution to a linear problem???
Except the memory layout might not be linear: each inner row might be
allocated in a different place.
--
Bartc
|
|
0
|
|
|
|
Reply
|
bart
|
5/6/2010 10:49:07 AM
|
|
"bart.c" <bartc@freeuk.com> writes:
> "Nathan Baker" <nathancbaker@gmail.com> wrote in message
> news:NamdnYqxi6pkH3_WnZ2dnUVZ_oydnZ2d@giganews.com...
>> "Keith Thompson" <kst-u@mib.org> wrote in message
>> news:ln4oilxyd9.fsf@nuthaus.mib.org...
[...]
>>> The original problem is to traverse a 3-dimensional array. A triple
>>> nested loop is the most obvious way to do that. There might be
>>> some advantages in converting it to a single loop, but clarity
>>> isn't one of them, at least in this case.
>>
>> I guess, the dragon that I am pointing at, is that CircuitCity does
>> not yet sell 3-dinensional RAM.
>
> From the point of a view of program code, memory *is* 3-dimensional. That's
> why C's gone to the trouble of providing 3-dimensional arrays.
Exactly. Your programming isn't, and shouldn't be, limited by RAM
layout. That's why we have programming languages.
[code snipped]
>>
>> ...a linear solution to a linear problem???
It's a 3-dimensional problem.
> Except the memory layout might not be linear: each inner row might be
> allocated in a different place.
No, C arrays are contiguous.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
Keith
|
5/6/2010 3:26:11 PM
|
|
ike@localhost.claranet.nl (Ike Naar) writes:
> In article <ln4oilxyd9.fsf@nuthaus.mib.org>,
> Keith Thompson <kst-u@mib.org> wrote:
>>A style point: comparisons to true and false are almost always
>>superfluous. Rather than
>> if (( xInd < data.size() ) != true )
>>just write
>> if ( xInd <= data.size() )
>
> It's not the same thing (``<='' should be ``>='').
Argh!
It was correct in my head.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
Keith
|
5/6/2010 3:27:17 PM
|
|
"Keith Thompson" <kst-u@mib.org> wrote in message
news:lnr5lpvyp8.fsf@nuthaus.mib.org...
> "bart.c" <bartc@freeuk.com> writes:
>> "Nathan Baker" <nathancbaker@gmail.com> wrote in message
>> news:NamdnYqxi6pkH3_WnZ2dnUVZ_oydnZ2d@giganews.com...
>> Except the memory layout might not be linear: each inner row might be
>> allocated in a different place.
>
> No, C arrays are contiguous.
Flat arrays, yes. But it sounded like this 3D array consisted of pointers to
pointers.
--
Bartc
|
|
0
|
|
|
|
Reply
|
bart
|
5/6/2010 3:55:48 PM
|
|
"bart.c" <bartc@freeuk.com> writes:
> "Keith Thompson" <kst-u@mib.org> wrote in message
> news:lnr5lpvyp8.fsf@nuthaus.mib.org...
>> "bart.c" <bartc@freeuk.com> writes:
>>> "Nathan Baker" <nathancbaker@gmail.com> wrote in message
>>> news:NamdnYqxi6pkH3_WnZ2dnUVZ_oydnZ2d@giganews.com...
>>> Except the memory layout might not be linear: each inner row might be
>>> allocated in a different place.
>>
>> No, C arrays are contiguous.
>
> Flat arrays, yes. But it sounded like this 3D array consisted of
> pointers to pointers.
You're right, that's certainly possible. And since the original
code is C++ (note that this thread is cross-posted), the [] and
other operators could be overloaded.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
Keith
|
5/6/2010 4:46:36 PM
|
|
In comp.lang.c++ Nathan <nathancbaker@gmail.com> wrote:
> On Apr 28, 1:16�am, Juha Nieminen <nos...@thanks.invalid> wrote:
>> Value_t* MyClass::findValue(const Value_t& value)
>> {
>> for(size_t xInd = 0; xInd < data.size(); ++xInd)
>> for(size_t yInd = 0; yInd < data[xInd].size(); ++yInd)
>> for(size_t zInd = 0; zInd < data[xInd][yInd].size(); ++zInd)
>> {
>> if(data[xInd][yInd][zInd] == value)
>> return &data[xInd][yInd][zInd];
>> }
>>
>> return 0;
>> }
>
> Hi Juha,
>
> I think that you either copied this from a poorly-written beginner C++
> book or you failed to understand what the author was attempting to
> demonstrate with that kind of code and that you did not 'catch on'
> that it is not (in any way) demonstrative of how one walks a series of
> sequential cells in the real world.
I don't know if you are being sarcastic, patronizing, or honestly don't
know what you are talking about, but I'll let it pass.
> Why do you insist on writing control structures that serve little
> actual purpose? For instance, it should be obvious that you only
> require ONE loop and a few conditionals to achieve your desired (or
> assumed) goal. E.G...
>
> ,---
> result = value
> xInd = 0
> yInd = 0
> zInd = 0
> while ( data[xInd][yInd][zInd] != value && result != 0)
> {
> ++zInd;
> if (( zInd < data[xInd][yInd].size() ) != true ) { zInd = 0; +
> +yInd};
> if (( yInd < data[xInd].size() ) != true ) { yInd = 0; ++xInd};
> if (( xInd < data.size() ) != true ) { result = 0 };
> }
> return result
> `---
The goal was to make the function simpler, not more complicated.
Your version (even if it's fixed to actually do the same thing, and even
after removing the superfluous conditionals) is significantly more
complicated for many reasons. Most importantly, it uses a strange idiom
which the vast majority of programmers are not familiar with and don't
use (and why would they?) It takes significantly more time to understand
what your code is doing, as well as to verify that it's doing it correctly.
My original version with three nested loops is a lot easier to understand,
and a lot easier to verify that it works correctly.
And what for? It's not more efficient, shorter or does it do anything
that the original wouldn't do. Moreover, it's very possible that in some
similar circumstances a compile could be able to perform better optimizations
on the original nested loop version than yours (eg. by applying loop
unrolling and other optimization techniques).
> Of course, this is a rather useless (maybe even retarded) function to
> begin with, because it only tells you IF the 'value' is located
> "somewhere" within that array -- it gives you absolutely no indication
> of "where" in that array you might be able to access the item which
> matches your search criteria.
Actually the function returns a pointer to the found element, or null
if the element is not found.
|
|
0
|
|
|
|
Reply
|
Juha
|
5/6/2010 4:54:39 PM
|
|
In comp.lang.c++ Nathan <nathancbaker@gmail.com> wrote:
> Well, 'y < x' must evaluate as 'true' in order for something to be
> classified as simpler. So, because *one loop* < *three loops*, my
> version certainly looks simpler. [e.g. less opcodes in the generated
> binary ]
"Simpler" does not mean "produces a smaller executable file" or "has
less loops". "Simpler" means "easier to understand".
Your version may have less loops, but you have replaced them with
complex conditional statements, which are unusual and useless (because
they don't do anything the loops weren't doing already).
(Ironically, your version is also less efficient because it performs
all three index range checks at each iteration, while the nested loop
version does only one index range check for the innermost iteration.)
>> More importantly, it can dereference index [0] before checking size(),
>> so produces undefined behaviour. �Anyway, IMHO it's far less clear
>> (=self-evidently correct & efficient as well as maintainable) than
>> Juha's code.
>>
>
> More maintainable by the original coder... or more maintainable by
> someone 'new' to the code??? If this function were many screens in
> length, and someone 'new' decides to have it perform an extra task
> 'just' before returning, wouldn't that person have a "devil of a time"
> debugging the program if he were not aware of the hidden alternative
> 'return' route tucked-away in that nest?
Even if you had an understandability problem with a "hidden return",
the correct solution is not to make the whole thing an unusual and hard
to understand construct which is probably even less efficient.
> Yes, rather than waste one's time bickering about the various esteemed
> implementation alternatives of a particular algo, why not consider an
> algo that renders those salient points mute?
Because the whole point of this thread is "how to exit nested loops
most cleanly?", not "what is the best way of doing task X?"
|
|
0
|
|
|
|
Reply
|
Juha
|
5/6/2010 5:02:22 PM
|
|
Juha Nieminen <nospam@thanks.invalid> writes:
> In comp.lang.c++ Nathan <nathancbaker@gmail.com> wrote:
>> Well, 'y < x' must evaluate as 'true' in order for something to be
>> classified as simpler. So, because *one loop* < *three loops*, my
>> version certainly looks simpler. [e.g. less opcodes in the generated
>> binary ]
>
> "Simpler" does not mean "produces a smaller executable file" or "has
> less loops". "Simpler" means "easier to understand".
>
> Your version may have less loops, but you have replaced them with
> complex conditional statements, which are unusual and useless (because
> they don't do anything the loops weren't doing already).
>
> (Ironically, your version is also less efficient because it performs
> all three index range checks at each iteration, while the nested loop
> version does only one index range check for the innermost iteration.)
Particularly if that "size()" function involves a counting loop rather
than a value lookup.
--
Online waterways route planner | http://canalplan.eu
Plan trips, see photos, check facilities | http://canalplan.org.uk
|
|
0
|
|
|
|
Reply
|
Nick
|
5/6/2010 6:06:35 PM
|
|
Keith Thompson <kst-u@mib.org> wrote:
> Nathan <nathancbaker@gmail.com> writes:
>
> > ,---
> > result = value
> > xInd = 0
> > yInd = 0
> > zInd = 0
> > while ( data[xInd][yInd][zInd] != value && result != 0)
> > {
> > ++zInd;
> > if (( zInd < data[xInd][yInd].size() ) != true ) { zInd = 0; +
> > +yInd};
> > if (( yInd < data[xInd].size() ) != true ) { yInd = 0; ++xInd};
> > if (( xInd < data.size() ) != true ) { result = 0 };
> > }
> > return result
> > `---
> [...]
>
> A style point: comparisons to true and false are almost always
> superfluous. Rather than
> if (( xInd < data.size() ) != true )
> just write
> if ( xInd <= data.size() )
>
> As for the overall structure of your proposed replacement, you've
> replaced three nested loops with one loop and three if statements.
> Furthermore, the original version only tests zInd on most iterations;
> your version tests zInd, yInd, and xInd on every iteration.
However, his version could easily be modified so it didn't make the
extra tests... As you probably know.
> The original problem is to traverse a 3-dimensional array. A triple
> nested loop is the most obvious way to do that. There might be
> some advantages in converting it to a single loop, but clarity
> isn't one of them, at least in this case.
I think there is some confusion here, the original problem is to return
the first element in the container that equals a particular value. Using
three loops to iterate through one container is unnecessary. i.e.,
iterator result = data.begin();
while (result != data.end() && *result != value)
++result;
return result;
A solution very much like the above could even be done in C on an actual
three dimensional array...
|
|
0
|
|
|
|
Reply
|
Daniel
|
5/7/2010 4:18:50 AM
|
|
In article
<7ec1a55b-4a14-46c3-bb65-dd5de1aa370b@n15g2000yqf.googlegroups.com>,
tonydee <tony_in_da_uk@yahoo.co.uk> wrote:
> On May 6, 2:36�pm, Nathan <nathancba...@gmail.com> wrote:
> > On Apr 28, 1:16�am, Juha Nieminen <nos...@thanks.invalid> wrote:
> > > � Care to show an actual example of your "simpler, cleaner and easier to
> > > follow" version of exiting a nested loop by meddling with the loop
> > > conditions instead of using 'return'? For example, modify the following
> > > code to conform to your specifications:
> >
> > > Value_t* MyClass::findValue(const Value_t& value)
> > > {
> > > � � for(size_t xInd = 0; xInd < data.size(); ++xInd)
> > > � � � � for(size_t yInd = 0; yInd < data[xInd].size(); ++yInd)
> > > � � � � � � for(size_t zInd = 0; zInd < data[xInd][yInd].size(); ++zInd)
> > > � � � � � � {
> > > � � � � � � � � if(data[xInd][yInd][zInd] == value)
> > > � � � � � � � � � � return &data[xInd][yInd][zInd];
> > > � � � � � � }
> > > � � return 0;
> > > }
> >
> > Hi Juha,
> >
> > I think that you either copied this from a poorly-written beginner C++
> > book or you failed to understand what the author was attempting to
> > demonstrate with that kind of code and that you did not 'catch on'
> > that it is not (in any way) demonstrative of how one walks a series of
> > sequential cells in the real world.
> >
> > Why do you insist on writing control structures that serve little
> > actual purpose? �For instance, it should be obvious that you only
> > require ONE loop and a few conditionals to achieve your desired (or
> > assumed) goal. �E.G...
> >
> > ,---
> > result = value
> > xInd = 0
> > yInd = 0
> > zInd = 0
> > while ( data[xInd][yInd][zInd] != value && result != 0)
> > {
> > � � ++zInd;
> > � � if (( zInd < data[xInd][yInd].size() ) != true ) { zInd = 0; +
> > +yInd};
> > � � if (( yInd < data[xInd].size() ) != true ) { yInd = 0; ++xInd};
> > � � if (( xInd < data.size() ) != true ) { result = 0 };}
> >
> > return result
> > `---
>
> Juha did ask for something "simpler, cleaner and easier to follow",
> which your single loop is not. Perhaps because of that, your code
> needlessly compares yInd and xInd to their respective limits on every
> iteration, rather than something like...
>
> while ( data[xInd][yInd][zInd] != value && result != 0)
> {
> if {++zInd == data[xInd][yInd].size()) {
> zInd = 0;
> if (++yInd == data[xInd].size()) {
> yInd = 0;
> if (++xInd == data.size())
> result = 0;
> }
> }
> ...
>
> More importantly, it can dereference index [0] before checking size(),
> so produces undefined behaviour. Anyway, IMHO it's far less clear
> (=self-evidently correct & efficient as well as maintainable) than
> Juha's code.
>
> > Of course, this is a rather useless (maybe even retarded) function to
> > begin with, because it only tells you IF the 'value' is located
> > "somewhere" within that array -- it gives you absolutely no indication
> > of "where" in that array you might be able to access the item which
> > matches your search criteria.
>
> You missed that the original function was returning a pointer to the
> matching cell, allowing a change to be made at that location,
> considerably more useful than the search-term-else-0-sentinel version
> you coded.
>
> > Please pardon any butchering of C++ syntax in my pseudo snippet above
> > -- I totally lack any C++ training.
>
> Fair enough... no worries.
>
> >�But we alt.lang.asm folk *do*
> > have an inkling of how to actually code our way out of a paper bag...
> > I do believe.
> >
> > Nathan.
>
> Your central point that a single loop can serve contributes an
> interesting alternative, which I'm sure the readers here will
> appreciate, if they bother to look past your smug attitude (which is
> quite unwarranted given the serious errors in your implementation)....
I posted a single loop alternative last week or so. I think it is a much
better solution than Juha's original.
|
|
0
|
|
|
|
Reply
|
Daniel
|
5/7/2010 4:23:26 AM
|
|
"Juha Nieminen" <nospam@thanks.invalid> ha scritto nel messaggio
news:4be2f44f$0$11839$7b1e8fa0@news.nbl.fi...
> In comp.lang.c++ Nathan <nathancbaker@gmail.com> wrote:
>> On Apr 28, 1:16 am, Juha Nieminen <nos...@thanks.invalid> wrote:
>>> Value_t* MyClass::findValue(const Value_t& value)
>>> {
>>> for(size_t xInd = 0; xInd < data.size(); ++xInd)
pheraps i don't understand C or C++;
are you sure that "data.size()" return the max index of x?
in how i read it, it could return the number of NxNxN table elements
or the size in bytes of data object
than where "data" came from: is it global?
>>> for(size_t yInd = 0; yInd < data[xInd].size(); ++yInd)
>>> for(size_t zInd = 0; zInd < data[xInd][yInd].size(); ++zInd)
>>> {
>>> if(data[xInd][yInd][zInd] == value)
>>> return &data[xInd][yInd][zInd];
>>> }
>>>
>>> return 0;
>>> }
could be this ok for a mXmXm matrix that has the index in the
same range 0..m?
Value_t* MyClass::findValue(Value_t& value)
{size_t x, y, z, m;
m=sizeof(data)/sizeof(data[0][0][0]);
m=sqrt3(m); // 3 radix
for(x=0; x <m; ++x )
for(y=0; y<m; ++y)
for(z=0; z<m; ++z)
if(data[x][y][z]==value)
return &data[x][y][z];
return 0;
}
>> Hi Juha,
>>
>> I think that you either copied this from a poorly-written beginner C++
>> book or you failed to understand what the author was attempting to
>> demonstrate with that kind of code and that you did not 'catch on'
>> that it is not (in any way) demonstrative of how one walks a series of
>> sequential cells in the real world.
>
> I don't know if you are being sarcastic, patronizing, or honestly don't
> know what you are talking about, but I'll let it pass.
in the code you write, for me nothing is clear
it is not question if "is it easy?", it is question "is it right?"
>> Why do you insist on writing control structures that serve little
>> actual purpose? For instance, it should be obvious that you only
>> require ONE loop and a few conditionals to achieve your desired (or
>> assumed) goal. E.G...
>>
>> ,---
>> result = value
>> xInd = 0
>> yInd = 0
>> zInd = 0
>> while ( data[xInd][yInd][zInd] != value && result != 0)
>> {
>> ++zInd;
>> if (( zInd < data[xInd][yInd].size() ) != true ) { zInd = 0; +
>> +yInd};
>> if (( yInd < data[xInd].size() ) != true ) { yInd = 0; ++xInd};
>> if (( xInd < data.size() ) != true ) { result = 0 };
>> }
>> return result
>> `---
>
> The goal was to make the function simpler, not more complicated.
> Your version (even if it's fixed to actually do the same thing, and even
> after removing the superfluous conditionals) is significantly more
> complicated for many reasons. Most importantly, it uses a strange idiom
> which the vast majority of programmers are not familiar with and don't
> use (and why would they?) It takes significantly more time to understand
> what your code is doing, as well as to verify that it's doing it correctly.
> My original version with three nested loops is a lot easier to understand,
> and a lot easier to verify that it works correctly.
>
> And what for? It's not more efficient, shorter or does it do anything
> that the original wouldn't do. Moreover, it's very possible that in some
> similar circumstances a compile could be able to perform better optimizations
> on the original nested loop version than yours (eg. by applying loop
> unrolling and other optimization techniques).
>
>> Of course, this is a rather useless (maybe even retarded) function to
>> begin with, because it only tells you IF the 'value' is located
>> "somewhere" within that array -- it gives you absolutely no indication
>> of "where" in that array you might be able to access the item which
>> matches your search criteria.
>
> Actually the function returns a pointer to the found element, or null
> if the element is not found.
|
|
0
|
|
|
|
Reply
|
io_x
|
5/7/2010 8:16:01 AM
|
|
On 6 May, 08:50, Keith Thompson <ks...@mib.org> wrote:
> The original problem is to traverse a 3-dimensional array. =A0A triple
> nested loop is the most obvious way to do that. =A0There might be
> some advantages in converting it to a single loop, but clarity
> isn't one of them, at least in this case.
I considered submitting a single loop solution as a joke. It never
crossed my mind someone would seriusly propose it!
|
|
0
|
|
|
|
Reply
|
Nick
|
5/7/2010 8:17:11 AM
|
|
In comp.lang.c++ io_x <a@b.c.invalid> wrote:
> pheraps i don't understand C or C++;
> are you sure that "data.size()" return the max index of x?
Standard C++ data containers use the size() member function to tell the
amount of elements.
> than where "data" came from: is it global?
Does it matter?
Anyways, since this was clearly a member function implementation, it's
safe to assume that 'data' is a member variable (well, I could have used
an even better name, such as 'mData', but as I said, it doesn't really
matter).
> could be this ok for a mXmXm matrix that has the index in the
> same range 0..m?
>
> Value_t* MyClass::findValue(Value_t& value)
> {size_t x, y, z, m;
> m=sizeof(data)/sizeof(data[0][0][0]);
> m=sqrt3(m); // 3 radix
> for(x=0; x <m; ++x )
> for(y=0; y<m; ++y)
> for(z=0; z<m; ++z)
> if(data[x][y][z]==value)
> return &data[x][y][z];
> return 0;
> }
What the function is doing isn't important. The point is how to exit
the nested loops most cleanly.
> in the code you write, for me nothing is clear
> it is not question if "is it easy?", it is question "is it right?"
Well, knowing the language is helpful.
|
|
0
|
|
|
|
Reply
|
Juha
|
5/7/2010 10:34:24 AM
|
|
Nick Keighley <nick_keighley_nospam@hotmail.com> wrote:
> On 6 May, 08:50, Keith Thompson <ks...@mib.org> wrote:
>
> > The original problem is to traverse a 3-dimensional array. �A triple
> > nested loop is the most obvious way to do that. �There might be
> > some advantages in converting it to a single loop, but clarity
> > isn't one of them, at least in this case.
>
> I considered submitting a single loop solution as a joke. It never
> crossed my mind someone would seriusly propose it!
I seriously proposed it. I think it is the best solution for the job
(not your code specifically of course, but the idea of a single loop
traversing a single container.)
|
|
0
|
|
|
|
Reply
|
Daniel
|
5/7/2010 2:16:53 PM
|
|
"Daniel T." <daniel_t@earthlink.net> writes:
> Nick Keighley <nick_keighley_nospam@hotmail.com> wrote:
>> On 6 May, 08:50, Keith Thompson <ks...@mib.org> wrote:
>>
>> > The original problem is to traverse a 3-dimensional array. A triple
>> > nested loop is the most obvious way to do that. There might be
>> > some advantages in converting it to a single loop, but clarity
>> > isn't one of them, at least in this case.
>>
>> I considered submitting a single loop solution as a joke. It never
>> crossed my mind someone would seriusly propose it!
>
> I seriously proposed it. I think it is the best solution for the job
> (not your code specifically of course, but the idea of a single loop
> traversing a single container.)
Can a container contain another container, which in turn contains
another container? If so, isn't a nested loop the most natural way to
traverse the elements?
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
Keith
|
5/7/2010 3:56:37 PM
|
|
In alt.lang.asm [FUp set] Keith Thompson <kst-u@mib.org> wrote in part:
> "Daniel T." <daniel_t@earthlink.net> writes:
>> I seriously proposed it. I think it is the best solution
>> for the job (not your code specifically of course, but
>> the idea of a single loop traversing a single container.)
>
> Can a container contain another container, which in turn
> contains another container? If so, isn't a nested loop
> the most natural way to traverse the elements?
Natural, perhaps. Not necessarily the most efficient.
Index calculations can be a significant component of multiply
nested structures [multi-d arrays]. For many operations,
the order of processing is unimportant so why not rip through
it in memory order rather than a big game of RAM hopscotch?
-- Robert
|
|
0
|
|
|
|
Reply
|
Robert
|
5/7/2010 5:42:34 PM
|
|
Nathan tried to convince HLL-folks :)
....
> Please pardon any butchering of C++ syntax in my pseudo snippet above
> -- I totally lack any C++ training. But we alt.lang.asm folk *do*
> have an inkling of how to actually code our way out of a paper bag...
> I do believe.
Ok Nate, we had enough discussions on this matter since HLLs
entered our progamming world ...
We better give up arguing and let the 'faster' programmers
be proud of their 'maintainable/foolproof-readable' sources
which are awful detours with "abstraction layers" while the
few hardware freaks like me work on "really existing things" :)
I don't like to start a war of flames or to pick on any
programmers choice for HLL. But there might be a good
reason for Asm-groups are apart from c/c+-/etc..-groups.
__
wolfgang
I don't 'believe', but I 'know !'
(now at least how my code affects any given hardware)
|
|
0
|
|
|
|
Reply
|
wolfgang
|
5/7/2010 6:32:32 PM
|
|
Keith Thompson <kst-u@mib.org> wrote:
> "Daniel T." <daniel_t@earthlink.net> writes:
> > Nick Keighley <nick_keighley_nospam@hotmail.com> wrote:
> > > On 6 May, 08:50, Keith Thompson <ks...@mib.org> wrote:
> > >
> > > > The original problem is to traverse a 3-dimensional array. A triple
> > > > nested loop is the most obvious way to do that. There might be
> > > > some advantages in converting it to a single loop, but clarity
> > > > isn't one of them, at least in this case.
> > >
> > > I considered submitting a single loop solution as a joke. It never
> > > crossed my mind someone would seriusly propose it!
> >
> > I seriously proposed it. I think it is the best solution for the job
> > (not your code specifically of course, but the idea of a single loop
> > traversing a single container.)
>
> Can a container contain another container, which in turn contains
> another container? If so, isn't a nested loop the most natural way to
> traverse the elements?
Then you would need an infinite number of find functions, one for each
dimension count. (i.e., a find for 1D arrays, a find for 2D arrays, a
find for 3D arrays, a find for 4D arrays, etc.) That's silly.
http://en.wikipedia.org/wiki/Zero_One_Infinity
|
|
0
|
|
|
|
Reply
|
Daniel
|
5/7/2010 6:33:30 PM
|
|
Daniel T. wrote:
> Keith Thompson <kst-u@mib.org> wrote:
>> "Daniel T." <daniel_t@earthlink.net> writes:
>> > Nick Keighley <nick_keighley_nospam@hotmail.com> wrote:
>> > > On 6 May, 08:50, Keith Thompson <ks...@mib.org> wrote:
>> > >
>> > > > The original problem is to traverse a 3-dimensional array. � A
>> > > > triple nested loop is the most obvious way to do that. � There
>> > > > might be some advantages in converting it to a single loop, but
>> > > > clarity isn't one of them, at least in this case.
>> > >
>> > > I considered submitting a single loop solution as a joke. It never
>> > > crossed my mind someone would seriusly propose it!
>> >
>> > I seriously proposed it. I think it is the best solution for the job
>> > (not your code specifically of course, but the idea of a single loop
>> > traversing a single container.)
>>
>> Can a container contain another container, which in turn contains
>> another container? If so, isn't a nested loop the most natural way to
>> traverse the elements?
>
> Then you would need an infinite number of find functions, one for each
> dimension count. (i.e., a find for 1D arrays, a find for 2D arrays, a
> find for 3D arrays, a find for 4D arrays, etc.) That's silly.
Huh? What is silly about that? You need an infinite number of member access
functions data(i), data(i,j), data(i,j,k), ... anyway (or with other syntax
data[i], data[i][j], ...). Of course, you only need those of these
infinitely many for which containers of that dimension are actually in your
code.
And if you have a container that implements different dimensions at run-
time, it could provide a single find() function that returns a multi-index
(say as a sequence or via an output iterator). Come to think of it, you
could also have that very same interface for the various fixed-dimension
containers. However, the functions would differ in implementation since
there a many, many ways to implement multi-dimensional container types.
Best
Kai-Uwe Bux
|
|
0
|
|
|
|
Reply
|
Kai
|
5/7/2010 6:54:09 PM
|
|
On 05/08/10 04:33, Daniel T. wrote:
> Keith Thompson <kst-u@mib.org> wrote:
>> "Daniel T." <daniel_t@earthlink.net> writes:
>>> Nick Keighley <nick_keighley_nospam@hotmail.com> wrote:
>>>> On 6 May, 08:50, Keith Thompson <ks...@mib.org> wrote:
>>>>
>>>>> The original problem is to traverse a 3-dimensional array. A triple
>>>>> nested loop is the most obvious way to do that. There might be
>>>>> some advantages in converting it to a single loop, but clarity
>>>>> isn't one of them, at least in this case.
>>>>
>>>> I considered submitting a single loop solution as a joke. It never
>>>> crossed my mind someone would seriusly propose it!
>>>
>>> I seriously proposed it. I think it is the best solution for the job
>>> (not your code specifically of course, but the idea of a single loop
>>> traversing a single container.)
>>
>> Can a container contain another container, which in turn contains
>> another container? If so, isn't a nested loop the most natural way to
>> traverse the elements?
>
> Then you would need an infinite number of find functions, one for each
> dimension count. (i.e., a find for 1D arrays, a find for 2D arrays, a
> find for 3D arrays, a find for 4D arrays, etc.) That's silly.
I've never heard of any programming languages that doesn't support
recursion.
|
|
0
|
|
|
|
Reply
|
Lie
|
5/8/2010 12:39:56 AM
|
|
On 05/08/10 10:39, Lie Ryan wrote:
> On 05/08/10 04:33, Daniel T. wrote:
>> Keith Thompson <kst-u@mib.org> wrote:
>>> "Daniel T." <daniel_t@earthlink.net> writes:
>>>> Nick Keighley <nick_keighley_nospam@hotmail.com> wrote:
>>>>> On 6 May, 08:50, Keith Thompson <ks...@mib.org> wrote:
>>>>>
>>>>>> The original problem is to traverse a 3-dimensional array. A triple
>>>>>> nested loop is the most obvious way to do that. There might be
>>>>>> some advantages in converting it to a single loop, but clarity
>>>>>> isn't one of them, at least in this case.
>>>>>
>>>>> I considered submitting a single loop solution as a joke. It never
>>>>> crossed my mind someone would seriusly propose it!
>>>>
>>>> I seriously proposed it. I think it is the best solution for the job
>>>> (not your code specifically of course, but the idea of a single loop
>>>> traversing a single container.)
>>>
>>> Can a container contain another container, which in turn contains
>>> another container? If so, isn't a nested loop the most natural way to
>>> traverse the elements?
>>
>> Then you would need an infinite number of find functions, one for each
>> dimension count. (i.e., a find for 1D arrays, a find for 2D arrays, a
>> find for 3D arrays, a find for 4D arrays, etc.) That's silly.
>
> I've never heard of any programming languages that doesn't support
> recursion.
except for assembly, perhaps... or some very ancient or jokular languages
|
|
0
|
|
|
|
Reply
|
Lie
|
5/8/2010 12:41:22 AM
|
|
"Lie Ryan" <lie.1296@gmail.com> ha scritto nel messaggio
news:4be4b38f$1@dnews.tpgi.com.au...
> On 05/08/10 10:39, Lie Ryan wrote:
>> On 05/08/10 04:33, Daniel T. wrote:
>>> Keith Thompson <kst-u@mib.org> wrote:
>>>> "Daniel T." <daniel_t@earthlink.net> writes:
>>>>> Nick Keighley <nick_keighley_nospam@hotmail.com> wrote:
>>>>>> On 6 May, 08:50, Keith Thompson <ks...@mib.org> wrote:
>> I've never heard of any programming languages that doesn't support
>> recursion.
>
> except for assembly, perhaps... or some very ancient or jokular languages
with assembly is possible to write recursions functions too
|
|
0
|
|
|
|
Reply
|
io_x
|
5/8/2010 6:50:58 AM
|
|
In comp.lang.c++ io_x <a@b.c.invalid> wrote:
> with assembly is possible to write recursions functions too
That's like saying that C supports object-oriented programming.
|
|
0
|
|
|
|
Reply
|
Juha
|
5/8/2010 7:07:59 AM
|
|
On May 8, 1:39=A0am, Lie Ryan <lie.1...@gmail.com> wrote:
> I've never heard of any programming languages that doesn't support
> recursion.
Standard Fortran, prior to 1990. It was not a bad idea, given the
limited stack space on most machines, and the likelihood of stack
overflow. Especially given you can always do tail recursion by hand
(ObOnTopic: ... using goto.)
|
|
0
|
|
|
|
Reply
|
gwowen
|
5/8/2010 8:46:17 AM
|
|
"Juha Nieminen" <nospam@thanks.invalid> wrote in message
news:4be50dcf$0$2544$7b1e8fa0@news.nbl.fi...
> In comp.lang.c++ io_x <a@b.c.invalid> wrote:
>> with assembly is possible to write recursions functions too
>
> That's like saying that C supports object-oriented programming.
Of course it does! C certainly has support for data structures.
There is absolutely no high-level language feature that can't also be
implemented in C and ASM.
Nathan.
|
|
0
|
|
|
|
Reply
|
Nathan
|
5/8/2010 10:25:59 AM
|
|
"Daniel T." <daniel_t@earthlink.net> wrote in message
news:daniel_t-BE6842.14333007052010@70-3-168-216.pools.spcsdns.net...
>> Can a container contain another container, which in turn contains
>> another container? If so, isn't a nested loop the most natural way to
>> traverse the elements?
>
> Then you would need an infinite number of find functions, one for each
> dimension count. (i.e., a find for 1D arrays, a find for 2D arrays, a
> find for 3D arrays, a find for 4D arrays, etc.) That's silly.
>
> http://en.wikipedia.org/wiki/Zero_One_Infinity
Maybe our entire 4D universe is represented by a 1D array?? If so, screw
the warp drive... we just need to arrange a buffer-overflow, insert our own
code (guess we need to know what processor it runs on) and we can transport
ourselves to another planet in an instant. :)
Nathan.
|
|
0
|
|
|
|
Reply
|
Nathan
|
5/8/2010 10:34:13 AM
|
|
"wolfgang kern" <nowhere@never.at> wrote in message
news:hs1msu$9ca$1@newsreader2.utanet.at...
>
> Ok Nate, we had enough discussions on this matter since HLLs
> entered our progamming world ...
> We better give up arguing and let the 'faster' programmers
> be proud of their 'maintainable/foolproof-readable' sources
> which are awful detours with "abstraction layers" while the
> few hardware freaks like me work on "really existing things" :)
>
The CPU experiences a nightmare while executing HLL code. Perhaps there is
an instructive way for us to demonstrate this fact?
Nathan.
|
|
0
|
|
|
|
Reply
|
Nathan
|
5/8/2010 10:46:58 AM
|
|
"Nathan Baker" <nathancbaker@gmail.com> wrote in message
news:4-Wdnf4R-ruqoXjWnZ2dnUVZ_tydnZ2d@giganews.com...
>
> "Juha Nieminen" <nospam@thanks.invalid> wrote in message
> news:4be50dcf$0$2544$7b1e8fa0@news.nbl.fi...
>> In comp.lang.c++ io_x <a@b.c.invalid> wrote:
>>> with assembly is possible to write recursions functions too
>>
>> That's like saying that C supports object-oriented programming.
>
> Of course it does! C certainly has support for data structures.
>
> There is absolutely no high-level language feature that can't also be
> implemented in C and ASM.
Nor as machine code, microcode, or even as a bunch of integrated circuits or
logic gates or transistors. But you wouldn't want to.
--
Bartc
|
|
0
|
|
|
|
Reply
|
bart
|
5/8/2010 1:47:57 PM
|
|
On 8 May, 01:41, Lie Ryan <lie.1...@gmail.com> wrote:
> > I've never heard of any programming languages that doesn't support
> > recursion.
>
> except for assembly, perhaps... or some very ancient or jokular languages
FORTRAN (in its original form), Coral-66 you had to use a special
keyword to indicate a function was recursive. Some BASICs probably
didn't alow recursion. But these all qualify as "ancient" (and maybe
jocular!)
|
|
0
|
|
|
|
Reply
|
Nick
|
5/8/2010 4:32:35 PM
|
|
On 8 May, 07:50, "io_x" <a...@b.c.invalid> wrote:
> "Lie Ryan" <lie.1...@gmail.com> ha scritto nel messaggionews:4be4b38f$1@dnews.tpgi.com.au...
> > On 05/08/10 10:39, Lie Ryan wrote:
> >> I've never heard of any programming languages that doesn't support
> >> recursion.
>
> > except for assembly, perhaps... or some very ancient or jokular languages
>
> with assembly is possible to write recursions functions too
depends on the architecture
|
|
0
|
|
|
|
Reply
|
Nick
|
5/8/2010 4:33:16 PM
|
|
On 8 May, 11:25, "Nathan Baker" <nathancba...@gmail.com> wrote:
> "Juha Nieminen" <nos...@thanks.invalid> wrote in message
> news:4be50dcf$0$2544$7b1e8fa0@news.nbl.fi...
> > In comp.lang.c++ io_x <a...@b.c.invalid> wrote:
> >> with assembly is possible to write recursions functions too
>
> > =A0That's like saying that C supports object-oriented programming.
>
> Of course it does! =A0C certainly has support for data structures.
>
> There is absolutely no high-level language feature that can't also be
> implemented in C and ASM.
the Turing tar pit where everything is possible and nothing is
feasible
|
|
0
|
|
|
|
Reply
|
Nick
|
5/8/2010 4:34:33 PM
|
|
Juha Nieminen <nospam@thanks.invalid> writes:
> In comp.lang.c++ io_x <a@b.c.invalid> wrote:
>> with assembly is possible to write recursions functions too
>
> That's like saying that C supports object-oriented programming.
Depending on the architecure, not really. Supporting full
object-orientation in C can be quite difficult. For some assembly
languages (certainly for the very few I've used), recursion is just
a matter of having a subroutine call itself.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
|
|
0
|
|
|
|
Reply
|
Keith
|
5/8/2010 4:41:22 PM
|
|
In article
<5dd9bdc8-4dc4-4537-84a0-885c4c92f7cd@l28g2000yqd.googlegroups.com>,
Nick Keighley <nick_keighley_nospam@hotmail.com> wrote:
> On 8 May, 01:41, Lie Ryan <lie.1...@gmail.com> wrote:
>
> > > I've never heard of any programming languages that doesn't support
> > > recursion.
> >
> > except for assembly, perhaps... or some very ancient or jokular languages
>
> FORTRAN (in its original form), Coral-66 you had to use a special
> keyword to indicate a function was recursive. Some BASICs probably
> didn't alow recursion. But these all qualify as "ancient" (and maybe
> jocular!)
What FORTRAN are you referring to. I never saw it in any FORTRAN up to
1978 (the last time I used FORTRAN).
--
Tim
"That excessive bail ought not to be required, nor excessive fines imposed,
nor cruel and unusual punishments inflicted" -- Bill of Rights 1689
|
|
0
|
|
|
|
Reply
|
Tim
|
5/8/2010 4:46:58 PM
|
|
Keith Thompson <kst-u@mib.org> writes:
> Juha Nieminen <nospam@thanks.invalid> writes:
>> In comp.lang.c++ io_x <a@b.c.invalid> wrote:
>>> with assembly is possible to write recursions functions too
>>
>> That's like saying that C supports object-oriented programming.
>
> Depending on the architecure, not really. Supporting full
> object-orientation in C can be quite difficult. For some assembly
> languages (certainly for the very few I've used), recursion is just
> a matter of having a subroutine call itself.
And, in all but the most trivial cases, using a couple of push/pop
instructions to keep some state between calls. It's certainly easier to
write recursive functions in assembly than in old "line number only and
no local variables" BASIC.
--
Online waterways route planner | http://canalplan.eu
Plan trips, see photos, check facilities | http://canalplan.org.uk
|
|
0
|
|
|
|
Reply
|
Nick
|
5/8/2010 6:57:21 PM
|
|
"io_x" <a@b.c.invalid> ha scritto nel messaggio
news:4bdda3e7$0$1112$4fafbaef@reader4.news.tin.it...
> "Red Rooster" ha scritto nel messaggio
> I advise them it could be not always so,
> there could be one language in wicht goto is easy :)
for example in these days i wrote this function for one sub-window
that gets data
90% of lines has at last one goto, #, jc, jmp etc
i'm naturally sloppy, doing some math count with my fingers
i'm not much smart, not remember [nor want remember] somting like many OS api
how is possible that both this routine and its sub-windows goes well?
it call the server, send data, and set the right answer
; void DialogButtonClick(u32 Handle, u32 Message)
; 0j, 4i, 8Ra, 12Handle, 16Message
; 2048, 2052, 2056, 2060, 2064
; 0k,4j,8i,12b,16Ra, 20P_Handle, 24P_Message +2048
; 2068 2072
align 4
DialogButtonClickCliente:
<b,i,j,k
<< NConto=160
s-=2048
; iint3
i=^2068|a=^2072|#.1
..e: a=0| stc| ##.z
..1: a==ID_DC_BTN_INVIA!#.8
a=s|D*s=0|SetDlgItemTextA(i, ID_DC_ED_RISULTATO, a)
; iint3
DC_VerificaCampi(i)|jnc .1a
..1e: DC_StampaErrore(i,a)|#.9 ; caso errore non sanabile
; controlli dopo questo punto
; tipo "GetDlgItemTextA(,,)|a<=0?#.9"
; dovrebbero essere inutili poiche' sono
; stati fatti in DC_VerificaCampi(i)
..1a: a==2!#.2 ; n conto inesistente => cerca dal nome e cognome n conto
a=NomeDaInviare |GetDlgItemTextA(i, ID_DC_ED_NOME1, a,
32)|a<=0?#.9
a=NomeDaInviare |IsSpaceString_m(a)|a==1#.9
a=CognomeDaInviare|GetDlgItemTextA(i, ID_DC_ED_COGNOME1, a,
32)|a<=0?#.9
a=CognomeDaInviare|IsSpaceString_m(a)|a==1#.9
k=NomeDaInviare |j=CercaNumeroDalNomeCognome
; Quando si preme il tasto invia
; se esiste un tread [risposta attesa] => segnala errore [esiste
gia' operazione]
; altrimenti
; apre un thread con il compito di aggiornare tutti i campi
; di cui ID_MD_ED_RISULTATO e' quello che il tread puo'
scrivere
; insieme a ID_MD_ED_NCONTO
..1aa: D*trhandle#.1c ; in trhandle il solo thread apribile
..1b: a=&^64|*a=i|*a+4=k|D*a+8=0|r=&^16 ; D*a+8==1 finestra
principale
; D*a+8==0 finestra cliente
CreateThread(0, 0, j, a, 0, r)|a==0#.1e
*trhandle=a|#.9
..1c: a=*trhandle|c=s|GetExitCodeThread(a, c)|a==0#.1e
a^=a
D*s!=&STILL_ACTIVE!#.1e ; se il processo e' terminato
a=*trhandle|CloseHandle(a)|a==0#.1e|D*trhandle=0|#.1b
#.9
..2: a==3!#.3 ; n conto presente ma assenti nome e cognome =>
; cerca nome e cognome dal numero di conto
a=&*s+NConto|GetDlgItemTextA(i, ID_DC_ED_NCONTO, a, 32)|a<=0?#.9
k=&*s+NConto|j=DC_CercaDalContoCliente|#.1aa
#.9
..3: a#.9 ; a==0 significa estono il numero conto e anche i nomi e cognomi
a=&^24|CB_GetText(a, 40, i, ID_DC_CMB_OPERAZIONI)|jc .9
c==0!#.4 ; inserisci nuovo cliente
k=0 ; k not used
j=DC_InserisciCliente|#.1aa
#.9
..4: c==1!#.5 ; elimina cliente
k=0 ; k not used
j=DC_EliminaCliente|#.1aa
#.9
..5: ; variazione dei dati cliente
#.9
..8: a==ID_DC_BTN_AZZERA!#.9
azzeraFormCliente(i)
..9: a=1|clc
..z:
s=&*s+2048
>> NConto
>b,i,j,k
ret 8
|
|
0
|
|
|
|
Reply
|
io_x
|
5/8/2010 6:59:58 PM
|
|
Juha Nieminen wrote:
> In comp.lang.c++ Richard Heathfield <rjh@see.sig.invalid> wrote:
>> Juha Nieminen wrote:
>>> In comp.lang.c++ Richard Heathfield <rjh@see.sig.invalid> wrote:
>>>> If the data are sorted, bsearch.
>>>>
>>>> If not, why not?
>>>>
>>>> In any case, your loop condition expressions do not correctly describe
>>>> the conditions under which the loop will terminate. Please rewrite your
>>>> example so that they do, and then by all means ask me again if you wish.
>>> No offense, but it always amuses me how some C programmers try to
>>> wiggle themselves out of actually giving honest answers when they are
>>> presented with problematic situations related to their coding style, C,
>>> or both.
>> Your paragraph, above, is a classic example.
>
> You know, an answer of "no, you are" is rather childish. How about
> presenting some actual arguments instead?
Well, I thought I had done so. Sorry for the late reply, by the way -
I've been kinda busy.
> I gave you a piece of code and asked you to modify it to conform to
> your principles. You did not do that. Who is trying to avoid answering
> to a challenge here?
Oh, I can modify it easily enough, and I am reasonably confident of how
you'll react to the modification, but here it is anyway. I am too
lazy/tired to look up your original code now, but IIRC basically you're
searching through an unsorted 3D array, which I would do along these lines:
/* p is a pointer to a valid "struct point" object, with x, y, and z
members */
int 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)
{
found = 1;
point_assign(p, x, y, z); /* that is, p.x = x; p.y = y, etc */
}
}
}
}
return found;
And I know you're not going to like the extra tests any more than I like
your early returns. Style issue.
<snip>
>>> Is it *really* that hard to simply say "yes, in this particular example
>>> the 'return' is indeed the simplest way"? Does it hurt your pride or
>>> something?
>> What has pride got to do with it? It's common sense, that's all. The
>> simplest way (and one of the fastest) to get from Tower Bridge Approach
>> to St Katharine's Way is to jump off the bridge, but that doesn't
>> necessarily mean it's the /best/ way.
>
> Then kindly show me this "best way".
One man's best is another man's mediocre, and a third man's worst. <shrug>
--
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
|
|
0
|
|
|
|
Reply
|
Richard
|
5/8/2010 8:57:57 PM
|
|
Juha Nieminen wrote:
> In comp.lang.c++ Richard Heathfield <rjh@see.sig.invalid> wrote:
>> Seebs wrote:
>>> On 2010-04-28, Richard Heathfield <rjh@see.sig.invalid> wrote:
>> <snip>
>>
>>>> If the data are sorted, bsearch.
>>>> If not, why not?
>>> I do not normally expect something structured like a three-dimensional
>>> array to be sorted, I expect it to be a representation of objects.
>> Then how on earth do you /find/ anything? It's O(N^3), for pity's sake!
>
> Are you saying that if an algorithm is O(N^3) it cannot find anything?
Hyperbole. An O(N^3) algorithm is sometimes necessary, but it is
probably worth spending at least some time trying to come up with a less
costly algorithm.
<snip>
--
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
|
|
0
|
|
|
|
Reply
|
Richard
|
5/8/2010 9:01:15 PM
|
|
James Kanze wrote:
> On May 2, 8:34 am, Richard Heathfield <r...@see.sig.invalid> wrote:
>> Seebs wrote:
>
> [...]
>> Why not just write while(i < j && a[i] != 42)?
>
> Because it states the loop invariants up front, in a single
> statement, rather than making the maintenance programmer have to
> figure them out for himself. Maintenance programmers have it
> too easy.
Someone who actually gets it! Thank you.
--
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
|
|
0
|
|
|
|
Reply
|
Richard
|
5/8/2010 9:02:20 PM
|
|
Seebs wrote:
> On 2010-05-02, Richard Heathfield <rjh@see.sig.invalid> wrote:
<snip>
>
>> This is really an argument about programming philosophy. Juha seems to
>> be in favour of the shortest code that does the job. I'm in favour of
>> code that accurately describes what it's doing. while(i < j) is not an
>> accurate description of the loop if you bomb out as soon as a[i] is 42.
>> Why not just write while(i < j && a[i] != 42)?
>
> Because, in some cases, the checks against a[i] make it harder to follow
> the code.
In my experience, it is generally easier to follow the code if it has a
clear structure. The example posted upthread isn't actually terribly
hard to follow, but I've seen (and had to maintain) some ghastly messes
in my time, where returns and breaks seemed to be inserted into the code
almost at random, and figuring out what the code was supposed to *do*
was way harder than it should have been.
>
> I guess it's a question of how you do the translation.
>
<break example>
<non-break example>
>
> In general, in fact, I prefer the former. The loop is "iterate through
> a". In this case, the idiomatic clarity of "we are looping from 0 to n-1"
> is so much greater that "we are looping from 0 to n-1, and the operation
> is to stop prematurely if..." is much clearer than "we are looping from 0
> to either n-1 or the first value such that....".
That's an interesting take on it, but I would read my version of the
loop control as "look through every element of the array in order until
you've either found what you're looking for or discovered that it's not
there".
<snip>
--
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
|
|
0
|
|
|
|
Reply
|
Richard
|
5/8/2010 9:08:56 PM
|
|
Leif Roar Moldskred wrote:
> In comp.programming Richard Heathfield <rjh@see.sig.invalid> wrote:
>> Then how on earth do you /find/ anything? It's O(N^3), for pity's sake!
>
> No, it isn't. It's O( N ).
>
> (Hint: What's N the count of?)
If N is the number of 3D points, you're right. If N is the size of one
dimension (which is how I was thinking of it), it's O(LMN). If L == M
and L == N, that makes it O(N^3).
For you to be right, however, N would have a granularity greater than 1
for all except the most trivial examples.
--
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
|
|
0
|
|
|
|
Reply
|
Richard
|
5/8/2010 9:11:59 PM
|
|
Nick wrote:
> Richard Heathfield <rjh@see.sig.invalid> writes:
>
>> Yes, and this question-begging is perfectly in keeping with the
>> requirement that one should never exit from within a loop. (It is,
>> after all, an argument about loops.)
>
> What requirement?
It's a style thing, not a language thing. As with any style thing, it is
only required by its advocates. :-)
Anyway, I was actually making an obscure joke about circular arguments,
which seems to have passed people by. Perhaps some people will catch it
the next time round...
--
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
|
|
0
|
|
|
|
Reply
|
Richard
|
5/8/2010 9:16:50 PM
|
|
In comp.programming Richard Heathfield <rjh@see.sig.invalid> wrote:
>
> If N is the number of 3D points, you're right. If N is the size of one
> dimension (which is how I was thinking of it), it's O(LMN). If L == M
> and L == N, that makes it O(N^3).
The point is that it doesn't matter whether you structure your search
as one single, overarching loop or three nested loops. In either case
it's a bog standard linear search, where each element is visited no
more than once.
If we set N to be the size of the search space then _both_ ways to do
it is O( N ) and if we set N to be the length of one edge of a cubic
search space then _both_ ways are O( N^3 ).
--
Leif Roar Moldskred
|
|
0
|
|
|
|
Reply
|
Leif
|
5/8/2010 9:31:17 PM
|
|
"Richard Heathfield" <rjh@see.sig.invalid> wrote in message
news:XIKdndhU_u7PTXjWnZ2dnUVZ8iudnZ2d@bt.com...
>> I gave you a piece of code and asked you to modify it to conform to
>> your principles. You did not do that. Who is trying to avoid answering
>> to a challenge here?
>
> Oh, I can modify it easily enough, and I am reasonably confident of how
> you'll react to the modification, but here it is anyway. I am too
> lazy/tired to look up your original code now, but IIRC basically you're
> searching through an unsorted 3D array, which I would do along these
> lines:
>
> /* p is a pointer to a valid "struct point" object, with x, y, and z
> members */
>
> int 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)
> {
> found = 1;
> point_assign(p, x, y, z); /* that is, p.x = x; p.y = y, etc */
> }
> }
> }
> }
> return found;
>
> And I know you're not going to like the extra tests any more than I like
> your early returns. Style issue.
>
Not just a style issue, for each conditional check at each level you are
emitting extra CPU instructions and therefore extra overhead which can be an
issue sometimes. Also your version is fugly, an early return is more
efficient and not so fugly. This post has been cross-posted to C++ where
SESE is not so important (we have RAII). Enough of your nonsense you lame C
hacker, try embracing a slightly more modern and flexible language such as
C++.
/Leigh
|
|
0
|
|
|
|
Reply
|
Leigh
|
5/8/2010 9:32:29 PM
|
|
On 2010-05-08, Richard Heathfield <rjh@see.sig.invalid> wrote:
> Seebs wrote:
>> On 2010-05-02, Richard Heathfield <rjh@see.sig.invalid> wrote:
>> Because, in some cases, the checks against a[i] make it harder to follow
>> the code.
> In my experience, it is generally easier to follow the code if it has a
> clear structure.
I would agree that it is *GENERALLY* easier.
But in some cases it's not.
The vanilla loop idiom ("for (i = 0; i < N; ++i)") has a HUGE weight of
idiomatic clarity -- it does not require noticable attention to model it,
and that clarity is lost as soon as you change the loop condition.
In short:
for (i = 0; i < N; ++i)
if (foo(i))
return i;
return -1;
is nearly always much easier for a programmer to grok in fullness than
for (i = 0; i < N && !foo(i); ++i)
;
if (i != N)
return i;
else
return -1;
> The example posted upthread isn't actually terribly
> hard to follow, but I've seen (and had to maintain) some ghastly messes
> in my time, where returns and breaks seemed to be inserted into the code
> almost at random, and figuring out what the code was supposed to *do*
> was way harder than it should have been.
Agreed.
But going from "in general, it is better to have the full loop condition
stated, but there may be exceptions where the clarity of an idiom trumps
this" to "it is absolutely in every case without any possible exceptions
no matter what worse to use any kind of break or return from within a
loop" is unsupportable.
> That's an interesting take on it, but I would read my version of the
> loop control as "look through every element of the array in order until
> you've either found what you're looking for or discovered that it's not
> there".
Agreed -- and that's a much more complicated condition.
Simple rules with exceptions are easier for humans to process than complex
rules.
-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
|
|
0
|
|
|
|
Reply
|
Seebs
|
5/8/2010 9:37:36 PM
|
|
Seebs <usenet-nospam@seebs.net> wrote:
> On 2010-05-08, Richard Heathfield <rjh@see.sig.invalid> wrote:
> > Seebs wrote:
> >> On 2010-05-02, Richard Heathfield <rjh@see.sig.invalid> wrote:
> >> Because, in some cases, the checks against a[i] make it harder to follow
> >> the code.
>
> > In my experience, it is generally easier to follow the code if it has a
> > clear structure.
>
> I would agree that it is *GENERALLY* easier.
>
> But in some cases it's not.
>
> The vanilla loop idiom ("for (i = 0; i < N; ++i)") has a HUGE weight of
> idiomatic clarity -- it does not require noticable attention to model it,
> and that clarity is lost as soon as you change the loop condition.
>
> In short:
> for (i = 0; i < N; ++i)
> if (foo(i))
> return i;
> return -1;
>
> is nearly always much easier for a programmer to grok in fullness than
> for (i = 0; i < N && !foo(i); ++i)
> ;
> if (i != N)
> return i;
> else
> return -1;
While both of the above are much worse than:
int i = 0;
while (i < N && !foo(i))
++i;
return i;
The above is a standard idiom in C++.
|
|
0
|
|
|
|
Reply
|
Daniel
|
5/9/2010 12:58:31 AM
|
|
On 8 May, 17:46, Tim Streater <timstrea...@waitrose.com> wrote:
> In article
> <5dd9bdc8-4dc4-4537-84a0-885c4c92f...@l28g2000yqd.googlegroups.com>,
> =A0Nick Keighley <nick_keighley_nos...@hotmail.com> wrote:
> > On 8 May, 01:41, Lie Ryan <lie.1...@gmail.com> wrote:
> > > > I've never heard of any programming languages that doesn't support
> > > > recursion.
[...]
> > FORTRAN (in its original form), Coral-66 you had to use a special
> > keyword to indicate a function was recursive. Some BASICs probably
> > didn't alow recursion. But these all qualify as "ancient" (and maybe
> > jocular!)
>
> What FORTRAN are you referring to. I never saw it in any FORTRAN up to
> 1978 (the last time I used FORTRAN).
lost me. So far as I remember FORTRAN didn't have recursion. Am I
wrong? Or are you saying even modern Fortran doesn't have recursion?
|
|
0
|
|
|
|
Reply
|
Nick
|
5/9/2010 1:01:03 AM
|
|
Nick Keighley wrote:
> On 8 May, 17:46, Tim Streater <timstrea...@waitrose.com> wrote:
>> In article
>> <5dd9bdc8-4dc4-4537-84a0-885c4c92f...@l28g2000yqd.googlegroups.com>,
>> Nick Keighley <nick_keighley_nos...@hotmail.com> wrote:
>>> On 8 May, 01:41, Lie Ryan <lie.1...@gmail.com> wrote:
>
>
>>>>> I've never heard of any programming languages that doesn't support
>>>>> recursion.
> [...]
>>> FORTRAN (in its original form), Coral-66 you had to use a special
>>> keyword to indicate a function was recursive. Some BASICs probably
>>> didn't alow recursion. But these all qualify as "ancient" (and maybe
>>> jocular!)
>> What FORTRAN are you referring to. I never saw it in any FORTRAN up to
>> 1978 (the last time I used FORTRAN).
>
> lost me. So far as I remember FORTRAN didn't have recursion. Am I
> wrong? Or are you saying even modern Fortran doesn't have recursion?
If recursion does not exist, I will have to ditch quite a couple
of fortran programs.
There is only 1 hitch, you have to write a 3 line dummy routine,
to do the calling, so a calls b , b calls a.
fortran MS 5.1 and later.
Also Fortran77 for Riscos (arc 320 computer)
|
|
0
|
|
|
|
Reply
|
Sjouke
|
5/9/2010 3:04:34 AM
|
|
In alt.lang.asm [FUp set] Sjouke Burry <burrynulnulfour@ppllaanneett.nnll> wrote in part:
> Nick Keighley wrote:
>> lost me. So far as I remember FORTRAN didn't have recursion. Am I
>> wrong? Or are you saying even modern Fortran doesn't have recursion?
>
> If recursion does not exist, I will have to ditch quite
> a couple of fortran programs. There is only 1 hitch, you
> have to write a 3 line dummy routine, to do the calling,
> so a calls b , b calls a. fortran MS 5.1 and later.
> Also Fortran77 for Riscos (arc 320 computer)
For what problems do you find recursion to be the fastest
[CPU runtime] solution method?
-- Robert
|
|
0
|
|
|
|
Reply
|
Robert
|
5/9/2010 3:53:36 AM
|
|
On 2010-05-09, Daniel T. <daniel_t@earthlink.net> wrote:
> While both of the above are much worse than:
> int i = 0;
> while (i < N && !foo(i))
> ++i;
> return i;
I'm not convinced of it.
> The above is a standard idiom in C++.
How nice for it?
In C, the idiom of using a for loop to iterate over arrays is pretty
firmly entrenched.
I just noticed the crossposting, so I'm dropping the extra groups.
-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
|
|
0
|
|
|
|
Reply
|
Seebs
|
5/9/2010 5:06:21 AM
|
|
In article
<967ab68e-ce6a-4767-8435-6810e10a6baa@p2g2000yqh.googlegroups.com>,
Nick Keighley <nick_keighley_nospam@hotmail.com> wrote:
> On 8 May, 17:46, Tim Streater <timstrea...@waitrose.com> wrote:
> > In article
> > <5dd9bdc8-4dc4-4537-84a0-885c4c92f...@l28g2000yqd.googlegroups.com>,
> > �Nick Keighley <nick_keighley_nos...@hotmail.com> wrote:
> > > On 8 May, 01:41, Lie Ryan <lie.1...@gmail.com> wrote:
>
>
> > > > > I've never heard of any programming languages that doesn't support
> > > > > recursion.
> [...]
> > > FORTRAN (in its original form), Coral-66 you had to use a special
> > > keyword to indicate a function was recursive. Some BASICs probably
> > > didn't alow recursion. But these all qualify as "ancient" (and maybe
> > > jocular!)
> >
> > What FORTRAN are you referring to. I never saw it in any FORTRAN up to
> > 1978 (the last time I used FORTRAN).
>
> lost me. So far as I remember FORTRAN didn't have recursion. Am I
> wrong? Or are you saying even modern Fortran doesn't have recursion?
I'm saying that no FORTRAN that I used (up to 1978, last time I used
FORTRAN) had recursion or any hint of it. This was on a variety of
platforms - CDC (6000 series), IBM (7094, 360/370), SIGMA7, ...
--
Tim
"That excessive bail ought not to be required, nor excessive fines imposed,
nor cruel and unusual punishments inflicted" -- Bill of Rights 1689
|
|
0
|
|
|
|
Reply
|
Tim
|
5/9/2010 8:52:05 AM
|
|
"Daniel T." <daniel_t@earthlink.net> writes:
> Seebs <usenet-nospam@seebs.net> wrote:
>> On 2010-05-08, Richard Heathfield <rjh@see.sig.invalid> wrote:
>> > Seebs wrote:
>> >> On 2010-05-02, Richard Heathfield <rjh@see.sig.invalid> wrote:
>> >> Because, in some cases, the checks against a[i] make it harder to follow
>> >> the code.
>>
>> > In my experience, it is generally easier to follow the code if it has a
>> > clear structure.
>>
>> I would agree that it is *GENERALLY* easier.
>>
>> But in some cases it's not.
>>
>> The vanilla loop idiom ("for (i = 0; i < N; ++i)") has a HUGE weight of
>> idiomatic clarity -- it does not require noticable attention to model it,
>> and that clarity is lost as soon as you change the loop condition.
>>
>> In short:
>> for (i = 0; i < N; ++i)
>> if (foo(i))
>> return i;
>> return -1;
>>
>> is nearly always much easier for a programmer to grok in fullness than
>> for (i = 0; i < N && !foo(i); ++i)
>> ;
>> if (i != N)
>> return i;
>> else
>> return -1;
>
> While both of the above are much worse than:
>
> int i = 0;
> while (i < N && !foo(i))
> ++i;
> return i;
>
> The above is a standard idiom in C++.
That one doesn't distinguish between "found" and "not found". I don't
think there's much to chose between
> int i = 0;
> while (i < N && !foo(i))
> ++i;
and
>> for (i = 0; i < N && !foo(i); ++i)
>> ;
when you present them like that you can see they are so close as makes
no difference. It's that bit of Seeb's code that you've not copied that
makes the the single exit point version messy.
And, of course, Seeb's isn't as good as it should be - he still has two
return points. So each of these, to be loop-politically-correct should
really end:
return (i != N) ? i : -1;
--
Online waterways route planner | http://canalplan.eu
Plan trips, see photos, check facilities | http://canalplan.org.uk
|
|
0
|
|
|
|
Reply
|
Nick
|
5/9/2010 9:32:56 AM
|
|
Nick <3-nospam@temporary-address.org.uk> wrote:
> "Daniel T." <daniel_t@earthlink.net> writes:
> > Seebs <usenet-nospam@seebs.net> wrote:
> > > On 2010-05-08, Richard Heathfield <rjh@see.sig.invalid> wrote:
> > > > Seebs wrote:
> > > > > On 2010-05-02, Richard Heathfield <rjh@see.sig.invalid> wrote:
> > > > >
> > > > > Because, in some cases, the checks against a[i] make it harder
> > > > > to follow the code.
> > >
> > > > In my experience, it is generally easier to follow the code if
> > > > it has a clear structure.
> > >
> > > I would agree that it is *GENERALLY* easier.
> > >
> > > But in some cases it's not.
> > >
> > > The vanilla loop idiom ("for (i = 0; i < N; ++i)") has a HUGE
> > > weight of idiomatic clarity -- it does not require noticable
> > > attention to model it, and that clarity is lost as soon as you
> > > change the loop condition.
> > >
> > > In short:
> > > for (i = 0; i < N; ++i)
> > > if (foo(i))
> > > return i;
> > > return -1;
> > >
> > > is nearly always much easier for a programmer to grok in fullness
> > > than
> > > for (i = 0; i < N && !foo(i); ++i)
> > > ;
> > > if (i != N)
> > > return i;
> > > else
> > > return -1;
> >
> > While both of the above are much worse than:
> >
> > int i = 0;
> > while (i < N && !foo(i))
> > ++i;
> > return i;
> >
> > The above is a standard idiom in C++.
>
> That one doesn't distinguish between "found" and "not found".
Of course it does, and it does so more efficiently. For the other
examples "if (i != N)" is checked and then later "if (result != -1)"
must be checked. With the example I presented only one "if" is necessary.
> ... It's that bit of Seeb's code that you've not copied that makes the
> the single exit point version messy.
It's the bit that I didn't copy that makes the code cleaner and reduces
overall code size and complexity.
I'm more than happy to accept that using a 'while' that actually has a
loop body, vs using a 'for' with an empty loop body is a style issue,
but considering the back and forth between how to effectively express an
empty loop body so that it won't be interpreted as a mistake, and the
fact that the initialized variable ("i" in this case) actually needs to
be used after the loop exits, I think my style is a better choice in
this regard.
(Note here, I'm not arguing for single exit in every case, but it's
clearly a better choice in *this* example.
|
|
0
|
|
|
|
Reply
|
Daniel
|
5/9/2010 2:42:01 PM
|
|
"Daniel T." <daniel_t@earthlink.net> writes:
> Nick <3-nospam@temporary-address.org.uk> wrote:
>> "Daniel T." <daniel_t@earthlink.net> writes:
>> > Seebs <usenet-nospam@seebs.net> wrote:
>> > > On 2010-05-08, Richard Heathfield <rjh@see.sig.invalid> wrote:
>> > > > Seebs wrote:
>> > > > > On 2010-05-02, Richard Heathfield <rjh@see.sig.invalid> wrote:
>> > > > >
>> > > > > Because, in some cases, the checks against a[i] make it harder
>> > > > > to follow the code.
>> > >
>> > > > In my experience, it is generally easier to follow the code if
>> > > > it has a clear structure.
>> > >
>> > > I would agree that it is *GENERALLY* easier.
>> > >
>> > > But in some cases it's not.
>> > >
>> > > The vanilla loop idiom ("for (i = 0; i < N; ++i)") has a HUGE
>> > > weight of idiomatic clarity -- it does not require noticable
>> > > attention to model it, and that clarity is lost as soon as you
>> > > change the loop condition.
>> > >
>> > > In short:
>> > > for (i = 0; i < N; ++i)
>> > > if (foo(i))
>> > > return i;
>> > > return -1;
>> > >
>> > > is nearly always much easier for a programmer to grok in fullness
>> > > than
>> > > for (i = 0; i < N && !foo(i); ++i)
>> > > ;
>> > > if (i != N)
>> > > return i;
>> > > else
>> > > return -1;
>> >
>> > While both of the above are much worse than:
>> >
>> > int i = 0;
>> > while (i < N && !foo(i))
>> > ++i;
>> > return i;
>> >
>> > The above is a standard idiom in C++.
>>
>> That one doesn't distinguish between "found" and "not found".
>
> Of course it does, and it does so more efficiently. For the other
> examples "if (i != N)" is checked and then later "if (result != -1)"
> must be checked. With the example I presented only one "if" is
> necessary.
Am I being particularly dumb here (it's been known). Are you saying
that you elsewhere in the code you use i!=N as the check? In which
case, I suppose so, but it's a pain to use if 'N' isn't easily
calculable or available later (say it's not actually i<N but a test
against a sentinal).
>
>> ... It's that bit of Seeb's code that you've not copied that makes the
>> the single exit point version messy.
>
> It's the bit that I didn't copy that makes the code cleaner and reduces
> overall code size and complexity.
>
> I'm more than happy to accept that using a 'while' that actually has a
> loop body, vs using a 'for' with an empty loop body is a style issue,
> but considering the back and forth between how to effectively express an
> empty loop body so that it won't be interpreted as a mistake, and the
> fact that the initialized variable ("i" in this case) actually needs to
> be used after the loop exits, I think my style is a better choice in
> this regard.
I'm coming to that view myself. It also prevents some clever person
coming along and sticking an "int" inside the first clause of the for
loop.
> (Note here, I'm not arguing for single exit in every case, but it's
>clearly a better choice in *this* example.
Only if you're prepared to check against N whenever you need to (or - as
I've said - I'm missing the blindingly obvious).
--
Online waterways route planner | http://canalplan.eu
Plan trips, see photos, check facilities | http://canalplan.org.uk
|
|
0
|
|
|
|
Reply
|
Nick
|
5/9/2010 3:06:50 PM
|
|
Nick <3-nospam@temporary-address.org.uk> wrote:
> "Daniel T." <daniel_t@earthlink.net> writes:
> > Nick <3-nospam@temporary-address.org.uk> wrote:
> > > "Daniel T." <daniel_t@earthlink.net> writes:
> > > > Seebs <usenet-nospam@seebs.net> wrote:
> > > > > On 2010-05-08, Richard Heathfield <rjh@see.sig.invalid> wrote:
> > > > > > Seebs wrote:
> > > > > > > On 2010-05-02, Richard Heathfield <rjh@see.sig.invalid> wrote:
> > > > > > >
> > > > > > > Because, in some cases, the checks against a[i] make it
> > > > > > > harder to follow the code.
> > > > >
> > > > > > In my experience, it is generally easier to follow the code
> > > > > > if it has a clear structure.
> > > > >
> > > > > I would agree that it is *GENERALLY* easier.
> > > > >
> > > > > But in some cases it's not.
> > > > >
> > > > > The vanilla loop idiom ("for (i = 0; i < N; ++i)") has a HUGE
> > > > > weight of idiomatic clarity -- it does not require noticable
> > > > > attention to model it, and that clarity is lost as soon as you
> > > > > change the loop condition.
> > > > >
> > > > > In short:
> > > > > for (i = 0; i < N; ++i)
> > > > > if (foo(i))
> > > > > return i;
> > > > > return -1;
> > > > >
> > > > > is nearly always much easier for a programmer to grok in fullness
> > > > > than
> > > > > for (i = 0; i < N && !foo(i); ++i)
> > > > > ;
> > > > > if (i != N)
> > > > > return i;
> > > > > else
> > > > > return -1;
> > > >
> > > > While both of the above are much worse than:
> > > >
> > > > int i = 0;
> > > > while (i < N && !foo(i))
> > > > ++i;
> > > > return i;
> > > >
> > > > The above is a standard idiom in C++.
> > >
> > > That one doesn't distinguish between "found" and "not found".
> >
> > Of course it does, and it does so more efficiently. For the other
> > examples "if (i != N)" is checked and then later "if (result != -1)"
> > must be checked. With the example I presented only one "if" is
> > necessary.
>
> Am I being particularly dumb here (it's been known). Are you saying
> that you elsewhere in the code you use i!=N as the check? In which
> case, I suppose so, but it's a pain to use if 'N' isn't easily
> calculable or available later (say it's not actually i<N but a test
> against a sentinal).
In this particular case 'N' (as opposed to 'n') implies that it's a
macro. In any case a specific range is being checked, and it would be
very poor design to define the range solely within the function in
question. Typically it is passed into the function, which means it is
available to the caller.
> > (Note here, I'm not arguing for single exit in every case, but it's
> > clearly a better choice in *this* example.
>
> Only if you're prepared to check against N whenever you need to (or - as
> I've said - I'm missing the blindingly obvious).
Again, the calling code must do an 'if' check in any case, so the
question is, why is the function *also* making the check? If by some odd
stroke the calling code doesn't know the value of 'N' that can easily be
fixed.
|
|
0
|
|
|
|
Reply
|
Daniel
|
5/9/2010 4:31:41 PM
|
|
"Daniel T." <daniel_t@earthlink.net> writes:
> Nick <3-nospam@temporary-address.org.uk> wrote:
>> Only if you're prepared to check against N whenever you need to (or - as
>> I've said - I'm missing the blindingly obvious).
>
> Again, the calling code must do an 'if' check in any case, so the
> question is, why is the function *also* making the check? If by some odd
> stroke the calling code doesn't know the value of 'N' that can easily be
> fixed.
But the function is only *also* making the check because we've
eliminated the early return. With the early return there's no need for
the second check.
Taking Richard H's joke that I missed last time, here we go round the
loop again.
--
Online waterways route planner | http://canalplan.eu
Plan trips, see photos, check facilities | http://canalplan.org.uk
|
|
0
|
|
|
|
Reply
|
Nick
|
5/9/2010 5:30:31 PM
|
|
Nick <3-nospam@temporary-address.org.uk> wrote:
> "Daniel T." <daniel_t@earthlink.net> writes:
> > Nick <3-nospam@temporary-address.org.uk> wrote:
> >
> > > Only if you're prepared to check against N whenever you need to
> > > (or - as I've said - I'm missing the blindingly obvious).
> >
> > Again, the calling code must do an 'if' check in any case, so the
> > question is, why is the function *also* making the check? If by some
> > odd stroke the calling code doesn't know the value of 'N' that can
> > easily be fixed.
>
> But the function is only *also* making the check because we've
> eliminated the early return. With the early return there's no need for
> the second check.
All I'm saying is that you can remove the early return *and* the extra
'if' check, if you aren't dogmatic about the not-found flag being -1.
> Taking Richard H's joke that I missed last time, here we go round the
> loop again.
Not at all. If for some reason the function *must* return -1 for a
not-found flag, then an early return is the correct choice; however, I'm
questioning that assumption. I'm not going back around the loop, I'm
moving up a level of abstraction.
|
|
0
|
|
|
|
Reply
|
Daniel
|
5/9/2010 6:25:33 PM
|
|
On 9 May, 09:52, Tim Streater <timstrea...@waitrose.com> wrote:
> In article
> <967ab68e-ce6a-4767-8435-6810e10a6...@p2g2000yqh.googlegroups.com>,
> =A0Nick Keighley <nick_keighley_nos...@hotmail.com> wrote:
> > On 8 May, 17:46, Tim Streater <timstrea...@waitrose.com> wrote:
> > > In article
> > > <5dd9bdc8-4dc4-4537-84a0-885c4c92f...@l28g2000yqd.googlegroups.com>,
> > > =A0Nick Keighley <nick_keighley_nos...@hotmail.com> wrote:
> > > > On 8 May, 01:41, Lie Ryan <lie.1...@gmail.com> wrote:
> > > > > > I've never heard of any programming languages that doesn't supp=
ort
> > > > > > recursion.
> >
> > > > FORTRAN (in its original form), Coral-66 you had to use a special
> > > > keyword to indicate a function was recursive. Some BASICs probably
> > > > didn't alow recursion. But these all qualify as "ancient" (and mayb=
e
> > > > jocular!)
>
> > > What FORTRAN are you referring to. I never saw it in any FORTRAN up t=
o
> > > 1978 (the last time I used FORTRAN).
>
> > lost me. So far as I remember FORTRAN didn't have recursion. Am I
> > wrong? Or are you saying even modern Fortran doesn't have recursion?
>
> I'm saying that no FORTRAN that I used (up to 1978, last time I used
> FORTRAN) had recursion or any hint of it. This was on a variety of
> platforms - CDC (6000 series), IBM (7094, 360/370), SIGMA7, ...
so you are agreeeing with me?
|
|
0
|
|
|
|
Reply
|
Nick
|
5/10/2010 8:15:21 AM
|
|
In article
<4a6447f6-4c90-41be-9f60-53b94f4207c8@a21g2000yqn.googlegroups.com>,
Nick Keighley <nick_keighley_nospam@hotmail.com> wrote:
> On 9 May, 09:52, Tim Streater <timstrea...@waitrose.com> wrote:
> > In article
> > <967ab68e-ce6a-4767-8435-6810e10a6...@p2g2000yqh.googlegroups.com>,
> > �Nick Keighley <nick_keighley_nos...@hotmail.com> wrote:
> > > On 8 May, 17:46, Tim Streater <timstrea...@waitrose.com> wrote:
> > > > In article
> > > > <5dd9bdc8-4dc4-4537-84a0-885c4c92f...@l28g2000yqd.googlegroups.com>,
> > > > �Nick Keighley <nick_keighley_nos...@hotmail.com> wrote:
> > > > > On 8 May, 01:41, Lie Ryan <lie.1...@gmail.com> wrote:
>
>
> > > > > > > I've never heard of any programming languages that doesn't support
> > > > > > > recursion.
> > >
> > > > > FORTRAN (in its original form), Coral-66 you had to use a special
> > > > > keyword to indicate a function was recursive. Some BASICs probably
> > > > > didn't alow recursion. But these all qualify as "ancient" (and maybe
> > > > > jocular!)
> >
> > > > What FORTRAN are you referring to. I never saw it in any FORTRAN up to
> > > > 1978 (the last time I used FORTRAN).
> >
> > > lost me. So far as I remember FORTRAN didn't have recursion. Am I
> > > wrong? Or are you saying even modern Fortran doesn't have recursion?
> >
> > I'm saying that no FORTRAN that I used (up to 1978, last time I used
> > FORTRAN) had recursion or any hint of it. This was on a variety of
> > platforms - CDC (6000 series), IBM (7094, 360/370), SIGMA7, ...
>
> so you are agreeeing with me?
Hard to say. Does modern FORTRAN have recursion? No good asking me!
--
Tim
"That excessive bail ought not to be required, nor excessive fines imposed,
nor cruel and unusual punishments inflicted" -- Bill of Rights 1689
|
|
0
|
|
|
|
Reply
|
Tim
|
5/10/2010 8:26:29 AM
|
|
On May 10, 9:26=A0am, Tim Streater <timstrea...@waitrose.com> wrote:
> Hard to say. Does modern FORTRAN have recursion? No good asking me!
Yes, since Fortran 90.
|
|
0
|
|
|
|
Reply
|
gwowen
|
5/10/2010 9:08:28 AM
|
|
Nathan Baker wrote:
>> Ok Nate, we had enough discussions on this matter since HLLs
>> entered our progamming world ...
>> We better give up arguing and let the 'faster' programmers
>> be proud of their 'maintainable/foolproof-readable' sources
>> which are awful detours with "abstraction layers" while the
>> few hardware freaks like me work on "really existing things" :)
> The CPU experiences a nightmare while executing HLL code.
> Perhaps there is an instructive way for us to demonstrate this fact?
Even we could try this one more time, I daubt that
'fundamental' HLL-coders may listen at all.
The believe in their holy compilers seem to be very strong :)
I think demonstration of the bloated redundance isn't required,
disassemble whatsoever you find (windoze+lunix/app+sys) and
see as of immediate all the weird detours created by 'a tool'.
The few programmers who know both worlds may be aware and
create lesser bloated and faster code even with HLL.
__
wolfgang
some believe in god, many in gold, a few in logic,
and HLL-coders in their compiler.
|
|
0
|
|
|
|
Reply
|
wolfgang
|
5/11/2010 7:55:27 AM
|
|
On May 11, 12:55=A0am, "wolfgang kern" <nowh...@never.at> wrote:
> Nathan Baker wrote:
> >> Ok Nate, we had enough discussions on this matter since HLLs
> >> entered our progamming world ...
> >> We better give up arguing and let the 'faster' programmers
> >> be proud of their 'maintainable/foolproof-readable' sources
> >> which are awful detours with "abstraction layers" while the
> >> few hardware freaks like me work on "really existing things" :)
> > The CPU experiences a nightmare while executing HLL code.
> > Perhaps there is an instructive way for us to demonstrate this fact?
>
> Even we could try this one more time, I daubt that
> 'fundamental' HLL-coders may listen at all.
> The believe in their holy compilers seem to be very strong :)
>
> I think demonstration of the bloated redundance isn't required,
> disassemble whatsoever you find (windoze+lunix/app+sys) and
> see as of immediate all the weird detours created by 'a tool'.
>
> The few programmers who know both worlds may be aware and
> create lesser bloated and faster code even with HLL.
There are several reasons for what you call compiler-produced bloat:
- copy-pasted code at the source level (can happen in asm too)
- duplicate functionality and data in different parts of big
applications (can happen in asm too)
- overly complicated code (can happen in asm too)
- dead code and data (can happen in asm too)
- error handling code (you probably need it in asm too)
- use of macros, inlining and templates (macros exist in asm too)
- calling convention support code for interoperation, variable
argument subroutines, exception handling and debugging (you may need
or want some of them in asm too)
- code alignment (you may need it in asm too)
- inadequately chosen optimization switches or speed preference over
size
- global variables, including not tightly packed structures (you may
want data alignment in asm too)
So, some of it comes from bad or complex source code, some from the
fact that applications are made from many different parts done
independently by different people, some is dictated by the overall API
design and some from how the compiler and linker are used. Then again,
often times quickly making software is more important than making it
fast or small or both. Depends on the business model, which you may be
unable to change other than by quitting your employer and finding a
"better" one or starting your own company or simply going self-
employed. I'm just explaining how this bloat is possible and expected.
Alex
|
|
0
|
|
|
|
Reply
|
Alexei
|
5/11/2010 8:54:35 AM
|
|
Ben Bacarisse <ben.usenet@bsb.me.uk> wrote:
> Kenneth Brody <kenbrody@spamcop.net> writes:
>
> > Consider:
> >
> > for ( begin_expr ; test_expr ; next_expr );
> > do_something();
> >
> > The "lone semicolon" could easily be a typo, and not easy to spot at
> > times. (Which is sort of what this sub-thread is all about.)
>
> The merits of various styles for empty loop bodies is frequently debated
> here, but here's a thought: does it actually matter? Has anyone ever
> encountered a hard bug caused by either the accidental inclusion of a
> semicolon (thereby excluding the while loop body) or by the omission of
> a null body (thereby sucking the following statement into the loop)? I
> don't think I ever have. I certainly don't recall one.
Personally, no. But we seem to get a lot of newbies in here who do make
that mistake - usually in the form Kenneth mentions - and are confused
by it. One reason we ourselves don't is, I suspect, mainly that we have
enough experience that we _do_ take a single style that we find clear,
and stick to it.
Richard
|
|
0
|
|
|
|
Reply
|
raltbos
|
5/11/2010 2:05:59 PM
|
|
"Nathan Baker" <nathancbaker@gmail.com> wrote:
> The CPU experiences a nightmare while executing HLL code. Perhaps there is
> an instructive way for us to demonstrate this fact?
<http://xkcd.com/371/>
Richard
|
|
0
|
|
|
|
Reply
|
raltbos
|
5/11/2010 2:14:01 PM
|
|
Alexei A. Frounze explained the cause:
<--q>
"wolfgang kern" <nowh...@never.at> wrote:
> Nathan Baker wrote:
>>> Ok Nate, we had enough discussions on this matter since HLLs
>>> entered our progamming world ...
>>> We better give up arguing and let the 'faster' programmers
>>> be proud of their 'maintainable/foolproof-readable' sources
>>> which are awful detours with "abstraction layers" while the
>>> few hardware freaks like me work on "really existing things" :)
>> The CPU experiences a nightmare while executing HLL code.
>> Perhaps there is an instructive way for us to demonstrate this fact?
> Even we could try this one more time, I daubt that
> 'fundamental' HLL-coders may listen at all.
> The believe in their holy compilers seem to be very strong :)
> I think demonstration of the bloated redundance isn't required,
> disassemble whatsoever you find (windoze+lunix/app+sys) and
> see as of immediate all the weird detours created by 'a tool'.
> The few programmers who know both worlds may be aware and
> create lesser bloated and faster code even with HLL.
There are several reasons for what you call compiler-produced bloat:
- copy-pasted code at the source level (can happen in asm too)
- duplicate functionality and data in different parts of big
applications (can happen in asm too)
- overly complicated code (can happen in asm too)
- dead code and data (can happen in asm too)
- error handling code (you probably need it in asm too)
- use of macros, inlining and templates (macros exist in asm too)
- calling convention support code for interoperation, variable
argument subroutines, exception handling and debugging (you may need
or want some of them in asm too)
- code alignment (you may need it in asm too)
- inadequately chosen optimization switches or speed preference over
size
- global variables, including not tightly packed structures (you may
want data alignment in asm too)
So, some of it comes from bad or complex source code, some from the
fact that applications are made from many different parts done
independently by different people, some is dictated by the overall API
design and some from how the compiler and linker are used. Then again,
often times quickly making software is more important than making it
fast or small or both. Depends on the business model, which you may be
unable to change other than by quitting your employer and finding a
"better" one or starting your own company or simply going self-
employed. I'm just explaining how this bloat is possible and expected.
Alex
</--q>
I fully agree with your notes, also ASM may use Libs and are often
'compiled' instead of designed.
But even ASM may have to follow API calling conventions, we are free
(in opposition to the poor C-coders) to avoid these 'oh so common'
stack-copy-detours in our ASM-functions ...
__
wolfgang
|
|
0
|
|
|
|
Reply
|
wolfgang
|
5/12/2010 12:37:24 PM
|
|
In comp.lang.c++ Richard Heathfield <rjh@see.sig.invalid> wrote:
> Hyperbole. An O(N^3) algorithm is sometimes necessary, but it is
> probably worth spending at least some time trying to come up with a less
> costly algorithm.
Well, as someone correctly pointed out, the algorithm is actually not
O(n^3) but O(n). There are n elements and the algorithm is going linearly
through all of them searching for a specific one. That's O(n). It doesn't
matter how the elements are arranged in memory. It doesn't make any
difference whether the elements are in a one-dimensional or a
three-dimensional array. It's still O(n).
O(n^3) would be if for each element the algorithm would go through all
the elements, and for that pass it would go through all the elements a
third time.
If you sorted the elements somehow such that you could use a binary
search on each single dimension, the algorithm would be reduced from
O(n) to O(log n) (and not from O(n^3) to O(log n), which would be way
too much of a reduction; a binary search cannot reduce from O(n^3) to
O(log n).).
|
|
0
|
|
|
|
Reply
|
Juha
|
5/12/2010 12:45:54 PM
|
|
In comp.lang.c++ Nathan Baker <nathancbaker@gmail.com> wrote:
>
> "Juha Nieminen" <nospam@thanks.invalid> wrote in message
> news:4be50dcf$0$2544$7b1e8fa0@news.nbl.fi...
>> In comp.lang.c++ io_x <a@b.c.invalid> wrote:
>>> with assembly is possible to write recursions functions too
>>
>> That's like saying that C supports object-oriented programming.
>
> Of course it does! C certainly has support for data structures.
See, that's another hilarious thing about obsessed C programmers:
They don't even understand what "object-oriented programming" means or
what does it mean for a language to support that.
Think about it with a different example: While it's possible to handle
arbitrary precision integers in C (for example by using a library like GMP),
that doesn't mean the C programming language supports arbitrary precision
integers. They are not part of the core language, or even its standard
libraries, nor are they mentioned in any way or form in the official
standard.
Likewise the C language does not support object-oriented programming:
It has no native support for classes with restricted compiler-enforced
access rights, inheritance or dynamic binding / message dispatching.
You can construct an environment which somewhat *simulates* this, but
that doesn't mean the C language supports OOP any more than it supports
eg. arbitrary precision integers.
The main difference between a language which supports OOP directly and
a language which does not is the amount of work the compiler does for the
programmer.
|
|
0
|
|
|
|
Reply
|
Juha
|
5/12/2010 12:56:52 PM
|
|
S Perryman <q@q.net> writes:
> Juha Nieminen wrote:
>
>> Care to show an actual example of your "simpler, cleaner and easier to
>> | | | |