-
Some Wirth wisdom for the weekend.
https://people.inf.ethz.ch/wirth/Articles/GoodIdeas_origFig.pdf
-
***very*** interesting :o :o :o :o
(should be used as a prologue in *every* computer science course)
-
Well, "everything bad" when "programmer bad". :-//
Neah, I'll pass reading yet another rant.
Too many people pass reading what they assume as yet another rant :o :o :o
edit:
error #42, catastrophic failure in comprehension
---> panic()
-----> disable_channels_and_halt()
-
Opened the PDF at random. Let's see...
Dude wrote "Goto bad". OK, but all CPU's have a jump instruction.
Then dude wrote "Switch bad". Well, "everything bad" when "programmer bad". :-//
Neah, I'll pass reading yet another rant.
Based on that, it appears that not only did you open the PDF at random, you only read a few random sentences without understanding the points and their rationale.
That reflects more on you than Niklaus Wirth.
Even if that wasn't the case, Wirth's opinions on those subjects are far more worthy of attention than the opinions of a random poster (that includes me).
-
download the sources of a kernel, say Linux. Then count how many goto are in there. The number by itself might not tell much. Make the ratio between the number of goto and the total number of code lines (no comments). Still believe goto is bad in programming?
Goto good. I miss goto. :-\
The Linux kernel is not a good example since its programming style is ... so bad that it cannot pass DO178B level C, and it's actually - in perpetual regression - and it hard passes level D.
A better example is VxWorks by Windriver, a kernel that can pass DO178B level { A, B }, which means it can be used for mission critical stuff.
Anyway, even VxWorks uses "goto", but
- it's segregated to "critical modules", which you can easily exclude from the project, when you have to run analysis and certification, while Linux ... use "gotos" wherever Linus&C like without classifying the files, which makes difficult Linux to be "modified" to pass DO178B level C ... not impossible, but it takes a lot human resources
- "goto" is only used as "fail-point, quickly release resources and exit", which clearly means the programming language is defective since it doesn't provide a proper mechanism.
my-c enforces this concept:
- refuses to compile sources with "goto" unless you declare my-c --level0 source.myc
- with --level3 uses monads as "fail-point, quickly release resources and exit" mechanism
Nice? Well ... it makes sources very clean and polished, but also the binary a lot slower, and less efficient.
That's why I am allowing "-level0" for "gotos" ;D ;D ;D
-
Though, when it's the last time when you've seen a goto?
Every day?
I still develop in VB6 :'( (<<<---- won't render into (https://www.eevblog.com/forum/Smileys/default/cry.gif) here)
On Error GoTo is pretty much a requirement
In C, i've always seen it as "assembly guy" or "clever guy" wants to coerce the compiler to produce a specific assembly output instead of writing an assembly module
You can always rewrite the code not to use the goto statement (usually by hiding it with a switch statement)
Alas, the imperium programming language shall provide a better way to deal with all of that
-
Too many people pass reading
I can afford passing that read, don't follow my opinion, I'm not a programmer.
Thanks for letting us know that you won't be reading this paper. I myself won't be eating pizza tomorrow, if that helps.
Not being a programmer is fine. Although I don't think you're doing yourself justice - if you write programs, however simple they are, you are a programmer.
Having opinions on something you didn't even read is odd though. I you had read maybe even just the introduction, you would have gotten the idea behind this paper.
In essence, Wirth is listing a non-exhaustive number of ideas in programming languages that seemed "good" when they were introduced, and that turned out not so good in the end, explaining a bit of history around each and why the ideas were in fact bad.
I guess by saying that you're not a programmer, what you meant is that you're not an expert in computer science? In which case, arguing against Wirth would look pretty uh, bold.
But if you have concrete arguments to oppose concrete points he made, that would be welcome.
Some people prefer the more immediate, and easy to consume content of bloggers making bold claims, assuming they have the same validity, if not better.
What's striking with Wirth is that, beyond his great knowledge of computer science, he has been very humble. And this humilty makes him write in a tone that will often make you first think: "not sure I agree with this". But you read a second time, and maybe a third time, and then you realize that what he wrote makes a lot of sense.
-
Too many people pass reading
I can afford passing that read, don't follow my opinion, I'm not a programmer.
Thanks for letting us know that you won't be reading this paper. I myself won't be eating pizza tomorrow, if that helps.
Not being a programmer is fine. Although I don't think you're doing yourself justice - if you write programs, however simple they are, you are a programmer.
Having opinions on something you didn't even read is odd though. I you had read maybe even just the introduction, you would have gotten the idea behind this paper.
In essence, Wirth is listing a non-exhaustive number of ideas in programming languages that seemed "good" when they were introduced, and that turned out not so good in the end, explaining a bit of history around each and why the ideas were in fact bad.
I guess by saying that you're not a programmer, what you meant is that you're not an expert in computer science? In which case, arguing against Wirth would look pretty uh, bold.
But if you have concrete arguments to oppose concrete points he made, that would be welcome.
Some people prefer the more immediate, and easy to consume content of bloggers making bold claims, assuming they have the same validity, if not better.
What's striking with Wirth is that, beyond his great knowledge of computer science, he has been very humble. And this humilty makes him write in a tone that will often make you first think: "not sure I agree with this". But you read a second time, and maybe a third time, and then you realize that what he wrote makes a lot of sense.
You are being humble yourself - and charitable.
-
Go To := Bad;
This is one of those ideas whose basis is absolutely understandable, and which is sort of generally, mostly correct, but which I have never believed is wholly correct.
Its genesis comes from old line numbered languages like the original Fortran and Basic, and in those contexts it often resulted in incomprehensible spaghetti code. It was inconsistent with the concept of breaking programs into simple, easy to comprehend and easy to test modules. So used in the way it was when Wirth presented the idea it was pretty spot on. Not that you couldn't write good, easy to maintain code using goto statements, but the evidence in the field was that many or most wouldn't.
Eliminating goto does not eliminate bad coding. I once worked with an individual who had somehow interpreted the modularization imperative to mean that anything that took more than three lines of high level code needed to be modularized into a function or procedure. The result was slow, buggy and incredibly hard to understand.
The message here is that hard and fast rules are not necessary for good code. Just as hard and fast rules don't make for good written English. Great authors often break many of the "rules". But most average folks do better writing following the rules.
The above mentioned more recent usages mentioned in prior comments are hinting at appropriate reasons for using a goto. The most clear cut and defensible reason is when execution is meant to leave an area and never come back. This is the equivalent of a worker recognizing the situation is out of control and putting down his tools and killing power before more damage is done. It is important in situations like this to not depend on other parts of the system working properly.
The failure of compilers to allow this type of operation in "certifiable" or "mission critical" application in my opinion results from hubris of the developers of robust code systems. To believe that it is possible to know all of the possible operating states and failure modes of a software controlled system, and all of the responses of software to this infinitude of possibilities, and also to believe that whatever isn't covered is better left under the control of the program than reported with an urgent request for help buggers my imagination. It would be an equal example of hubris to claim that a goto or other 'forbidden' operation is the solution to these problems. But used sparingly and carefully these methods can be tested robustly and can be of benefit.
-
The above mentioned more recent usages mentioned in prior comments are hinting at appropriate reasons for using a goto. The most clear cut and defensible reason is when execution is meant to leave an area and never come back. This is the equivalent of a worker recognizing the situation is out of control and putting down his tools and killing power before more damage is done. It is important in situations like this to not depend on other parts of the system working properly.
If it was possible to implement goto such that this would be the only situation when it could be used then that would be OK. There are better alternatives for these cases e.g. exception handling.
-
What's dissapointing about this thread is that a 27+ pages paper has been reduced to a GoTo discussion.
There is also a period missing from one of the references and the year sometimes is in parenthesis and other times not.
goto end.
:horse:
-
There is also a period missing from one of the references and the year sometimes is in parenthesis and other times not.
Can we assume they were the only issues of concern for you with the article? If so you will be interested to know that the references had been edited by the time the published version of the article appeared in IEEE Computer, vol. 39, no. 01, pp. 28-39, 2006.
https://doi.ieeecomputersociety.org/10.1109/MC.2006.20
-
Then he continued writing switch is also bad, which I also disagree.
Did you notice that it is the use of the break statement in the switch that he is actually complaining about?
Either the break symbol denotes a separation between consecutive statements Si, or it acts as a goto to the end of the switch construct. In the first case, it is superfluous; in the second, it is a goto in disguise.
Do you agree that aspect of the switch statement is bad. If not, why not?
-
Can we assume they were the only issues of concern for you with the article?
Assume not.
It was a tongue-in-cheek comment , finding something to critique ,that is only one step below getting into a "goto" discussion.
-
The paper is still there in full. It was not reduced. Please feel free to talk about other chapters.
The go to was only the sample I've read. And I disagreed. Then he continued writing switch is also bad, which I also disagree. Then tggzzz told me that I missed the point.
No, I didn't. I wrote something very different...
Based on that, it appears that not only did you open the PDF at random, you only read a few random sentences without understanding the points and their rationale.
That reflects more on you than Niklaus Wirth.
Even if that wasn't the case, Wirth's opinions on those subjects are far more worthy of attention than the opinions of a random poster (that includes me).
Given your statements below, I see no reason to change that assessment.
...
I still don't see what wisdom hide in those pages.
...
Those were very good ideas, or at least fully entitled ideas at their time.
Your English is quite reasonable, but your knowledge of the subject and general comprehension skills are not as good.
-
If you restrict them of doing very stupid things, that will restrict them of doing very smart things either.
In my experience, 'smart' programmers are even more dangerous than stupid programmers ;)
-
If you restrict them of doing very stupid things, that will restrict them of doing very smart things either.
In my experience, 'smart' programmers are even more dangerous than stupid programmers ;)
Just so.
"Truly superior pilots are those who use their superior judgment to avoid those situations where they might have to use their superior skills." s/pilot/programmer/
But then RoGeorge also stated (https://www.eevblog.com/forum/programming/good-ideas-through-the-looking-glass/msg4803224/#msg4803224) "I am not a programmer", so his opinions about programming are, um, of questionable value.
-
OK, maybe I stepped into one of those "Blind men and the elephant" situations, where I'm one of the blind men. :-//
If readers enjoyed his essay, and found it valuable, good for them. I've tried twice and failed. Won't change my impression based on peer pressure either. So I'll just let it be, and not argue any longer.
Nobody would expect you to change your mind based on any imagined peer pressure.
In a topic where you know you aren't proficient, it is good practice to learn from the masters of a topic.
Making disparaging remarks about such master's opinions does not reflect well on you, and leads people to question your opinion on other topics.
-
Opened the PDF at random. Let's see...
Dude wrote "Goto bad". OK, but all CPU's have a jump instruction.
Then dude wrote "Switch bad". Well, "everything bad" when "programmer bad". :-//
Neah, I'll pass reading yet another rant.
Based on that, it appears that not only did you open the PDF at random, you only read a few random sentences without understanding the points and their rationale.
That reflects more on you than Niklaus Wirth.
Even if that wasn't the case, Wirth's opinions on those subjects are far more worthy of attention than the opinions of a random poster (that includes me).
It seems that Wirth wants to model a program as a continuous function. Which in itself isn't a bad idea. However, you are still dealing with hardware and users so not every program's behaviour is a continuous function. Hence the need for goto, switch/break, exceptions, etc.
-
Opened the PDF at random. Let's see...
Dude wrote "Goto bad". OK, but all CPU's have a jump instruction.
Then dude wrote "Switch bad". Well, "everything bad" when "programmer bad". :-//
Neah, I'll pass reading yet another rant.
Based on that, it appears that not only did you open the PDF at random, you only read a few random sentences without understanding the points and their rationale.
That reflects more on you than Niklaus Wirth.
Even if that wasn't the case, Wirth's opinions on those subjects are far more worthy of attention than the opinions of a random poster (that includes me).
It seems that Wirth wants to model a program as a continuous function. Which in itself isn't a bad idea. However, you are still dealing with hardware and users so not every program's behaviour is a continuous function. Hence the need for goto, switch/break, exceptions, etc.
I think you'll find Wirth isn't looking for any single feature; he is interested in improving programming.
If a feature "plugs and plays" with other features in a way that improves the ability to construct good programs, then he will like it. And vice versa.
He isn't interested in "shortcuts" that are convenient in some limited and/or temporary circumstances.
-
Opened the PDF at random. Let's see...
Dude wrote "Goto bad". OK, but all CPU's have a jump instruction.
Then dude wrote "Switch bad". Well, "everything bad" when "programmer bad". :-//
Neah, I'll pass reading yet another rant.
Based on that, it appears that not only did you open the PDF at random, you only read a few random sentences without understanding the points and their rationale.
That reflects more on you than Niklaus Wirth.
Even if that wasn't the case, Wirth's opinions on those subjects are far more worthy of attention than the opinions of a random poster (that includes me).
It seems that Wirth wants to model a program as a continuous function.
I don't know where you'd get that idea, or what in fact it would actually mean.
Which in itself isn't a bad idea. However, you are still dealing with hardware and users so not every program's behaviour is a continuous function. Hence the need for goto, switch/break, exceptions, etc.
Not sure what you are trying to say here, but it appears that you haven't understood what Wirth said about any of these points.
-
Goto:
Goto and break are indeed equally bad. No, actually break is even worse as it does not come with labels, which is a self-documenting feature (which reduces risk of confusion where it jumps).
The key point in goto bad mindset is; if you (or the language) restrict yourself never to use such control constructs in loops, then the termination condition is in one place, for example in C, here:
for(...; LOOK HERE; ...)
This eases analysis.
However, in practical world, this whole idea crumbles down as soon as you really need to break out of the loop, and need to construct a weird-looking, hard to analyze condition:
for(...; ACTUAL_CONDITION && keep_doing; ...)
{
if(break_condition)
keep_doing = 0;
if(keep_doing)
{
normal stuff
}
}
In such cases direct manipulation of control flow is just cleaner and easier to follow; our human brain processes sequential instructions like "stop doing this and jump here" as well! But you can of course abuse it like any construct.
Paper otherwise: Did read it all. It's a good piece of history in one paper, most of which is very agreeable.
-
I do not quite agree with "break" being worse. As a statement to exit a loop, it is relatively fine, and an ultra-common feature in modern programming languages.
What is absolutely horrific is the C switch-break construct that Wirth mentions - this one is terrible. While the concept of breaking out of a loop is relatively straightforward, breaking out of a "case" construct is not.
To understand where it comes from, one has to go back to the B language - C took this feature pretty much as is.
See there, section 5.4: https://www.bell-labs.com/usr/dmr/www/bref.pdf (https://www.bell-labs.com/usr/dmr/www/bref.pdf)
While it's very flexible, it's absolutely horrific from a readability and analyzability POV. Whoever has never forgotten a 'break' here can throw the first stone. And it also leads to demonic constructs such as the infamous "Duff's device".
Which leads to some point, while one of the key points of historic "structured programming" was a single exit point for loops, which would thus prohibit any statement that could get out of a loop outside of its main condition, this had been a source of debate for several decades - before the debate eventually got lost in history.
A 1995 paper talks about it: http://cs.stanford.edu/people/eroberts/papers/SIGCSE-1995/LoopExits.pdf (http://cs.stanford.edu/people/eroberts/papers/SIGCSE-1995/LoopExits.pdf)
Due to this being frowned upon by the structured programming principles, Pascal did not have any statement for exiting a loop.
But Wirth added one ('EXIT') in Modula-2. Modula-2 has been seen as a more practical language (to the point of still existing and being now available in GCC 13!).
https://www.modula2.org/reference/loopstatements.php (https://www.modula2.org/reference/loopstatements.php)
But then he removed it again from Oberon up to Oberon-07.
Active Oberon has reintroduced 'EXIT'. Active Oberon can also be seen as a more practical variant of Oberon.
https://en.wikipedia.org/wiki/Active_Oberon (https://en.wikipedia.org/wiki/Active_Oberon)
While a way of exiting a loop is useful (as we all know by experience and the paper above talks about), an excessive use of that can of course make your code difficult to analyze, so simplicity should still be kept as a goal IMO. Avoid an excessive number of exit points all over the place.
As to 'goto', it has no place in any reasonably structure language, and its only use in C is for lack of better constructs for doing some things, such as exiting several loop levels, or emulating some kind of "defer" construct for error handling. Those are the two most common uses of 'goto' in C, and they clearly are for lack of another construct.
I for one would favor 'tagged' loops with an 'exit' statement mentioning the tag - so the loop to be exited from would be explicit. Simple and effective, yet can't be abused for other use cases.
Something like this (the syntax is only indicative, and is similar to what Ada offers):
Rows: for (j = 0; j < Nrows; j++)
{
Columns: for (i = 0; i < Ncols; i++)
{
if (...)
exit Rows;
}
}
-
Due to this being frowned upon by the structured programming principles, Pascal did not have any statement for exiting a loop.
But Wirth added one ('EXIT') in Modula-2.
For the record, EXIT was necessary in Modula-2 because the, otherwise infinite, LOOP statement had been introduced. However, EXIT could also be used in the other Modula-2 loop constructs (i.e. FOR, WHILE, REPEAT).
The LOOP statement was dropped in Oberon-07 and EXIT went with it:
All changes were made in the interest of regularity, simplicity, completeness, and well-structuredness.
https://people.inf.ethz.ch/wirth/Oberon/Oberon07.pdf
There has been much debate, including my own comments, about this change, on the ETH Oberon mailing list. If you are interested you can read further on:
https://lists.inf.ethz.ch/pipermail/oberon/2021/015434.html
In particular, evidence of how LOOP and EXIT can be misused is here:
https://lists.inf.ethz.ch/pipermail/oberon/2021/015437.html
-
{ break, goto, continue, for, switch } all banned from my-c
and resistance is futile, they won't be assimilated ;D
-
{ break, goto, continue, for, switch } all banned from my-c
and resistance is futile, they won't be assimilated ;D
Is this because they imply an unconditional jump? If so, there are more:
- if-then-else. When the "then" branch ends, the execution has to jump at first address after the if-then-else
- while loops. At the end of the loop it is an unconditional jump, back to the start of the loop
- coroutines. They have to unconditionally jump between two areas of code executed in parallel
That leaves us with a dilemma: do we assume you are merely trolling, or do we believe you really really don't understand the concept of abstraction?
In addition to that, co-routine implementations don't necessarily "unconditionally jump between two areas of code". It might look like that at one level of abstraction, usually they will be implemented using subroutine call/return instructions.
-
Unconditional jump is when the PC (Program Counter) is overwritten with another address, without pushing its current value to the stack.
This is pretty low-level stuff. When writing non-trivial programs, we don't usually want to deal with such details all the time.
-
Unconditional jump is when the PC (Program Counter) is overwritten with another address, without pushing its current value to the stack.
And that's what I see common in those enumerated instructions by DiTBho. I've even asked if that was the criteria, then pointed a few more while writing "If so". It's the hardware point of view. Why don't you want to dismount from the high horses of abstraction, and see what they are.
Don't take programming like a religion that no one should dare look at it differently.
I got it, that for software industry, writing code has different norms and priorities.
For me, programming is different. Including the coroutines which I've used for writing a CP/M BIOS (coroutines written in Z80 assembler). The proc was only 3.5MHz, not GHz and no DMA. The incoming datastream while reading a floppy disk was too fast, so I had to manually insert jumps between to pieces of code, to satisfy the timing for both coroutines. That, to me, is a corutine. Jumping back and forth between two pieces of code.
By wikipedia, that was abstracted into
Coroutines are computer program components that allow execution to be suspended and resumed, generalizing subroutines for cooperative multitasking.
OK, whatever, I don't see coroutines that way.
I can see that, what bothers is now programmers get angry when I don't use the holy scriptures.
Amongst other reasons[1], fish get annoyed when people don't use language and terms in the same way as other fish. The purpose of these conversations is to convey meaning to other fish, and that means either using terms with the accepted meaning. If that is not possible or there is ambiguity or the possibility of error (e.g. English isn't the native language), then it is necessary for the fish to define the term.
In that vein, in this post I am using "fish" to mean "engineers, technicians, and any other person who cares about language and exchanging ideas and improving knowledge". My apologies to Humpty Dumpty and Lewis Carroll (https://www.goodreads.com/quotes/12608-when-i-use-a-word-humpty-dumpty-said-in-rather).
[1] other reasons include self-acknowledged beginners being too lazy to learn the topic, and thinking their opinions are more valid than the opinions of acknowledged masters with decades of hard-won experience.
-
About those coroutines, I've just remembered that the Z80 was slightly different than other Von Neumann architectures. Z80 has had two sets of registers. Only one set accessible at a time, and the two sets of registers were swappable in a single machine cycle. That was a very tempting feature to implement coroutines, where the program was jumping back and forth between two parallel running codes.
ARM has something similar, for interrupt processong.
In computing there are three simple and useful numbers: zero, one, many. All other numbers cause problems w.r.t. resource allocation and optimisation.
The only general use for the alternate register set is during an interrupt, to avoid having to push the registers to memory, and hence reducing interrupt latency.
Naturally, it is possible to dream up other uses, but they are are single purpose niche edge cases. They are brittle in that any change in application specification or implementation will be prone to !making the technique useless. Obvious example: needing three "parallel running codes".
-
Hmm, that sounds... fishy. ???
you need to abstract in computer science as well as in math
-
Hmm, that sounds... fishy. ???
you need to abstract in computer science as well as in math
You need to abstract in everything!
If you can't then you "can't see the wood for the trees" :)
If you can't then you will indiscriminately ask lots of boring and unimportant questions.
If you can't then, while you might be able to answer a question, you can't determine which questions are worth answering.
-
And when I try to point out that's a biased rant and not a reference paper, people start talking about my person, instead of talking about the subject.
I do not condone personal attacks but if you have the hubris to state, on a public forum, that a paper that was published in a peer-reviewed computing journal from the IEEE is a 'biased rant' then you should expect to get some strong adverse reactions. If you wish to restore some credibility then, at the very least, you should retract that statement.
-
- Another good idea that turned out to be bad is ending lines in ; , but at least that's a single keystroke
I would agree with that. Wirth would also agree. However, I suspect that you may be confusing lines with statements and terminators with separators. If so you are not alone. This is a distinction that I have often found is difficult for trainee (or even more experienced) programmers to understand.
-
{ break, goto, continue, for, switch } all banned from my-c
and resistance is futile, they won't be assimilated ;D
Is this because they imply an unconditional jump?
Not at all. There is nothing wrong with unconditional jumps.
It is the varying levels of difficulty of identifying where the jump is taking you (goto being the worst) that is the problem. If you are just writing small snippets of one-off code with a limited lifetime that nobody else if ever going to have to read or maintain then it is unlikely to concern you.
However, you should be concerned if you are ever likely to need to maintain an application with many hundreds of thousands of lines of code that have been written over several decades by a large number of programmers with varying abilities. You would then be extremely grateful if it was written in a language that prohibits, or at least restricts, the use of goto's, breaks, continues etc.
If the switch and for statements in the language were designed similarly to the case and for statements in Wirth's languages, they would be less of a worry.
-
No, not hubris.
"Hubris" was an accurate description of the attitude you display in your posts on this subject. For example: https://dictionary.cambridge.org/dictionary/english/hubris
Fast forward 10-20 years and two weeks ago I wanted to put a goto in Python for a weekend proj, some data logging from an instrument. Googled goto python, and my understanding is there is no goto in Python. That buggers me.
You may be buggered, but other more competant people probably wouldn't be.
I've wrote that I'm not a programmer, which is correct, but I'm not a stranger to it.
...
TL;DR, I'm nobody. Still can't write more than 100-200 lines. But I still need to use programming here and there. For me, programming is a tool, just like a hammer.
And yet you felt competent to criticise someone that had been a pioneering professional programmer for decades. Criticism is acceptable provided that the criticisms can be justified - and aren't merely a rant.
Never have had any intention to attack him or his work.
...
Anyways, I've never planned to attack him or his work.
Yes, you did. That's demonstrated by your repeating it in several posts.
I'm glad that you have bothered to look up various topics that you criticised, and it is to your credit that you have realised your lack of comprehension and apologised.
Overall, I don't think you've understood that a significant advantage of prohibiting naked uncontrolled gotos is that it vastly increases the code that you can easily determine that you don't have to read and understand. That's also the advantage of most abstraction mechanisms.
-
What's striking with Wirth is that, beyond his great knowledge of computer science, he has been very humble. And this humilty makes him write in a tone that will often make you first think: "not sure I agree with this". But you read a second time, and maybe a third time, and then you realize that what he wrote makes a lot of sense.
OK, in the light of that testimony it seems that I've misinterpreted the PDF. Then I've asked friends for https://doi.ieeecomputersociety.org/10.1109/MC.2006.20, which to me is behind a paywall, and the i3e paper is different from the PDF in the OP. I apologize, take back, and delete.
-
What's striking with Wirth is that, beyond his great knowledge of computer science, he has been very humble. And this humilty makes him write in a tone that will often make you first think: "not sure I agree with this". But you read a second time, and maybe a third time, and then you realize that what he wrote makes a lot of sense.
OK, in the light of that testimony it seems that I've misinterpreted the PDF. Then I've asked friends for https://doi.ieeecomputersociety.org/10.1109/MC.2006.20, which to me is behind a paywall, and the i3e paper is different from the PDF in the OP. I apologize, take back, and delete.
Oh dear.
Yet another person that attempts to rewrite delete history in an attempt to hide their actions.
Next time I will remember to quote your posts in full, so you won't be able to do that. I'll explain why I find it necessary to do that by referring to this post.
-
Deleted, so to not dent the author's reputation.
If I were to let what I've wrote here, Google bots might have index that, and show it in future search results, or ChatGPT bots might have get trained wrong in the future.
-
Deleted, so to not dent the author's reputation.
Obviously.
It is bad form to attempt to hide what other posters were responding to.
Everyone makes mistakes, but when other people respond and they then "double/quadruple down" on the mistake, the conversation should be preserved.
-
Back when I was messing around with BASIC and 6502 assembly, it didn't make any difference one way or the other whether I used GOTO or not or where, as long as the code works.
But in recent years, messing around with some 680x code dumped from a few EPROMs has given me a LOT of thought and reason to reevaluate GOTO in general - both pro and con.
It took me longer than I expected to get an understanding of the first of the two code dumps because it would at times suddenly hit a GOTO and then go in a different direction.
I eventually had to take the code dump and cut / paste it line by line in some areas to put it in proper order to understand it (if I didn't just rewrite it outright).
Even so, the few remaining GOTO statements in the cleaned code are there to redirect program flow from from the core loop to the test modules as required and return when done.
In other words, I see GOTO being acceptable to use as long as it is used in a structured programming context, and its use kept to an absolute minimum.
It may be better to break convention and just do it than go through a bunch of complex gymnastics to avoid its use.
This second code dump I'm working on... ANYONE would have a healthy dislike of the GOTO statement after trying to make heads or tails of it. Indirect jumps anyone? :rant:
They reused code via well-placed GOTOs as much as possible to sqeeze 5.5 kilobytes of code into a 4K EPROM!
-
50 years ago Dijkstra declared
the quality of programmers is inversely proportional to their number of goto statements
my-c bans goto, therefore it must be High Quality (o' really?!?) :o :o :o :o
well...sort of, see point (1)
- - -
Talking about common C/89, C/99, ...
The 2012 version of the MISRA-C Guideline for the Use of the "C Programming Language in Critical Systems" merely advises against the use of goto:
Rule 15.1 (Advisory): The goto statement should not be used
though at least the use of goto is required to be appropriately narrowed:
Rule 15.2 (Required): The goto statement shall jump to a label declared later in the same function
Rule 15.3 (Required): Any label referenced by a goto statement shall be declared in the same block, or in any block enclosing the goto statement
but ... should the 2018 Misra-update to Barr-C relax the prior ban on all use of goto?
Formally, [the goto keyword is] never necessary” as it is “almost always easy to write code without it”. They go on to recommend that goto “be used rarely, if at all.”
What?!? :o :o :o
DO178B + Misra/Barr-C says: Allow goto ***ONLY*** when it gives some benefit(1) to Exception Handling
(1)benefit = { shorter code -> less instructions, faster reaction to exception }
* * * * my-c entirely fails here
goto is absorbed by monads, but they 4x bloat the code and make it 10% slower
was/is it "high quality"?
- probably yes: from the High Level (software design) point of view
- yes: from the test-ability point of view (makes test-cases simpler)
- No: in practice since it produces worst code
not sure, but for sure here, one things is "software design", one things is "test-ability", one things is the final binary, its performance and size ...
* * * *
DO178B + Misra-2018 + Barr-C-2018 guidelines in pills :
- goto must not be used to branch into a deeper level of nesting
- goto should never be used to branch UP to an earlier point in a function
- goto should be used in an exception dispatcher to quickly route the flow to the proper handler
- goto could be used in a kernel driver as "quick fail-safe exit point"(2), if and only if, it doesn't lead to a very subtle and difficult type of bug to detect–such as a memory leak caused by the incorrect release of resources
(1)(2) my-c is basically "C with monads" and even inside an exception handler, my-c always consumes up to 4Kbyte of ram and thousand cycles to unroll into big pipeline all the involved monads to correctly find the "exception cause", thus the correct "reaction code" and which resources need to be released (by invoking their done-destruction), etc
This is as great as frustrating when compared with "goto" because it makes the "quick and safe exit point" offered by a single "goto fail_${n}" a rather slow, and big elephant, which needs to read things on its trunk before it can even plan to start moving.
But hey? I did my best here, and at least ... it's less prone to silly but sneaky "memory leakage" bugs.
-
Goto itself is just an indicator, an alarm bell. Therefore, banning goto does not help at all to produce better code.
C needs goto to break out of multidimensional loops, and for error handling. This is because C lacks better constructs to do so. If goto is forbidden, that only forces programmer to use even worse constructs to achieve the same, for example invent weird and error prone flag variables to break out of loops, or copypaste cleanup code at every exit site.
This is an excellent example of how things are: C is mediocre, and attempts to improve it usually lead to a worse language.
-
Well, I find many things I can concord wi(r)th, others I'm not 100% convinced.
E.g. APL fixed right associativity and no precedence is quite fine, the language itself requires one to think in different way, and that's just fewer rules to learn.
Not having exceptions is good*, and left associativity would make a lot of APL code (even) more complicated.
* So much so that I always keep an operator precedence chart handy in C...after more than 30 years.
Also from the paper:
In C, we may write, for example, x+++++y
I don't know about K&R - while I used it, I would never have dared to write something like that, but the paper is from 2005 (though probably a collection of earlier thoughts) and that is definitely not possible to do in C89 and later since it's interpreted as x++ ++ + y, an invalid expression.
A good portion of the argument then falls.
Also saying that using '==' led to '++', '&&' etc. sounds a bit inconsequential and naïve.
Another odd thing:
Some later hardware designs, notably the RISC architectures of the 1990s, accommodated recursive procedure calls by introducing specific registers dedicated to stack addressing
What? I'm pretty sure that stuff like 6502 and contemporary 8-bitters are from the 70's and absolutely have a stack pointer register!
(not that this weakens the points he is making about where to store a return address).
Another point I buy only partially it's the one about virtual memory:
Even forgetting about spill-over storage, in a large multiuser or multitasking system loading and unloading programs would be quite more complicated, with a loader/linker doing the remapping at launch time in a soon to be very fragmented memory space.
Also, today I learned that ALGOL is good on paper, but implementation is a nightmare, and reading code might be quite complicated.
All in all a very good read, written by a CS giant, also quite interesting from a historical perspective, but not (IMXHO) something to endorse 100%.
-
This is an excellent example of how things are: C is mediocre, and attempts to improve it usually lead to a worse language.
That's relatively true in general, but, for instance, I proposed earlier a simple way of breaking out of loops with 'tagged loops'. Which incidently is exactly what Ada offers, with a rather similar syntax.
Let me know how *this* would make C a worse language if added?
-
Also from the paper:
In C, we may write, for example, x+++++y
I don't know about K&R - while I used it, I would never have dared to write something like that, but the paper is from 2005 (though probably a collection of earlier thoughts) and that is definitely not possible to do in C89 and later since it's interpreted as x++ ++ + y, an invalid expression.
The expression above is indeed invalid with ISO C starting with C89, as the ++ operator requires an lvalue, and 'x++' isn't one. So you can't chain '++' operators. But I'm (almost) sure I've seen that in old C code (pre-ISO), things like 'x++++', so it's possibly what he had in mind. Don't forget that the point of this paper is to look back at bad ideas of the past. Not at the current state of things (even if some of what he lists is still valid today). Some of it has been abandonned, some has lingered.
A good portion of the argument then falls.
No. Again, that's probably what it was like with pre-ISO C. But even with recent C, a small change leads to a similar, yet perfectly valid expression, that is almost every bit as atrocious:
'x+++y;'.
From a syntax POV, these operators are pretty horrific.
Also saying that using '==' led to '++', '&&' etc. sounds a bit inconsequential and naïve.
Is it? Once you're ready to make up funky operators made of repeated symbols (that again pose issues from a syntax POV), there's no reason to stop at one, so I kind of agree with him here. Some languages have not stopped at 2. Javascript has '==='. And why stop there? '++?!#' doesn't look too shabby. :-DD
I think his point was mainly that devising those funky operators could only bring problems while not having much benefit compared to explicit keywords, such as 'and', 'or', etc.
Another odd thing:
Some later hardware designs, notably the RISC architectures of the 1990s, accommodated recursive procedure calls by introducing specific registers dedicated to stack addressing
What? I'm pretty sure that stuff like 6502 and contemporary 8-bitters are from the 70's and absolutely have a stack pointer register!
(not that this weakens the points he is making about where to store a return address).
Well, in this paragraph he kind of goes straight from the CDC 6000 to RISC CPUs, that's indeed quite a shortcut.
I don't know the 6502 very well, but I do know the Z80 and it had "conventional" stack pointers and there was no problem using recursion with it. I've used Turbo Pascal back in the days on the Z80 and sure wrote a ton of recursive procedures, typically to write parsers.
What the RISC ISAs (not all, but typically) added if anything regarding stacks is the ability to use any register for manipulating stacks rather than a dedicated one.
-
This is an excellent example of how things are: C is mediocre, and attempts to improve it usually lead to a worse language.
That's relatively true in general, but, for instance, I proposed earlier a simple way of breaking out of loops with 'tagged loops'. Which incidently is exactly what Ada offers, with a rather similar syntax.
Let me know how *this* would make C a worse language if added?
I agree it would be an improvement - at least not any worse - but people like you who know how to improve C do not seem to implement new languages nevertheless. Instead, DiTHBho made C worse by introducing myC :P.
-
This is an excellent example of how things are: C is mediocre, and attempts to improve it usually lead to a worse language.
That's relatively true in general, but, for instance, I proposed earlier a simple way of breaking out of loops with 'tagged loops'. Which incidently is exactly what Ada offers, with a rather similar syntax.
Let me know how *this* would make C a worse language if added?
I agree it would be an improvement - at least not any worse - but people like you who know how to improve C do not seem to implement new languages nevertheless. Instead, DiTHBho made C worse by introducing myC :P.
I did attempt it a couple years back - main features were to add module support and a few things like these tagged loops.
But - maybe out of reason - I didn't get it to completion and figured it would not be that immensely useful.
-
Instead, DiTHBho made C worse by introducing myC :P.
yup, that's one of the reason why I don't public it:
fear it's +=1 for me, but -=10 for others :o :o :o
-
Instead, DiTHBho made C worse by introducing myC :P.
yup, that's one of the reason why I don't public it:
fear it's +=1 for me, but -=10 for others :o :o :o
Well, that's the case for most programming languages that have been designed in the last 3+ decades.
That's hasn't prevented some from publishing them and sometimes even infecting the world with them. ;D
-
multidimensional loop, and escape
private void app()
{
uint32_t i0;
uint32_t i1;
uint32_t i2;
boolean_t is_done0;
boolean_t is_done1;
boolean_t is_done2;
boolean_t is_EOL0;
boolean_t is_EOL1;
boolean_t is_EOL2;
boolean_t is_err0;
boolean_t is_err1;
boolean_t is_err2;
is_err0 = False;
is_err1 = False;
is_err2 = False;
i0 = 0;
is_done0 = False;
is_done0 = (is_done0 logicalOr is_err0);
while (is_done0 isEqualTo False)
{
i1 = 0;
is_done1 = False;
is_done1 = (is_done0 logicalOr is_err1);
while (is_done1 isEqualTo False)
{
i2 = 0;
is_done2 = False;
is_done2 = (is_done2 logicalOr is_err2);
is_done2 = (is_done2 logicalOr is_err1);
is_done2 = (is_done2 logicalOr is_err0);
while (is_done2 isEqualTo False)
{
i2++;
is_EOL2 = (i2 isEqualTo 30);
is_done2 = (is_EOL2);
is_done2 = (is_done2 logicalOr is_err2);
is_done2 = (is_done2 logicalOr is_err1);
is_done2 = (is_done2 logicalOr is_err0);
}
i1++;
is_EOL1 = (i1 isEqualTo 20);
is_done1 = (is_EOL1);
is_done1 = (is_done1 logicalOr is_err1);
is_done1 = (is_done1 logicalOr is_err2);
is_done1 = (is_done1 logicalOr is_err0);
}
i0++;
is_EOL0 = (i0 isEqualTo 10);
is_done0 = (is_EOL0);
is_done0 = (is_done0 logicalOr is_err0);
is_done0 = (is_done0 logicalOr is_err1);
is_done0 = (is_done0 logicalOr is_err2);
}
}
my-c level0, should be compatible with C/89
private void app()
{
loop_t loop0;
loop_t loop1;
loop_t loop2;
init { loop0, loop1, loop2 };
bond { loop0, loop1, loop2 };
loop0.i = 0;
during loop0
{
loop1.i = 0;
during loop1
{
loop2.i = 0;
during loop2
{
loop2.i++;
loop2.is_EOL = (loop2.i isEqualTo 30);
}
loop1.i++;
loop1.is_EOL = (loop1.i isEqualTo 20);
}
loop0.i++;
loop0.is_EOL = (loop0.i isEqualTo 10);
}
}
my-c level3, see "loop" is a monad and can automatically trigger a reaction code.
"Bond" internally does something like this
is_done = (is_done logicalOr is_err2);
is_done = (is_done logicalOr is_err1);
is_done = (is_done logicalOr is_err0);
so, if one inner loop fails, the whole loop exits
with monads, you also have
- reaction code(1) if the iterator (loop0.i) is out of range
- reaction code if something invokes "failure"
- reaction code if something forces .is_done=True
(1) loop exit, in this "basic" case
-
How is setting some variable, purely to exit the loop, better than a simple break? The two do the same thing, but the variable is make work and verbose, there just to not have 'break'. With break you can at least search for it, and when you see it you know exactly what it means (which of is_donex actually terminates the loop? - easy to see the wrong one).
-
private void app()
{
loop_t loop0;
loop_t loop1;
loop_t loop2;
init { loop0, loop1, loop2 };
bond { loop0, loop1, loop2 };
loop0.i'range = { 0 .. 10 };
loop1.i'range = { 0 .. 20 };
loop2.i'range = { 0 .. 30 };
during loop0
{
during loop1
{
during loop2
{
loop2.i++;
}
loop1.i++;
}
loop0.i++;
}
}
(bad?) side effect: it works ;D
-
Why is there 'loopn.i++'? Surely, a run around the loop counts as +1 so you shouldn't need to increment anything. In fact, having to increment the loop counter makes a mockery of it since you could make it any value: 1, 2, 24, -6, 3,...
Given that context, the C style of having the loop counter within the loop definition seems preferable: it's in one defined place, easily digested and no hidden gotchas buried in the loop somewhere (at least, there shouldn't be).
-
How is setting some variable, purely to exit the loop, better than a simple break? The two do the same thing, but the variable is make work and verbose, there just to not have 'break'. With break you can at least search for it, and when you see it you know exactly what it means (which of is_donex actually terminates the loop? - easy to see the wrong one).
This is questionable - I'll again refer to the additional article I posted about exiting loops.
One reason to use flags to exit loops rather than instructions that directly control the flow is to have the loop "condition" at a single place in the loop's construct rather than spread out everywhere in the loop's body. The main idea is that the loop's condition should be the loop's invariant. The invariant should be unambiguous, written at a single place, and ideally easy to understand.
The problem is that while some algorithms lend themselves very well to this approach, others do not and would be pretty hard to write with this strict model.
And then, if you artifically set intermediate flags in the loop's body just to fit this strict model, you'll quickly run into a pretty similar situation as with additional flow control statements within the loop - just possibly even harder to read.
Sometimes, you can rewrite your loop in a way that better fits the "invariant" model. That may imply splitting one loop into several distinct ones.
As it doesn't come very naturally to most of us, we tend to prefer having a way to break out of loops in direct fashion, even if that makes analyzing the invariants much trickier.
But strictly speaking, if you can't exactly tell what your invariant is, you don't know what your loop does.
-
Why is there 'loopn.i++'?
as much as advanced the "auto loop" is, it still needs "a hamster to spin the wheel" (what? )
and you end up needing "something" that increments the counter :o :o :o
Note, i++ is a saturated increment operator(2), which guarantees the counter never goes out of its range
having to increment the loop counter makes a mockery of it since you could make it any value: 1, 2, 24, -6, 3,...
the symbol ' means "property", you assign the range { lower .. upper } property to the loop counter
always guaranteed: lower <= counter <= upper
property is a great trick in my-c as it permits other tricks ;D ;D ;D
This example uses a side effect to automatically re-initialize the counter when it encounters the keyword "during", and that's it, all the rest works exactly as the previous two examples, just it's all "hidden", but as soon as the counter is equal to the counter'range.upper, is_EOL becomes true, is_done becomes also true, all auto-magically, and the loop ends.
However, in this example there is also a second side effect, and a difference a difference from the previous first example: this time, if the loop ends without an error then the counter is ***exactly*** equal to the upper bound.
C/89 loop:
for (i=0; i<10; i++) { } ;
/* i'range = { 0 .. 9 }
the counter i is equal to 10 at the end of the loop ----------> potentially an "out by one" bug(1)
C/99 loop:
for (uint32_t i=0; i<10; i++) { } ;
/* i'range = { 0 .. 9 }
the counter i is ... no more existing after the loop :o :o :o
my c previous first example:
the counter is equal to 10 at the end of the loop ------------> potentially an "out by one" bug(1)
my C auto loop:
loop.i'range = { 0 .. 9 };
during loop { loop.i++; }
/* i'range = { 0 .. 9 }
loop.i = 9 at the end of the loop
Given that context, the C style of having the loop counter within the loop definition seems preferable: it's in one defined place, easily digested and no hidden gotchas buried in the loop somewhere (at least, there shouldn't be).
in C you can go over the counter range and you can be "out of one"; in my-c it is impossible as being strict in-range is guaranteed.
In C you have to think a way to "exit" from an inner loop (goto? break?), in my-c you just need to invoke .is_EOL or .is_done, that's good as it facilitates step-by-step manual debugging and ICE-testcases.
edit:
(1) when the counter is used in some following statement under the belief that it is in-range
(2) you can override its reactive code callback and invoke "panic()" or a "console_out_warning()" to be warned that a counter has gone out of its range -> probably a bug.
-
One reason to use flags to exit loops rather than instructions that directly control the flow is to have the loop "condition" at a single place in the loop's construct rather than spread out everywhere in the loop's body. The main idea is that the loop's condition should be the loop's invariant.
that's what an ICE wants.
So, it's better for test-cases.
-
One reason to use flags to exit loops rather than instructions that directly control the flow is to have the loop "condition" at a single place in the loop's construct rather than spread out everywhere in the loop's body.
Yes, I accept that. That lets you know at least what you are looking for, but it's then still a hunt for where it is being set. The use of an exit flag doesn't actually help much more in knowing why the loop is done. I mean, what does the variable "done" mean? There is also scope for gymnastics in trying not to do things in the loop after the exit determination but before the end of the loop body so the flag can trigger the exit. Of course, if one had designed the thing better in the first place...
But strictly speaking, if you can't exactly tell what your invariant is, you don't know what your loop does.
Indeed. However, one may not own the loop (that is, it is not 'my' loop but someone elses that I am trying to figure out what it does), so the probability is that one doesn't know anyway.
-
Why is there 'loopn.i++'?
as much as advanced the "auto loop" is, it still needs "a hamster to spin the wheel" (what? )
and you end up needing "something" that increments the counter :o :o :o
Note, i++ is a saturated increment operator(2), which guarantees the counter never goes out of its range
having to increment the loop counter makes a mockery of it since you could make it any value: 1, 2, 24, -6, 3,...
the symbol ' means "property", you assign the range { lower .. upper } property to the loop counter
always guaranteed: lower <= counter <= upper
property is a great trick in my-c as it permits other tricks ;D ;D ;D
This example uses a side effect to automatically re-initialize the counter when it encounters the keyword "during", and that's it, all the rest works exactly as the previous two examples, just it's all "hidden", but as soon as the counter is equal to the counter'range.upper, is_EOL becomes true, is_done becomes also true, all auto-magically, and the loop ends.
However, in this example there is also a second side effect, and a difference a difference from the previous first example: this time, if the loop ends without an error then the counter is ***exactly*** equal to the upper bound.
C/89 loop:
for (i=0; i<10; i++) { } ;
/* i'range = { 0 .. 9 }
the counter i is equal to 10 at the end of the loop ----------> potentially an "out by one" bug(1)
C/99 loop:
for (uint32_t i=0; i<10; i++) { } ;
/* i'range = { 0 .. 9 }
the counter i is ... no more existing after the loop :o :o :o
my c previous first example:
the counter is equal to 10 at the end of the loop ------------> potentially an "out by one" bug(1)
my C auto loop:
loop.i'range = { 0 .. 9 };
during loop { loop.i++; }
/* i'range = { 0 .. 9 }
loop.i = 9 at the end of the loop
Given that context, the C style of having the loop counter within the loop definition seems preferable: it's in one defined place, easily digested and no hidden gotchas buried in the loop somewhere (at least, there shouldn't be).
in C you can go over the counter range and you can be "out of one"; in my-c it is impossible as being strict in-range is guaranteed.
In C you have to think a way to "exit" from an inner loop (goto? break?), in my-c you just need to invoke .is_EOL or .is_done, that's good as it facilitates step-by-step manual debugging and ICE-testcases.
edit:
(1) when the counter is used in some following statement under the belief that it is in-range
(2) you can override its reactive code callback and invoke "panic()" or a "console_out_warning()" to be warned that a counter has gone out of its range -> probably a bug.
I just wish that if the coder is aware/worried of the potential off-by-one, please just put an if statement with the boundaries specified in the code and better yet, comment it so we know what you were thinking/expecting the code to do.
Ok. Off my soap box. :)
-
Why is there 'loopn.i++'?
as much as advanced the "auto loop" is, it still needs "a hamster to spin the wheel" (what? )
and you end up needing "something" that increments the counter :o :o :o
Surely the loop, ah, looping would step through the desired range. Where you've specified the upper and lower limits, shouldn't you also specify the step?
Note, i++ is a saturated increment operator(2), which guarantees the counter never goes out of its range
Quite, but you still have to manually move it along, and move it along at a specific place (to prevent problems similar to off-by-one), and can still mess with it going forward or backward or missing sub-ranges, or even using the same value three times before moving on.
C/99 loop:
for (uint32_t i=0; i<10; i++) { } ;
/* i'range = { 0 .. 9 }
the counter i is ... no more existing after the loop :o :o :o
I don't see the problem with this. You have the option to restrict the loop counter to the loop (sensible IMO) but can opt to make it available outside if you want. It's just another means of specifying scope. If you don't like this then you should also be horrified at defining variables within the loop body, which go out of scope (and disappear) at the end. But isn't this kind of thing why the idea of scope exists, or are we meant to prefer the idea of global variables?
-
the step can be achieved with +=step
loop.i += step;
and the counter will be still constrained to the upper range boundary.
-
How is setting some variable, purely to exit the loop, better than a simple break? The two do the same thing, but the variable is make work and verbose, there just to not have 'break'.
Yeah. The variable way is how it's taught at school infested by "goto considered harmful" -tier professors, or if the language lacks the control instructions. And it's again more surface area for bugs.
Classic mistake is using a variable to avoid using goto:
bool continue = true;
for(int i = 0; continue && i < i_end; i++)
{
// some code 1
for(int o=0; continue && o < o_end; o++)
{
// some code 2
if(break_condition)
continue = false;
// more code 2
}
// more code 1
}
The issue here is that "more code 1" and "more code 2" run after the break_condition. If this is what you want, then fine, you should use the variable, and the variable name would communicate it. But if you want to break, then adding the variable itself and modifying the loop exit condition is not enough, but you need to modify the code more:
bool continue = true;
for(int i = 0; continue && i < i_end; i++)
{
// some code 1
for(int o=0; continue && o < o_end; o++)
{
// some code 2
if(break_condition)
continue = false;
if(continue)
{
// more code 2
}
}
if(continue)
{
// more code 1
}
}
Which is getting quite nasty (see Don't Repeat Yourself.)
The purpose of language is to provide things programmers need to make their code more readable, writable and understandable. Status variables and breaks/gotos are not alternatives, they cater to different purposes and are both needed. Besides, that termination condition (continue && i < i_end) easily goes wrong.
-
Quite, but you still have to manually move it along, and move it along at a specific place (to prevent problems similar to off-by-one), and can still mess with it going forward or backward or missing sub-ranges, or even using the same value three times before moving on.
I don't get your point :-//
but, anyway, you can change the range property when and where you wish, it's not immutable.
Also, inside the loop you can check if the loop is going to end.
if (loop.is_done isEqualTo True) { ... }
as well as you can check the reason of its ending
- an "error" inside the current loop
- an "error" inside the inner loop (here you need to "bound" monads)
- the counter has reached it's upper boundary
- other reasons (here you need to "bound" monads)
if (loop.is_err isEqualTo True) { ... }
if (loop.is_other_causes isEqualTo True) { ... }
is_done is true when one of them is true
I don't see the problem with this.
I see a lot of bugs with this, especially with strings and arrays/matrices :o
defining variables within the loop body, which go out of scope (and disappear) at the end
indeed "defining variables within the loop body" is banned in my-c as the ICE needs to know the stack size in the worst case, as well as a counter is usually re-cycled and used even *after* the loop.
That means all the variables (including counters) must be declared immediately in the head of the function body (80s C coding style, I know, I know ;D ) rather than here and there along the algorithm.
-
Classic mistake is using a variable to avoid using goto:
only if you are not good at planning your code :o :o :o
-
Quite, but you still have to manually move it along, and move it along at a specific place (to prevent problems similar to off-by-one), and can still mess with it going forward or backward or missing sub-ranges, or even using the same value three times before moving on.
I don't get your point :-//
during loop0
{
during loop1
{
during loop2
{
loop1.i++;
...
if (weather == WS_WARM) loop2.i -= 3;
...
}
loop1.i++;
}
loop0.i++;
}
defining variables within the loop body, which go out of scope (and disappear) at the end
indeed "defining variables within the loop body" is banned in my-c as the ICE needs to know the stack size in the worst case, as well as a counter is usually re-cycled and used even *after* the loop.
[/quote]
Sounds like you are writing the language to suit a specific tool. Which is kind of OK as a tool-specific, er, tool but a bit detrimental for a general purpose language. There is no reason why you can't use the style that scope-locks the counter if that's what you want. There are good reasons not to access the loop counter outside the loop too.
-
if (weather == WS_WARM) loop2.i -= 3;
inside the loop, each incrementer has saturated logic, guaranteed to always be in-range.
I always spend a lot of time AAL-designing the code to avoid to introduce things like in your example, when possible, and usually it's possible, and when it's not ... I write a dispatcher.
With my-c I have already written
- a b+tree filesystem, nothing special, proof of concept, but the b+tree module is polymorphic
- a gauss-full-pvoting-based polymorphic systems of equations, the matrix cells can be complex, real, natural, ...
- a lib tokenizer, uses safestring, it's used by { my-ucshell, my-c }
- safestring and its utils, massively replaces "string_t"
- filename utils for bash-scripting (uses safestring)
- a micro shell (uses safestring)
- my-c itself has been rewritten in my-c (--level2, the next gen will be --level3, so ... with auto loops, prologues and epilogues, end more new stuff), the initial code was c-89
I know it requires shocking constraints such as {no goto, no continue, no for(), ... }, but, as those projects have some level of complexity, from having them done with less frustration than their c/89 versions, I also know it can be done with final benefits.
Sounds like you are writing the language to suit a specific tool. Which is kind of OK as a tool-specific, er, tool but a bit detrimental for a general purpose language. There is no reason why you can't use the style that scope-locks the counter if that's what you want. There are good reasons not to access the loop counter outside the loop too.
my-c is a personal and private project without the pretext of having any authority. It's used to design advanced AI-assisted ICEs, which is my second core business, and I only sometime mention the work environment (avionics) in which I operate, where many of the things I report for my "toy compiler" are actually prohibited by the DO178B guideline.
is my-c even "detrimental" for a general purpose language? bah ... so I'm right not to release it ;D
That's what I am afraid of: it works for me, it works for my ICE, but will it work for others?!?
Mumble
I don't want to wake up in the morning and find a dead horse's head in bed (funny saying(1)) for the arrogance of claiming that, if not only it "de facto" works but also makes less stressing most of the constrains I have to consider in my job, then it's somehow "superior/better" to traditional compilers :-//
(1) plus, OpenSource is becoming "dangerous" in Europe. a law of the European parliament is being discussed these days which, if approved, will make "single-person projects" very disadvantageous to release opensource because the authors will be held legally responsible for any damage caused by their software.
(brrrrrrrrrr)
-
guaranteed to always be in-range
The point I was trying to make was that 'in-range' does not equate to 'valid'. I tried to show this by having various silly values, all of which could be in-range but are obviously nonsensical.
-
my-c is a personal and private project without the pretext of having any authority
That's fine, and absolutely valid. But I'm not sure of the value of promoting such things in other contexts, which is why I bring up the points I have. For what you want from it, it is surely ideal :)
-
my-c is a personal and private project
You talk about it publicly so much and in such great detail I don't think it's purely personal and private anymore :)
-
You talk about it publicly so much and in such great detail I don't think it's purely personal and private anymore :)
well, for pure enthusiasm and because in this forum you are all far away from constrained environment (like DO178B) so, I thought it was "informative" at least, but I was wrong.
Sorry.
-
No need to be sorry. Just expect to see it being treated like any public project in discussions.
-
Not everyone has the opportunity to get their project backed by Mozilla and then become the absolute best thing since sliced bread. ;D
-
You talk about it publicly so much and in such great detail I don't think it's purely personal and private anymore :)
well, for pure enthusiasm and because in this forum you are all far away from constrained environment (like DO178B) so, I thought it was "informative" at least, but I was wrong.
Expect to get occasional negative comments in general for anything personal you talk about/show off on forums and social media. That's just what's bound to happen.
Most people tend to be more vocal about their negative thoughts than their positive ones.
That said, in this specific case, probably the point that doesn't "help" is that you are more or less answering very general programming questions with very specific solutions oriented towards your own needs and particular tools, so you can expect people to point it out.