is it a good idea to use Goto statement? - Page 1
Forum section: electronics / general

author: Picuino
author_rank: Super Contributor
timestamp: May 25, 2020, 12:56:37 pm
content: Since Edsger Dijkstra's letter "Go To Statement Considered Harmful" appeared in 1968, this statement has become synonymous of bad programming.https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdfHowever many programmers think there is still room for goto in modern programming.Structured Programming with go to Statementshttp://www.clifford.at/cfun/cliffdev/p261-knuth.pdfGood Use Of Gotohttps://wiki.c2.com/?GoodUseOfGotoGOTO Still Has a Place in Modern Programming. No! Really!https://smartbear.com/blog/develop/goto-still-has-a-place-in-modern-programming-no-re/What do you think about that?

author: nfmax
author_rank: Super Contributor
timestamp: May 25, 2020, 12:59:49 pm
content: No

author: Fred27
author_rank: Unknown
timestamp: May 25, 2020, 01:02:28 pm
content: I'd you can find a case where using a goto makes your code easier to read, maintain and extend - especially by someone else - then I'd say it's fine. I doubt you will though.

author: SiliconWizard
author_rank: Super Contributor
timestamp: May 25, 2020, 01:11:37 pm
content: You have to put all this in context. Around that time, a few people were advocating "structured programming", whereas "spaghetti programming" was still relatively common.Introducing specific flow control constructs instead of "hand-crafting" loops with IF's and GOTO's was a big step forward.Now it's certain that you can use GOTO's in structured programming, like Knuth's article shows. But that still makes code a lot less readable overall.These days, there is one lingering use of goto (that I still use too) in C for instance, for error handling. It allows to have a single exit point in functions, which is often desirable (and even a rule in some coding guidelines.) Thing is, we use goto for lack of any other construct. A "throw-catch" construct allows a single point for handling errors, while being more structured (and I'm saying that independently of exceptions, but just as a flow control construct.) C doesn't have that, and C++ does, but only if you're willing to use exceptions, so I'd say it doesn't replace goto's completely either.Likewise, goto can allow to exit nested loops, although a typical, more structured approach usually consists in using flags and only a one-level exit (such as break.)But as soon as you multiply goto labels, it quickly becomes a big mess.Beyond mere structure, the whole idea behind structured programming was the ability to define invariants for instance, and clear and single-point conditions for loops. As soon as you introduce goto's that can change the flow, you make it much harder to prove that a loop's invariant is respected, or what the exit condition really is.Long story short: still using goto for error handling (mostly) in languages that don't have better, but otherwise not. And when I do, I avoid multiple labels. Only one per function.

author: Nusa
author_rank: Super Contributor
timestamp: May 25, 2020, 01:13:09 pm
content: Provide a definition of "modern programming" thateveryone agrees withand I will answer the question. Proof of universal agreement required up front.

author: RoGeorge
author_rank: Super Contributor
timestamp: May 25, 2020, 01:18:36 pm
content: If we could only live our lives without paying so much attention to all these ideologies...There's nothing wrong with go to. Real world shows it's heavily used.If that seems hard to believe, download the Linux Kernel sources and grep for all the goto lines. I did it some years ago, when Linux kernel was only about 10 million lines. About0.3%1% of all the C lines were using a goto.https://www.elforum.info/topic/64219-initiere-in-c-pentru-microcontrolere/page/5/?tab=comments#comment-689462Later edit:Sorry,1% of all C lines in the Linux kernel (linux-3.5.4.tar.bz2) were 'goto's.0.3% of all C lines were either 'goto out', 'goto err' or 'goto fail'.

author: TimFox
author_rank: Super Contributor
timestamp: May 25, 2020, 01:21:55 pm
content: IIRC, "structured programming" regarded the GOTO statement as a misdemeanor, the conditional GOTO as a felony, and the Fortran computed GOTO as a capital offense. The latter could send the program into the operating system if an unanticipated result of the computation sent the GOTO beyond the expected range.

author: ebclr
author_rank: Super Contributor
timestamp: May 25, 2020, 01:38:44 pm
content: 1ST use of gotoA reset Vector,2nd useInterruption vectorIt's near impossible to do that without a goto or something like

author: bd139
author_rank: Super Contributor
timestamp: May 25, 2020, 01:43:43 pm
content: Edit: Withdrawn comment. I coded myself out of using the goto. So no they aren't needed

author: greenpossum
author_rank: Frequent Contributor
timestamp: May 25, 2020, 01:46:02 pm
content: I've always wanted to use a COMEFROM statement (https://en.wikipedia.org/wiki/COMEFROM), especially the computed COMEFROM.

author: ebclr
author_rank: Super Contributor
timestamp: May 25, 2020, 01:50:03 pm
content: In the above example, "goto" isn't the best choice, Break is the right one to exit a for loop premartully

author: 0xdeadbeef
author_rank: Super Contributor
timestamp: May 25, 2020, 01:50:42 pm
content: In C, "Goto" is still the most efficient way to leave a loop that has more than one level. Java introduced break and continue with a label for this purpose.As using multiple returns from a function, it's considered bad style by the people behind MISRA and the like. Which of course doesn't really make it bad style.Anyway, in the industry you need to learn to follow coding guidelines which are typically written by people who never actually coded something in the last ten years.

author: ebclr
author_rank: Super Contributor
timestamp: May 25, 2020, 01:51:35 pm
content: The "COMEFROM" existIs called Stack, When you call a function the stack will hold all the Comefrom address

author: chriva
author_rank: Regular Contributor
timestamp: May 25, 2020, 01:56:04 pm
content: Generally no. I use it once a week during very heaving coding. You tend to get the feel for when it's better than some weird complex logic

author: artag
author_rank: Super Contributor
timestamp: May 25, 2020, 03:38:48 pm
content: State machines can usually be coded as switch statements but goto is possibly more clear.It's best to avoid ideological stances that insist on a particular layout. The critical thing is not what language features you use but whether they're a) efficient and b) clear. Yes, it's easy to write spaghetti code with goto. You can do it even more effectively with break, continue and switch (see Duff's device if you don't believe me), because the targets of those are marked with braces in a page awash with braces, rather than by explicit, clear and meaningful labels.The overriding concern is efficienmcy. Don't sacrifice it for clarity. Clarity can easily be restored using layout and comments. But structure alone doesn't create clarity. It can do the opposite.Look at Python for an example of this. The author tried to force layout to follow structure by using layout to create structure. It's a disaster, though pythonistas are too inbred to admit it. No flexibility.C, where you can use whitespace as well as comments to show control or data flow, can be far more readable. Just because obfuscated C is also possible doesn't mean you have to use it : you can use that flexibilty for good as well as evil. In fact, that's the point of obfuscated C - it shows how you can tell a story with layout that is unimpeded by the needs of structure.

author: Cyberdragon
author_rank: Super Contributor
timestamp: May 25, 2020, 03:41:04 pm
content: "Jump" in assembly would like to know your location.

author: golden_labels
author_rank: Super Contributor
timestamp: May 25, 2020, 04:26:30 pm
content: The question is of the same kind as “is it ok to test if a wire is live by touching it with a finger?” or “is it ok to not use ESD protection?”. You will find hundreds and hundreds of people, who claim that they did it or know someone who did. They will tell you “it works”, merely because they are not yet aware of a situation in which this fails. And if you argue against, some will produce synthetic scenarios in which this makes sense — responding to which is a waste of time, because they are fallacies. GoTo is the same.As for the answer: there is a good heuristic. If there is a positive correlation between the portion of people expressing opinion X and the time those people spent in some engineering/development field, it is very likely opinion X is right. Limit the age to 20 years: after that too many people refuse to learn new things and will tell you that it is good to do whatever they learned in those first 20 years.There are two important use cases for GoTo and similar concepts(1): one is more general that the GoTo itself, the other is circumventing effects of earlier mistakes. The first one is in the category of providing compiler-specific optimizations to code that the compiler itself can’t optimize properly. As any true optimization, the need for providing it should be proven. In this case it requires reading the compiled binary and understanding how the compiler has failed, so if you can’t read assembled code, you are employing shotgun debugging. The second case is going around the limitations of the tool chosen for the job. As an example: C has no syntax to express exceptional flows conveniently, so one may define macros that emulate those with thegotoinstruction. This wouldn’t be needed if one would choose the right tool in the first place, but often we do not have any choice. Be aware that both uses still have serious risks associated with using GoTo, but at least they also have someimportantsupporting arguments.____(1)break/continuein a loop,returnin a loop etc. are not different if the concept you have in mind is the same. It doesn’t matter you expressed the same idea with a different word.

author: nctnico
author_rank: Super Contributor
timestamp: May 25, 2020, 04:34:11 pm
content: Quote from: golden_labels on May 25, 2020, 04:26:30 pmTrue. And I agree with SiliconWizard that using goto (in C) to create a single exit point from a function is actually a very good use of goto. Returning from various points in a larger function leads to code which is hard to read & modify.

author: free_electron
author_rank: Super Contributor
timestamp: May 25, 2020, 04:48:44 pm
content: and what does the compiler produce ? JMP JMP JMP. which is nothing but ... goto.So there . you are all (unknowingly) using a massive amount of GOTO. Because that is how processors go to a location. Same with directly loading the address pointer. That is nothing but a 'goto'. Same thing like bit test and skip operations. those are nothing but a if " x = <boolean> then goto ". actually, if more than one operation needs to be done in the pass operation the code there becomes a gotoCode:test :BTFSC * bit test skip if clear. the following line will be skipped if clear so we land at 'handle_if_clear'JMP handle_if_dirtyhandle_if_clear:yadda ...JMP were_donehandle_if_dirty :yadda ...were_done:alliswell ...So , if you let the compiler do it ? why are you so afraid of using it ?GOTO is perfectly safe. as long as you take care not to imbalance the stack. You can use it to gracefully skip a chunk of code INSIDE the same routine.

author: Jr460
author_rank: Regular Contributor
timestamp: May 25, 2020, 04:58:41 pm
content: Not only that but many many bugs have been caused but a routine that allocates some buffer/resource, and a discovered error/exception causes an early exit of the routine. The buffer/resource didn't get returned or freed up. Having a common exit where the cleanup is done and then the correct status returned goes long way in preventing these bugs.

author: PKTKS
author_rank: Super Contributor
timestamp: May 25, 2020, 05:24:15 pm
content: Quote from: free_electron on May 25, 2020, 04:48:44 pmAnyone used to code in assembly will answer same thingI can not even live without that statementit does a magical simplification where insteada complex logic would be required.It has no substitute for simplificationPaul

author: chriva
author_rank: Regular Contributor
timestamp: May 25, 2020, 05:33:38 pm
content: if / else produce the same thing as goto in assembler. You're oversimplifying things...

author: artag
author_rank: Super Contributor
timestamp: May 25, 2020, 05:38:12 pm
content: Jump and goto are just an assignment where the register used for the program counter is the target or lvalue. Most assembly languages provide an explicit jump mnemonic but the underlying instruction may have very similar composition - including conditionals and source values - as more general operations.The hard bit is managing the other resources the compiler allocated in the code - explicit memory allocation like malloc() or file resources like open() are obvious examples (so using goto to create a single exit point should be done with care : you'll often arrive there with some, but not all the resources allocated and you have to unwind the cleanup).The most important example of this is the stack frame. Even if an alternate register (BP on the x86) is used to index auto variables, SP has to be moved below local allocations or an interrupt will overwrite them, so jumping to the return instruction is almost never right : you have to jump to the exit veneer which restores the calling stack pointer before returning.

author: chriva
author_rank: Regular Contributor
timestamp: May 25, 2020, 05:46:12 pm
content: Quote from: artag on May 25, 2020, 05:38:12 pmAbout that. I think this is slightly compiler/version and target dependant also.You do ofc have to make sure allocated memory is freed and all that but the stack handling is usually separate to the rest of the gunk. Even if you were to jump to the end of the function or just pass "return" it'll usually parse a branch in assembler and go to the stack restoration stuff at the very end of the function. At least in my experience. Would gladly be proven wrongIf you do inline assembler on the other hand, yeah.. easy to shoot ones feet lol

author: golden_labels
author_rank: Super Contributor
timestamp: May 25, 2020, 05:50:49 pm
content: Quote from: free_electron on May 25, 2020, 04:48:44 pmWhat a textbook example of a strawman. I haven’t seen this one for years WRT goto.That is missing the point. We do not talk about what the compiler produces or whether the processor doing jumps is fine or not. The discussion is about theabstract representationof a procedure, that has to be described to the compiler for it to be able to generate code. Of course, if one writes code in an assembler language, one uses jumps or similar instructions(1). But this is not about writing in such a language — it should be obvious.Note: before anyone points out that I am myself actually not delivering any arguments in my earlier post: yes, I am intentionally shifting the perspective. Why am I doing this is a matter for a separate discussion.____(1)branches, jump-overs, calls, rets are in their essence the same.

author: Mechatrommer
author_rank: Super Contributor
timestamp: May 25, 2020, 06:37:32 pm
content: Quote from: free_electron on May 25, 2020, 04:48:44 pmi was about to say this. since you mentioned it, there is no need for me to repeat. the idea that people (the programming language architects) tried to prevent you from using goto is readability/manageability and safer code by encapsulating "gotos" (jmps) in managed-like language structures such as if, loop, for, sub routines with automated prologue/epilogue-stack/memory management trickeries to ensure safe entry, reentry, exit and re-exit. so if one cant debug their or others code well enough, using gotos in their code will harm themselves. in my latest code, at first i was using interrupt subroutines structures thats recommended by anyone in the industry and because i want to play neat and tidy. but it turned out it cant perform in timely manner (small and slow attiny13a and out of spec/undeterministic trigger delay) so i have to redo and restructure in the raw metal and messy pooling method in big conditional state machine structure with gotos everywhere. if one cant debug well enough, avoid this type of structure, or the business at all, let alone coding in assembly(which i myself tried to avoid in the latest code if i want even a slight glimps of readability)

author: Syntax Error
author_rank: Frequent Contributor
timestamp: May 25, 2020, 07:42:55 pm
content: As eluded, GOTO belongs in assembler development... where it's jump or branch. Otherwise everything else is nested, object based structures.https://en.m.wikipedia.org/wiki/Branch_(computer_science)Geek fights could rise (on Reddit) from it's use in antique control languages like DCL, DOS and JCL, or in classic 1980's home micro Basic; where program flow jumps to specific line numbers or labels, and then advances on line by line... just like in assembler where pc <- 1 + pcSome developers may never have heard of a goto statement, let alone used one.Basic had a function-like call, the GOSUB.Code:#stack attack....10 GOSUB 2020 GOSUB 10

author: RenThraysk
author_rank: Regular Contributor
timestamp: May 25, 2020, 08:14:54 pm
content: Think it rather depends on where you are on the high level programming learning curve.If just starting out, not using gotos is a good thing, just to realise can probably solve the vast majority problems without them.Gotos are useful for simplification of code generation tools, like compiler compilers (Bison & YACC type stuff), where the generated code shouldn't even need to be looked at by a human.And there are some circumstances were using computed gotos are used as an optimisation, like in interpreted languages like Ruby and Python, as a faster implementation of a switch.

author: chriva
author_rank: Regular Contributor
timestamp: May 25, 2020, 09:32:14 pm
content: (Hope I'm not making an idiot out of myself since I just wrote this as an example)This is a case where I'd prefer goto. One of very few cases I must add but if you follow the datasheet you'll have an easier time following their flowchart.Code:#define fCommand(cm) \*(uint8_t *) 0x5555 = 0xaa; \*(uint8_t *) 0x2aaa = 0x55; \*(uint8_t *) 0x5555 = (cm);#define DQ5 (1<<5)#define DQ6 (1<<6)goto:Code:static uint8_t wToggle(const void *dat, const uint32_t address, uint32_t len){volatile uint8_t *dst = (uint8_t *) address; // Warnings are usually a bad sign but I'm wholeheartedly ignoring this *#%%erconst uint8_t *buf = dat;uint8_t tgl;while (len--){if (*dst != *buf){// Send command and datafCommand(0xa0);*dst = *buf;do {tgl = *dst ^ *dst;// DQ6 not toggling, we're done!if (!(tgl & DQ6))goto pass;} while (!(tgl & DQ5));// Perform second read, DQ5 indicates an error. Is it in transition or an actual fault?if ((*dst ^ *dst) & DQ6)return 1;}pass:dst++;buf++;}return 0;}Regular:Code:static uint8_t wToggle(const void *dat, const uint32_t address, uint32_t len){volatile uint8_t *dst = (uint8_t *) address; // Warnings are usually a bad sign but I'm wholeheartedly ignoring this *#%%erconst uint8_t *buf = dat;uint8_t tgl;while (len--){if (*dst != *buf){// Send command and datafCommand(0xa0);*dst = *buf;// Toggle bits..do {// Which bits are toggling?tgl = *dst ^ *dst;} while (!(tgl & DQ5) && (tgl & DQ6));if (tgl & DQ5)tgl = *dst ^ *dst;// FAIL!if (tgl & DQ6)return 1;}dst++;buf++;}return 0;}

author: artag
author_rank: Super Contributor
timestamp: May 25, 2020, 10:48:15 pm
content: Quote from: chriva on May 25, 2020, 05:46:12 pmOh, absolutely I would expect the compiler to correctly handle stack frame correction regardless of where the goto goes. Even within locally scoped blocks.Yes, this had drifted into assembler equivalents of HLL constructs. You're on your own in assembler

author: golden_labels
author_rank: Super Contributor
timestamp: May 25, 2020, 10:55:58 pm
content: Diverting a bit from thegoto, but I need to note this. Thegotoalone is covered in the last paragraph.You are missing curly braces around thefCommandmacro definition. Keep in mind that neither C compiler nor C preprocessor care about indentation and do not understand thatfCommandis used as a single operation. Currently it may produce invalid code in some contexts. E.g.Code:if (cond) fCommand(arg);… will produce:Code:if (cond) *(uint8_t *) 0x5555 = 0xaa; *(uint8_t *) 0x2aaa = 0x55; *(uint8_t *) 0x5555 = (arg);;… which, with some stuff added for clarity, means:Code:if (cond) {*(uint8_t *) 0x5555 = 0xaa;}*(uint8_t *) 0x2aaa = 0x55;*(uint8_t *) 0x5555 = (cm);(void)0;This belongs to a wider range of issues related to forgetting that C preprocessor is a separate step that works on text, without having any understanding of the actual C code. Missing parens around complete macro expressions is another such situation. In this particular case you may use:Code:#define fCommand(cm) do {\*(uint8_t *) 0x5555 = 0xaa;\*(uint8_t *) 0x2aaa = 0x55;\*(uint8_t *) 0x5555 = (arg);\while (0)Note no semicolon after that. That topic is covered byC-FAQ 10.20,10.1,CERT C Coding Standard PRE10-C,PRE02-C,PRE11-C, and may lead toCWE-483(which coincidently lists one of the most famousgotofails an example).If there is no reason to not do so, perhaps a function will be better?Code:static inline void fCommand(uint8_t const cm) {*(uint8_t*)0x5555 = 0xAA;*(uint8_t*)0x2AAA = 0x55;*(uint8_t*)0x5555 = cm;}I am unaware of what platform you are using, so the current solution may be ok or even strictly required, but shouldn’t it be a cast touint8_t volatile*instead ofuint8_t*? While both versions may produce code that optimizes out the first write to 0x5555, the latter one is in the general case unlikely to do so. But I can’t clearly say “you should”, because not only I don’t know that platform, but if*dst ^ *dstis not a constant expression yielding always 0, this one also shouldn’t.While we’re at it:*dst ^ *dstis symmetric, but I hope you are aware that the order of reads is unknown.As for structuring the code, aren’t this equivalent?Code:static uint8_t wToggle(const void *dat, const uint32_t address, uint32_t len){volatile uint8_t *dst = (uint8_t *) address; // Warnings are usually a bad sign but I'm wholeheartedly ignoring this *#%%erconst uint8_t *buf = dat;while (len--) {if (*dst != *buf) {bool waiting = true;// Send command and datafCommand(0xA0);*dst = *buf;do {uint8_t const tgl = *dst ^ *dst;if (!(tgl & DQ6)) {waiting = false;} else if (tgl & DQ5) {waiting = false;if ((*dst ^ *dst) & DQ6) {return 1;}} // else: skip; still waiting} while (waiting);}++dst;++buf;}return 0;}But note that I do not know peculiarities of your platform. On Linux/x86_64 and AVR8 (ATmega16) with gcc 10.1, and Linux/x86_64 with clang 10.0 the produced assembly is identical.

author: chriva
author_rank: Regular Contributor
timestamp: May 25, 2020, 11:16:38 pm
content: It's nothing more than some junk I wrote up without debugging so I'm more than willing to believe there's a few nasties in thereI simply downloaded the datasheet for am29f010b (a flash chip) and wrote as if I were implementing something on an embedded target.Checked the macro and it does indeed work. (It'd probably be better to encapsulate it with curly braces tho) Another thing I did wrong is the the ";" after the macro. It's not necessary and you might trap yourself if you put them after if statements or loops etc. It's otherwise ignored.Reason for declaring it as volatile was in my intent to force two reads and not have the compiler perform some weird optimizations. The flash is kinda weird in that way that you must make two consecutive reads to check if particular pins of interest are toggling. Order doesn't matter, you just want to know if the two reads are different.No idea what you guys prefer when it comes to assembler but I find 68k easier to read than x86 so here's the assembler listing:(the macro can be seen just before "L4")Code:wToggle:move.l %d7,-(%sp)move.l 8(%sp),%a0move.l 16(%sp),%d0move.l 12(%sp),%a4jra .L2.L6:move.b (%a4),%d0cmp.b (%a0),%d0jeq .L3move.b #85,10922.wmove.b #-96,21845.wmove.b (%a0),(%a4).L4:move.b (%a4),%d1move.b (%a4),%d0eor.b %d1,%d0btst #6,%d0jeq .L3btst #5,%d0jeq .L4move.b (%a4),%d1move.b (%a4),%d0eor.b %d1,%d0btst #6,%d0jne .L7.L3:addq.l #1,%a4addq.l #1,%a0move.l %d7,%d0.L2:move.l %d0,%d7subq.l #1,%d7tst.l %d0jne .L6jra .L5.L7:moveq #1,%d0.L5:move.l (%sp)+,%d7rts

author: SilverSolder
author_rank: Super Contributor
timestamp: May 25, 2020, 11:43:03 pm
content: "Goto" is a tool like any other... if used with skill, it can be an elegant solution...People that don't like "goto" tend also not to like early exits from loops or other code blocks. To me, it comes down to whether it looks concise and clean.

author: tkamiya
author_rank: Super Contributor
timestamp: May 26, 2020, 03:03:11 am
content: During the day, I am a programmer/software engineer in a major database company.During 1980s, structured programming movement started and that philosophy made "goto" a taboo. We were to use for loop, while loop, switch statement, case statement, etc, etc, etc exclusively, no matter what.While any program can be written without a single goto, that doesn't mean that's the most efficient way to do it. Like, say, you have a error subroutine, process_error. Right in the middle of a big loop, error happens and you must go to the routine. You can just pop in if error goto process_error. Exceptions handlings are one place goto is often used and typically accepted. In this type of example, at the end, there is return. No further logic handling happens.But, over-use of goto makes program difficult to read. Say in the exception handling above, there is another goto in that routine, then another. It's called spaghetti code. Or you write an entire program with goto after goto. You can make your program run faster, but awfully difficult to read and maintain.Overall though, restrained use of goto are perfectly fine. Typically, well thought out structured programmings are easier to debug and maintain.

author: Alex Eisenhut
author_rank: Super Contributor
timestamp: May 26, 2020, 03:39:50 am
content: I prefer gosub. Or on ... goto on my c64.

author: greenpossum
author_rank: Frequent Contributor
timestamp: May 26, 2020, 03:47:53 am
content: Don't forget there is also a GoToPro, for adventurous programmers.

author: emece67
author_rank: Frequent Contributor
timestamp: May 26, 2020, 08:59:06 am
content: .

author: Syntax Error
author_rank: Frequent Contributor
timestamp: May 26, 2020, 09:10:27 am
content: To escape from inside a nested structure, what about using EXIT, BREAK, ASSERT or THROW?GOTO belongs to languages that have no implicit structure.

author: 0db
author_rank: Frequent Contributor
timestamp: May 26, 2020, 09:29:13 am
content: Quote from: Jr460 on May 25, 2020, 04:58:41 pmSure, this perfectly summaries what I think: Goto's are only worthwith forshort handling routines under interruptsand for exceptions cleanups

author: Nusa
author_rank: Super Contributor
timestamp: May 26, 2020, 09:36:46 am
content: The question didn't specify a language or structure, other than "modern", which wasn't defined.In the military, there's all sorts of advanced weaponry that can be issued, but soldiers are still equipped with a simple knife. Because it still works.In the end, results are what matter.

author: hendorog
author_rank: Super Contributor
timestamp: May 26, 2020, 09:51:40 am
content: Simple.Consider other solutions first.If goto remains the best solution, then use it.Experience will dictate what you consider best to be.Try and keep an open mind, that helps us gain experience instead of just gaining age.

author: Picuino
author_rank: Super Contributor
timestamp: May 26, 2020, 11:54:42 am
content: Quote from: emece67 on May 26, 2020, 08:59:06 amWeb:https://modernc.gforge.inria.fr/Book:https://gforge.inria.fr/frs/download.php/latestfile/5298/ModernC.pdfExample of goto in numberline.cCode: (c)int fprintnumbers_opt(FILE*restrict stream,char const form[restrict static 1],char const sep[restrict static 1],size_t len, size_t nums[restrict len]) {if (!stream) return -EFAULT;if (len && !nums) return -EFAULT;if (len > INT_MAX) return -EOVERFLOW;int err = errno;size_t const seplen = strlen(sep);size_t tot = 0;size_t mtot = len*(seplen+10);char* buf = malloc(mtot);if (!buf) return error_cleanup(ENOMEM, err);for (size_t i = 0; i < len; ++i) {tot += sprintf(&buf, form, nums);++i;if (i >= len) break;if (tot > mtot-20) {mtot *= 2;char* nbuf = realloc(buf, mtot);if (buf) {buf = nbuf;} else {tot = error_cleanup(ENOMEM, err);goto CLEANUP;}}memcpy(&buf, sep, seplen);tot += seplen;if (tot > INT_MAX) {tot = error_cleanup(EOVERFLOW, err);goto CLEANUP;}}buf = 0;/* print whole line in one go */if (fputs(buf, stream) == EOF) tot = EOF;CLEANUP:free(buf);return tot;}Quote

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 26, 2020, 03:29:36 pm
content: The cases where I tend to usegotoare nested cleanup and some state machines. Both have been described by others in this thread already.(The state machines I typically do, tend to have an action function per state; or be a simpleswitch() { caseN: ... default: }. It's the generated ones – lex/bison – and those with related state paths (large state diagrams) that usegoto.)One specific case where I do not use goto for cleanup is when the cleanup is selective. Then, I often use a bit mask with a bit per used resource to clean up.A good example of that is when duplicating file descriptors (pipes or sockets for slave processes) on POSIXy systems, and you want to ensure the descriptor is not one of the standard ones (STDIN_FILENO==0,STDOUT_FILENO==1,STDERR_FILENO==2) – sometimes the piping gets pretty hairy, if you're like me, and have an extra close-on-exec socket to detect successful exec and return exec failure errno, and you may have to close some of the standard descriptors before opening/duplicating new ones.(This is relevant for example when writing a security-sensitive fork-exec code, and youneedto detect any hiccups or errors, and may have complicated piping/sockets between the master and slave processes.)The following one is just an example; the point is that theclose_fdscontains the "need to do these cleanups" bitmask.Code:int notstdfd(int fd){unsigned int close_fds;int saved_errno;/* If invalid descriptor, return it; errno should be already set. */if (fd == -1) {return -1;}/* No descriptors to clean up yet. */close_fds = 0;/* Save errno, so that in case of success, we can keep it "unchanged". */saved_errno = errno;/* POSIX says these are 0, 1, and 2. On all systems, they are small (<16) nonnegative integers. */while (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO) {/* fd is one of the descriptors that need to be closed. */close_fds |= 1 << fd;/* We no longer care about fd at all -- we'll close it later --, so just reuse it for the new descriptor. */fd = dup(fd);if (fd == -1) {/* Failed. Ran out of descriptors, the one we got was no longer open, et cetera. */saved_errno = errno;break;}}/* Close the standard descriptors we temporarily used.If the constants are too large, these will cause a compile-time warning or error. */if (close_fds & (1 << STDIN_FILENO)) {close(STDIN_FILENO);}if (close_fds & (1 << STDOUT_FILENO)) {close(STDOUT_FILENO);}if (close_fds & (1 << STDERR_FILENO)) {close(STDERR_FILENO);}/* Restore errno, and return the descriptor or -1. */errno = saved_errno;return fd;}Because of how this works, you can use it as a wrapper aroundsocket(),open()and so on: if successful, it will keep errno unchanged. If the original descriptor is one of the standard descriptors, and there are no free descriptors left, it will close the original one and return -1 with errno == EMFILE or errno == EBADF.If we just close the previous (standard descriptor) after duplicating it to a new one, we can end up in a eneverending loop, because dup() returns the lowest unused descriptor. (It may not be obvious which one that is either, if other threads are opening and closing descriptors at the same time. However, since we do "own" each descriptor we get without race windows, this is thread-safe.)For pointers to dynamically allocated memory, I just initialize them to NULL, and then do an unconditionalfree()on them,Quote from: chriva on May 25, 2020, 09:32:14 pmThere is a way to fix the warning: usingconst uintptr_t address. This does change the parameter size (to native address size), but makes it portable.To just silence the warning (and hide a bug if ever run on LP64 architectures – I've been bitten by exactly this!), usevolatile uint8_t *dst = (uint8_t *)(uintptr_t)address;

author: chriva
author_rank: Regular Contributor
timestamp: May 26, 2020, 03:45:14 pm
content: Thanks, dude!Generally, I tend to pass -Wpedantic and just hide that particular warning with pragmas since I've never figured out how to cast it to the compilers liking.Then there's strict aliasing.. Always something to whine about.

author: free_electron
author_rank: Super Contributor
timestamp: May 26, 2020, 03:54:56 pm
content: Quote from: greenpossum on May 26, 2020, 03:47:53 amgoto int(rnd*memsize)

author: free_electron
author_rank: Super Contributor
timestamp: May 26, 2020, 04:01:01 pm
content: i suggest we create two aliasesskiptoreturntoCode:sub somethingblablareadkey:if key is <esc> then skipto theresome more blablareturnto readkeythere:do some other nonsense and store the key in a variable.( global of course. we don't do any of that silly push 'n'pop with stacks. that is just a waste of machine cycles )end sub

author: Nominal Animal
author_rank: Super Contributor
timestamp: May 26, 2020, 04:44:39 pm
content: The GNU C/C++ variants can use "computed"gotos. The idea is thatgoto *ptr;jumps to the label whose address was obtained inconst void *constptr= &&label;. If you use an array of labels, sayconst void *const next[] = { &&label0, &&label1, .., &&labelN };you need to still include the asterisk:goto *next;.This can make writing a finite state machine much easier because you can use pointers to the current and next state labels, and split out code common to many cases, thus reducing the code size.Actually, now that I checked, GCC, LLVM/clang 2.7 and later, and Intel Compiler Collection at least on Linux all support this. Hmm, this could be very useful on 8-bit microcontrollers (AVRs in my case) with limited Flash, for implementing larger state machines like parsers. Gcode and HPGL in my case.

author: profdc9
author_rank: Frequent Contributor
timestamp: May 26, 2020, 05:06:30 pm
content: In general, gotos tend to lead to spaghetti programming. Using program blocks and braces tends to enforce scope which encapsulates variables and code so that the side-effects of code running in strange ways tends to be minimized.That said, there are lots of other program structures that can complicate program flow and introduce scope and side-effect issues. In C, there is break, continue, and return. Especially Duff's device (https://en.wikipedia.org/wiki/Duff%27s_device) is quite useful but exploits this side-effect behavior, allowing jumping into loops using a switch statement. C++ introduces whole other levels of side-effects, with exceptions especially, but also virtual functions. I am not saying these are necessarily bad but can be a real nightmare sometimes to debug. So while C and C++ generally do not use gotos (even though they exist in C and C++), many of these program constructs violate the spirit of the no gotos idea by allowing highly varying program flow.One really cool application of gotos/Duff's device is protothreadshttp://dunkels.com/adam/pt/They can be quite useful to implement state machines in embedded programming.

author: olkipukki
author_rank: Frequent Contributor
timestamp: May 26, 2020, 10:46:54 pm
content: Actually, I don't mind if an author use GOTO where is make sense in some situation. Just say 'No, you cannot' , like you cannot cross a road when the red light showsIn most cases, people who used GOTO don't have any clues how to get out from a dead end, especially languages like C# for a basic CRUD app

author: Picuino
author_rank: Super Contributor
timestamp: May 27, 2020, 07:44:24 am
content: Quote from: profdc9 on May 26, 2020, 05:06:30 pmI think this is the technique used to create RTOS in small PICs.https://en.wikipedia.org/wiki/ProtothreadEdit:Protothreads versus State Machineshttps://embeddedgurus.com/state-space/2011/06/protothreads-versus-state-machines/

author: free_electron
author_rank: Super Contributor
timestamp: May 27, 2020, 02:34:56 pm
content: Quote from: profdc9 on May 26, 2020, 05:06:30 pmjust like driving cars tends to lead to traffic jams.It is an instruction just like anything else.

author: wizard69
author_rank: Super Contributor
timestamp: June 20, 2020, 04:45:39 am
content: Quote from: artag on May 25, 2020, 03:38:48 pmgoto can actually map onto what assembly language programmers do in low level driver code, sometimes it is the only way.QuoteThis is where my love/hate for Python developed, using indentation to define blocks of code can really led to some frustrating bugs. This is one of the reasons I'm hoping that Apples Swift ends up more widely used. It shares with Python ease of use, ease of code reading but not the major limitations.QuoteAs for the original question; is it a good idea to use GOTO, the answer is no if you expect to use it unwisely. This probably applies to a lot of coding constructs but good or bad depends upon how you use it.

author: Siwastaja
author_rank: Super Contributor
timestamp: June 21, 2020, 07:11:09 am
content: Using goto is highly recommended.Goto, along with other similar means such as using C instead of a more "modern" language, can save your project, the technical possibilities are truly tremendous.Goto's technical excellence is based on the role ofrepellentagainst just graduated brainwashed CS students who have absolutely no idea what they are talking about, and worse, high self-confidence that prevents them from hearing out what others have to say, let alone doanykind of scientifically sound analysis over cargo cult science they learned at school. They have never used goto, or never seen it used, because they don't read code from real-world projects. But they attended a circle jerk fest where the lecturer talked them about the dangers of goto, then went on to read a post on Stack Overflow which, using such nice language that it looked like science, clearly enumerated all the dangers of such unholy construct. This enables them to have very strong opinions about goto, and further, make conclusions about the quality of the project.Having no such people in your project does not fully ensure your success, but is a great layer of security against destroying the project with hundreds of thousands of lines of trend-pattern-of-the-year framework crap.For best effect, the gotos need to be put in visible places in your code, because the people you want to scare away typically do not read the code. For example, if the very first thing you need to do is to initialize an array, replace the for loop with a goto loop.

author: Syntax Error
author_rank: Frequent Contributor
timestamp: June 21, 2020, 09:07:45 am
content: QuoteWell that's my post of the weekI remember when MVC was the new big thing, and our code had to be MVC compliant. Even just a web page that said "hello world" needed a model-view-controller entity diagram thing. And then some MVP at Microsoft invented MVVC, which is a whole new paradigm of Reddit bitchin'.Worse than CS graduates who think industry is all quatum computers running Python scripts, are the Javascript bootcamp grads who try to nail the latest prototype framework to problems that only need a <p> tag or onMouseOver statement.Trouble is, the use of GOTO also requires the use of thinking

author: hamster_nz
author_rank: Super Contributor
timestamp: June 21, 2020, 11:49:20 am
content: That "Go To Statement Considered Harmful" article is now 50 years old.The removing of GOTOs changed program execution from being an arbitrary flow diagram of basic blocks, to being a nested hierarchy that matches source code indentation (not all languages had indentation back then...)The resulting flow diagram might not be the simplest or the most efficient, but they are often the most comprehensible for programmers, because they have of a very clear understanding of the flow of execution and they don't have to inspect every line of code for "goto" statements that change program flow, or wonder what paths can lead to any given block of statements.As mentioned, implementing Finite State Machines in programming languages is awkward, (usually done by using a loop and a 'switch' or 'case' statement). This is because the structure of the FSM's graph doesn't map across cleanly to structured code. When I see a complex FSM in code I often end up sketching out the FSM states and transitions, because the real, deeper structure has been hidden. Maybe in some cases using GOTOs to change states would be just as good?A GOTO statement isn't essential, but then neither are "for" loops, or exception handling. But occasionally use of GOTOs can improve the quality of code.

author: SilverSolder
author_rank: Super Contributor
timestamp: June 21, 2020, 11:54:09 am
content: Quote from: Siwastaja on June 21, 2020, 07:11:09 amYou could name the file - e.g. "goto.h" and include it. - job done, the miscreants don't even have to open the file!

author: Fredderic
author_rank: Regular Contributor
timestamp: June 21, 2020, 05:22:35 pm
content: Quote from: hamster_nz on June 21, 2020, 11:49:20 amWe should start a new thread on the great mistake that was exceptions…There are two kinds:Errors, which need a backtrace and all the rest.Signals, which don't.Lets just use errors forALL THE THINGS…! allocating memory is cheap and easy, right?

author: bd139
author_rank: Super Contributor
timestamp: June 21, 2020, 05:53:52 pm
content: Exceptions should not be used for flow control or signalling. Everything else about them is fine. In fact because they are contextual and have state then they are amazingly powerful for defect analysis.

author: Syntax Error
author_rank: Frequent Contributor
timestamp: June 21, 2020, 08:23:33 pm
content: Quote from: bd139 on June 21, 2020, 05:53:52 pmAgreedI usethrowin classes, but that's only to trap malformed instantiation. Then use the try-catch block to write to the log or debug.btw I would sack any programmer who thinks try-catch blocks are "not needed with their code". It's just the Zen of safe programming: it's not about when thing go right, it's about when they often go wrong.GOTO UndefinedException

author: SilverSolder
author_rank: Super Contributor
timestamp: June 21, 2020, 09:21:04 pm
content: Quote from: Syntax Error on June 21, 2020, 08:23:33 pmEvery application is technically inside a giant TRY-EXCEPT when run by the OS!

author: Siwastaja
author_rank: Super Contributor
timestamp: June 21, 2020, 09:25:59 pm
content: Quote from: Syntax Error on June 21, 2020, 08:23:33 pmIn C++, try-catch construct is aninterfaceto the language-built-inimplementationof a thing calledC++ exceptions, which is onespecific wayto doprogram jumps, most often used in cases like error reporting or recovery (among other uses, some good, some bad).Note that exceptions have absolutely nothing to do with checking errors. Those actual error checks need to be implemented; exceptions are an interface tojump elsewhere. Throw is just a goto-on-steroids without predefined destination, and catch is just a label-on-steroids without direct knowledge where it comes from. Whether those "steroids" are of good or bad kind, is up to the programmers, and often it's a different programmer who writes "throw", than who writes "catch".I don't have enough experience with C++ exceptions to have a strong opinion about them, but they have been widely criticized. If your imaginary programmer you refer to thinks try-catch blocks are "not needed", it does notnecessarilymean they are not taking error checking seriously. It's completely possible they deal with errors some other way, possibly for very good reasons. They are using their own subset of C++, like everybody else.One funny thing about exceptions and try-catch blocks is the fact that while "goto" has been heavily criticized for "creating spaghetti codewhich can suddenly jump anywhere without you knowing", which obviously isn't true, this ridiculous claim would bemuch closer to the truthwhen it comes to exceptions; yet those same people think exceptions are the best thing since sliced bread.All I'm saying is, don't judge anyone bynotusing any specific C++ feature. It's full of features, and everyone uses a subset. You can create good and robust code with or without exceptions.A lazy programmer surrounding the complete program in a massive try catch block is not error checking&recovery. It isn't doing anything more than not checking for return values in classic C way. So in both cases, the application programmer needs to figure out high enough granularity to detect problems, then figure out the logic how todealwith the errors. No part of this is built-in in exceptions (and obviously, cannot be). The most often forgotten part is checking for errors in your own code (not only looking at the return status / catching exceptions fromlibrary functions); this is clearly shown by fact everyone talks about "try-catch"; too few think aboutthrowinganything. The most difficult part is likely how torecoverfrom errors, if that is necessary instead of giving up and quitting; it often is.

author: hamster_nz
author_rank: Super Contributor
timestamp: June 21, 2020, 11:22:04 pm
content: I wonder how many people who use exceptions could clearly explain how they are realized at the machine level. From the programmer's view it is an instant transition to the exception handler, but under the covers it is far more complex.How does the system work out where the exception is going to be caught?How the stack is unwound?How are things tied up along the way to the exception handler?(I'm not asking for somebody to explain it to me, just pondering on how many people know how it is actually implemented).

author: Syntax Error
author_rank: Frequent Contributor
timestamp: June 22, 2020, 12:06:13 am
content: A developer should not only fear their own exceptions, but everyone elses. Where data, types, context, etc, is flowing across any boundary, such as threads, processes and even networks, the assumption must be, prepare to crash! Try-catch is just a parachute to give a gracefull landing plan inside a nested structure.An example; a process is expecting an array of bytes, but instead injests the error message string from an upstream process. Some null type exception is thrown, either manually or automatically. The only problem is the object that caused the exception has gone out of scope!

author: Nominal Animal
author_rank: Super Contributor
timestamp: June 22, 2020, 02:13:50 am
content: Quote from: hamster_nz on June 21, 2020, 11:22:04 pmExcatly.It is also at the core of why I am unsure if we can really call C++ used in embedded environments fully C++, because of the lack of core features like exceptions. (By "unsure", I mean I literally do not know the answer; am undecided.) As I've mentioned before, each language has "beauty" in their underlying paradigm, the underlying idea on how to solve a problem. You could hardly have BASIC without GOTO, for example. Using a strict subset really changes that. (I do call it POSIX C when I work with a C implementation that supports POSIX, and GNU C when I rely on GNU extensions to C, and use "plain" C when dealing with code that relies on standard C, so this definitely also applies to C too in my opinion.)For C, I rarely needgoto, but when I do need it, it can really make the logic much more understandable, and therefore the codebase so much more maintainable. Although at the face of it, goto does not seem like a core feature in C, but the way it enables labels, and the way GNU C supports labels as values (via void pointers), it can mean the difference between being human-maintainable or not for certain type of code (very complex FSMs). I personally dislike code generators and their domain-specific languages, which might color my opinion, though.

author: nfmax
author_rank: Super Contributor
timestamp: June 22, 2020, 08:21:58 am
content: Quote from: Syntax Error on June 22, 2020, 12:06:13 amOne of the things that Java gets right (IMHO) is the requirement to declare all the exceptions a method may throw. It forces the programmer to think about them - including exceptions thrown by other methods that may be called

author: golden_labels
author_rank: Super Contributor
timestamp: June 22, 2020, 11:48:22 am
content: Quote from: nfmax on June 22, 2020, 08:21:58 amWhile I have bailed out of theg**odiscussion, this thing should be rectified. Those declarations apply only to checked exceptions. One still doesn’t have to declare aThrowable(as long as it’s notException) and anything that isRuntimeException:Code:┌───────────┐│ Throwable │ <╴╴╴╴╴╴╴╴╴╴ ✗ Unchecked└──^───^────┘╵ ╵╵ ╵╵ ┌┴──────┐╵ │ Error │ <╴╴╴╴╴╴╴╴╴╴ ✗ Unchecked╵ └───────┘┌─┴─────────┐│ Exception │ <╴╴╴╴╴╴╴╴╴╴ ✓ Checked└──────^────┘╵╵┌───────┴──────────┐│ RuntimeException │ <╴╴╴╴╴╴╴╴╴╴ ✗ Unchecked└──────────────────┘Thre is nothingwrongwith it and makes sense in how they’re meant to be used, but it’s not like in Java all exceptions must be declared.While this is not a problem with exceptions as a concept, thre are some issues with how that stuff works. Two commons pains:A programmer is not required to catch a checked exception if the enclosing method has it declared. This may be something intentional, but more often than not programmers are just lazy or not thinking about what they’re doing. The effect? The method are signaling something that doesn’t conform to its contract. E.g. documentation tells that anIOExceptionindicates missing file. You catch that exception, act as if the file was missing but… it is not. Upon inspection you discover that theIOExceptioncomes from some inner call and it means the file has been opened, but an error occured during reading. This problem is not limited to exceptions and I have seen similar in functions returning special values in C, but with exceptions there is a way to sanely define language to prevent it from happening.Passing callables around if they throw checked exceptions. Unless the code using the callable is prepared to handle a specific exception, you must wrap the callable only to wrap or suppress the exception, and then possibly unwrap it on the other side. This is horrible.

author: tggzzz
author_rank: Super Contributor
timestamp: June 22, 2020, 11:53:55 am
content: Quote from: nfmax on June 22, 2020, 08:21:58 amI strongly agree with that.Unfortunately it isn't the case: there are unchecked exceptions, NullPointerException being one case.Regrettably those wet behind the ears can't cope with the extra typing (cntl-space anyone?), and the current fashion is to throw UncheckedExceptions. That's arguably OK if you are in a managed environment such as a web container, but is bloody awful elsewhere.

author: tggzzz
author_rank: Super Contributor
timestamp: June 22, 2020, 12:01:24 pm
content: Quote from: hamster_nz on June 21, 2020, 11:49:20 amWrong, fortunately. The Gand of Four codified a traditional technique in the seminal Design Patterns book.https://en.wikipedia.org/wiki/State_patternThat works very well in specification, design and maintenance - unlike the switch/if-then-else technique which usually grows incrementally to be an incomprehensible tangle. I've seen the latter end up nesting 10 deep(!), and it took down the companyThe other useful technique is a 2D array of function pointers, where the first index is the state and the second index is the event.

author: tggzzz
author_rank: Super Contributor
timestamp: June 22, 2020, 12:03:36 pm
content: Quote from: Syntax Error on June 21, 2020, 08:23:33 pmAmateurs think mainly about how thingswork. Professionals think mainly about how thingsfail.

author: tggzzz
author_rank: Super Contributor
timestamp: June 22, 2020, 12:06:08 pm
content: Quote from: hamster_nz on June 21, 2020, 11:22:04 pmI'd be satisfied if people had a clue about how a function+parameters is called, executes, and returns. Pseudocode is fine; no need to be familiar with any particular processor's ISA.

author: bd139
author_rank: Super Contributor
timestamp: June 22, 2020, 12:25:59 pm
content: Just a point on checked vs unchecked exceptions. I tend to not bother with checked exceptions if I'm honest. I think they're a waste of time. What is being thrown is less important than the fact that it is thrown. If something is an expected situation then it should not throw. If it does it should handle failure conditions within the scope of the method that expects the exception. If something is not handled in the method then the exception should ripple up the call stack to thefailure context boundary.The failure context boundary is clearly defined as a wrapper around a chunk of code which handles the failure policy. For example if it's a web thread then the obvious answer is to throw the response buffer away, generate a correlated error ID, write it to the logging system with the exception and stack, then inform the client side that the shit hit the fan. If it's a service call or network boundary, it may have a warn and retry policy. If it's a queue or a messaging contract then it will have its own policy, usually exponential drop off and retry. As always these situations are handled differently depending entirely on the context of the operation, not the eventual target of the caller which has no write to boss the failure context around. This allows generic failure handling code to exist.This means checked exception's just force the method encapsulation to be broken. Handling any logic with exceptions is horrible. So tersely, fuck 'em.A well designed system does not throw ANY visible exceptions at all outside the last chance interface layer other than complete inability to continue.A common trite example in C# of some wrappers (written off top of my head so probably wont compile):Code:void WrapWithGiveUp(Func target) {try {target();} catch (Exception ex /* root exception type */) {Log.Error("No retry policy. Operation cancelled", ex);}}// and in your codeWrapWithGiveUp(f => TargetMethod()); // do it once and just give up. It wasn't that important.WrapWithRetries(4, f => TargetMethod()); // retry 4 times immediatelyWrapWithBackOffPolicy(b => 2 ^ b, 4, f => TargetMethod()); // rettry 2, 4, 8, 16 seconds a maximum of 4 times then throw in the root context// etc etc

author: SilverSolder
author_rank: Super Contributor
timestamp: June 22, 2020, 02:09:23 pm
content: Quote from: bd139 on June 22, 2020, 12:25:59 pmFor many applications, the "failure context boundary" is the OS catching the app's unhandled exception as it sh!ts the bed uncontrollably!

author: bd139
author_rank: Super Contributor
timestamp: June 22, 2020, 02:22:11 pm
content: Yeah and people who do that need to be shot. Preferably with some blunt cutlery out of a not very powerful cannon.A screenshot of the first things every application should do (from actual production code serving about 20,000 people):Ignore the AppContext stuff. That's a .net framework frig so it uses better than TLS1.1 by default.

author: Syntax Error
author_rank: Frequent Contributor
timestamp: June 22, 2020, 08:29:57 pm
content: Often theunhandled exceptionbubbles up into the application scope late on a Friday afternoon.This is what I call STRESS TESTING!!!On the subject of code execution/invocation, where doasync callbacksandeventsfit with Planet Goto?+ So is aninterrupt handlerorinterrupt vector tablea kind of goto too?

author: SilverSolder
author_rank: Super Contributor
timestamp: June 22, 2020, 08:43:44 pm
content: Quote from: Syntax Error on June 22, 2020, 08:29:57 pmI think most of us would have a problem with a "Goto" that hopped from one thread to another, or hopped outside an event handler!An interrupt is definitely a kind of "managed goto", to my mind at least...

author: bd139
author_rank: Super Contributor
timestamp: June 22, 2020, 09:43:16 pm
content: Or a catch block

author: hamster_nz
author_rank: Super Contributor
timestamp: June 23, 2020, 12:55:37 am
content: We all know where this leads:https://medium.com/swlh/stop-using-if-else-statements-f4d2323e6e4Quote

author: SilverSolder
author_rank: Super Contributor
timestamp: June 23, 2020, 02:04:18 am
content: Quote from: hamster_nz on June 23, 2020, 12:55:37 amThat is going a little too far for my liking - the solution is even more complex than the problem!That whole If-Else mess used as an example in the article could be made much cleaner and maintainable...

author: tggzzz
author_rank: Super Contributor
timestamp: June 23, 2020, 06:22:11 am
content: Quote from: SilverSolder on June 23, 2020, 02:04:18 amLet's be clear; this is w.r.t. FSMs.For tiny FSMs with a couple of states and a couple of events, it is fine. But many FSMs aren't like that.Frequently FSMs start out small and, as corner conditions are discovered and requirements added, they end up large. At that point it is an unmaintainable mess. I've seen them end up as 10 deep if-then-else messes. Long before then, when a bug is found, it is impossible to determine how to change the code so as to fix the bugand not introduce another bug. That mess took down a company!With a little extra work up (i.e. using the standard GoF State Machine Design Pattern) front you have something that allows easy logging, tracing, "fixability", extendability - and visible correspondence between design specification and implementation.Those attributes are superb when integrating your component with other company's components - they enable you to definitively point the finger at them or at the line in your code that needs fixing. (The logging enables a very fast compact mechanism for retaining the "state trajectory" to find out why something failed in an installed system.)Those attributes are superb when performance testing your component with other company's components - point the finger at them.All in all a great way of deflecting flak and avoiding the use of lawyers

author: nctnico
author_rank: Super Contributor
timestamp: June 23, 2020, 10:49:54 am
content: I agree. If you need to nest if-thens more than 4 deep then a switch-case is better.

author: tggzzz
author_rank: Super Contributor
timestamp: June 23, 2020, 11:54:17 am
content: Quote from: nctnico on June 23, 2020, 10:49:54 amWell, I'm not sure that switches are superior in that context. A switch statement might directly replaceif ( state == 1 ) {} else if (state == 2 ) {} else if (state == 3 ) {} //etcbut I don't regard that as being nested in the destructive ways that I have seen.I was thinking more ofif ( state == ) {if ( inputA == ) {if (inputB == && inputC == ) {if (inputD == ) {if (inputE == ) {}}if (inputE == ) {}}} else if (state == ) {}plus other peversions carried out to the 10th level!Yes, I refused to look at it in detail, let alone consider modifying it. There was zero chance of spotting the line that needed to be modified to implement one use-case,whileensuring that it didn't affect other use-cases.No, it wasn't remotely sensible, but that's the kind ofthingthat accretes over the years. Cancerous.Any design pattern can be implemented badly, but at the GoF Class-per-State Pattern can neatly and directly implemented FSMs with nested states.(Shortform features including: one abstract superstate for operation, another abstract superstate for faults, and concrete substates within a superstate for the normal operation FSM, catch all error events occurring in any substate causing a transition to the fault state, etc)

author: bd139
author_rank: Super Contributor
timestamp: June 23, 2020, 11:57:57 am
content: Or screw it all and do what I did and write a DSL and compiler for defining the state machine that generates an entire-machine interface contract and state chart and generating an optimised pattern matching based switch in a loop with transition validation which can be suspended and serialised between states safely.

author: tggzzz
author_rank: Super Contributor
timestamp: June 23, 2020, 01:13:32 pm
content: Quote from: bd139 on June 23, 2020, 11:57:57 amDid anybody else ever have to look at the application written in your DSL?Every home-grown DSL I've seen ended up as an incomprehensible mess. Exactly like the DSL the FSM I referred to above, and, come to think of it, much like C++ and PerlIn my experience in almost all cases a DSLanguage was worse that a corresponding DSLibrary in a standard language. Start by considering tooling, staff training, staff retention... including yourself 12 months later I perpetrated one once, long ago; the saving grace was that it was a 2 week project and was thrown away after that. I learned my lesson, and realised Forth would have been a better starting point.

author: Syntax Error
author_rank: Frequent Contributor
timestamp: June 23, 2020, 02:33:10 pm
content: Quote from: hamster_nz on June 23, 2020, 12:55:37 amSo the guy's argument is that if-else makes for messy and unreadable code, okay, so instead he introduces a 'design pattern' which is a mash of internal, abstract, static and overridden classes? Hmmmm, he's obviously twigged he's the only contractor in the corporation who can figure out this over-complicated codebase.I wonder how these gurus would deal with branching in assembler? which is if-true-jump-else-dont

author: tggzzz
author_rank: Super Contributor
timestamp: June 23, 2020, 02:54:08 pm
content: Quote from: Syntax Error on June 23, 2020, 02:33:10 pmIt is a standard design pattern that is well known and understood by those skilled in the art.I first saw it in 1987 (gulp, 33 years ago), and it became widely known after the GoF book appeared in 1994 - over quarter of a century ago. As is traditional with design patterns, the GoF were careful to state its advantages, where it was applicable, and where there are better alternatives.I have used it to good effect, especially when compared with the absolutely horrific if-then-else mess in the previous product.Now if an amateur uses it where not beneficial, or doesn't use it where beneficial, that can hardly be said to be a fault of the design pattern.

author: SilverSolder
author_rank: Super Contributor
timestamp: June 23, 2020, 03:09:17 pm
content: The example "mess" would respond somewhat to a Case statement - e.g.Code:case orderState ofisPending: ...isExpired: ...isCancelled: ...end;

author: tggzzz
author_rank: Super Contributor
timestamp: June 23, 2020, 04:40:40 pm
content: Quote from: SilverSolder on June 23, 2020, 03:09:17 pmAs I stated earlier in this thread, that technique is perfectly suitable for small FSMs, especially those that won't have to be modified/extended over the years. I've used it myself.The example is,of course, adeliberately simpleexample chosen so that thegeneral principlescan berapidly and easilyunderstood. For teaching and exposition purposes, it would be counterproductive to have long complex example! (The solution is important, not the problem)For similar reasons, when I've been interviewing people I've sometimes asked them how they might design a traffic lights controller for a child's toy set. I chose that example because it is so simple thatI don't have to explain what that is. That leaves precious time for finding out how they approach problems.

author: bd139
author_rank: Super Contributor
timestamp: June 23, 2020, 06:56:36 pm
content: Quote from: tggzzz on June 23, 2020, 01:13:32 pmI did consider all of that when I wrote it initially, including the worry of “what hell hath I deposited on the world”. Hell was uneventful, fast and reliable in the end after a few bugs in ReaderWriterLockSlim (Microsoft’s frameworks should never be trusted) were ironed out.I did make myself a little sick by writing a recursive descent parser in itself that could emit graphviz dot files of the state chart. It worked but I regret it. Mostly because that was the bit I crawled back to after 12 months and nearly sicked down myself.But yes Forth is a much much better solution. When you grok it, it’s magical. When you don’t though, it’s hell. I went through the latter for quite a while.

author: tggzzz
author_rank: Super Contributor
timestamp: June 23, 2020, 07:11:21 pm
content: Quote from: bd139 on June 23, 2020, 06:56:36 pmForth would have been ideal for my application: testing on an 8-bit embedded processor. I managed without, but the usual "how could I have done that better with 20:20 hindsight" brought me to that conclusion about my DSL and Forth. All of the other "little domain specific scripting languages" I've seen since have convinced me I was rightPrinciple: compilation is so damn fast and the tools so good that you migh as well use a proper language. (I suspect the "fast" bit precludes C++)At university I promised myself I would never write a compiler nor use a database. I've never regretted that decision. The nearest I came to it was replacing a postgres database with an in-memory distributed key-value store; the keys were a phone number, the values were money (etc).

author: SilverSolder
author_rank: Super Contributor
timestamp: June 23, 2020, 07:33:52 pm
content: Quote from: tggzzz on June 23, 2020, 07:11:21 pmFor my sins, I've had to learn to program Oracle, with its weird PL/SQL language, in latter years.You can do unbelievable things like this:beginS:= 'create table TEST as select * from BIG_DATA_TABLE';--Create a string containing an arbitrary commandexecute immediate S;--execute the string!endNot only that, executing "self modifying code" is the ONLY way some things can be done. Something about the design of this thing bothers me a lot more than Goto statements!

author: tggzzz
author_rank: Super Contributor
timestamp: June 23, 2020, 07:48:34 pm
content: Quote from: SilverSolder on June 23, 2020, 07:33:52 pm"Eval" in any form is liberating (in the short term at least)But you remind me of my other lapse. I did create a database for an early (award winning!) web business, back in '98/'99. The interesting bit was the extendable, scalable, distributed, fault-resilient manufacturing process that made the orders specified by rows in the database.

author: nctnico
author_rank: Super Contributor
timestamp: June 23, 2020, 07:55:03 pm
content: Quote from: tggzzz on June 23, 2020, 11:54:17 amI was kind of implying that your second example would have to be rewritten in the form of the first using a state-machine design pattern (for which switch/case usually is a good fit). If my code starts to look like your second example I rewrite the code as a state machine. Or if I expect code to turn out like your second example I just go for a state machine approach right away. It always ends with better code.

author: SilverSolder
author_rank: Super Contributor
timestamp: June 23, 2020, 07:57:39 pm
content: Quote from: tggzzz on June 23, 2020, 07:48:34 pm...ok, I see your Eval, and raise you nested "Execute Immediate" calls - to any depth! Can you do that with "Eval" ?(I misread "Eval" as "Evil" the first time. Are you sure it is spelled correctly?)QuoteSounds an interesting project!

author: tggzzz
author_rank: Super Contributor
timestamp: June 23, 2020, 08:45:02 pm
content: Quote from: SilverSolder on June 23, 2020, 07:57:39 pmEval is the LISP function that evaluates an arbitrary data structure as a LISP programes. So it can do anything a LISP programes can do!It is the heart of the REPL constructions you see in interactive environments such as interpreters and shells and... REPL is read evaluate print loop.https://en.m.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loopQuoteIt was. Many of mine have been; there has been little repetition

author: Syntax Error
author_rank: Frequent Contributor
timestamp: June 23, 2020, 08:57:03 pm
content: eval (repeat { Eat();Sleep();Rave() };);

author: bd139
author_rank: Super Contributor
timestamp: June 23, 2020, 09:02:29 pm
content: Eval is the root of all untrusted execution.

author: magic
author_rank: Super Contributor
timestamp: June 23, 2020, 09:09:26 pm
content: PHP include comes close second

author: tggzzz
author_rank: Super Contributor
timestamp: June 23, 2020, 09:30:36 pm
content: Quote from: bd139 on June 23, 2020, 09:02:29 pm... Such as a von Neumann machine which doesn't have a capability as architecture. I hesitate to mention the Burroughs/Unisys machine architecture, which keeps tight control of the compiler and debugger