You are not logged in.
hi scripters of bash
Does anybody know if there is any way to find the number of the depth of loops in a script. What I want to do is be able to break to the outside loop regardless of depth. Unfortunately break does not support -1. I can't find a bash variable for this (unlike function calls), and as far as I can see bash runtime keeps hard line addresses for loop control, which, I might add, is a goto by any other name. Of course, if we still had goto then this would not be a problem, but that's a whole new story. Thanks one and all.
Last edited by olly (2022-05-22 10:30:05)
Bullies are only weak people trying to compensate for their own inadequacy. If they can't compete intellectually, they bully.
Offline
There are lots of approaches - can you share the code so we can see what you're working with? Likely the simplest would be to use an arbitrarily high value to "break".
EDIT: I may have mis-read: do you want to break out of the outtermost loop, or break out of all except the outtermost? In the case of the latter, one option is to track depth yourself. Set a variable that gets incrememented before the start of each loop and decremented after the loop ends. Though I suspect there are cleaner solutions with some refactoring: put the content of the outer loop in a function and call that function in a loop, then any loop within the function (regardless of depth) can call "return" to go back to the outter loop.
EDIT: Actually if the goal is to break to the outtermost loop, then "continue" with an arbitrarily high parameter could work assuming the nested loops you break out of are at (or can be moved to) the end of the outter loop.
Last edited by Trilby (2022-05-20 20:50:35)
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
You could also add a flag ("breaktosurface=true") and condition the break on the intermediate loops on that.
Offline
Thanks for replies.
Counting loop depth and breaktosurface are good, but in practice there are so many the overhead is greater than hardcoding break -number. Putting it in one control loop function works, but within the loop are many others, so you would have to count the returns as well.
I'm dealing with lines in a file, with the outer loop fixed on a line number, and inner loops allowing the user to edit fields in the line, move to another line, or exit the program, amongst many other things. Structured programming has its benefits, but on large programs trying to find which if belongs to which else and fi, is more trouble than it's worth, and, if then two lines of code, else two hundred lines of code, disproportionately effects style. Using mostly functions can work, but does not allow no return calls. So I invented the bash goto.
line=1
goto=display-line
while : ; do
while : ; do
goto () { goto=$1 ; }
case "${goto}" in
select-option) select forward/backward/edit/quit
goto ${ selection}
break ;;
forward) line=line+1
goto display-line
break ;;
backward) line=line-1
goto display-line
break ;;
display-line) display line on screen
. goto select-option
break ;;
edit-line) edit line with lots of loops
goto select-option
break ;;
exit) break 2 ;;
done
done
And it's clean, simple and very fast, except the single fact that in, for example, the edit code block with lots of loops, you can't just break to the outer loop simply. Also you can't include the break function within the goto function, making it not possible to just use a single goto command.
Bullies are only weak people trying to compensate for their own inadequacy. If they can't compete intellectually, they bully.
Offline
I'm dealing with lines in a file, with the outer loop fixed on a line number, and inner loops allowing the user to edit fields in the line, move to another line, or exit the program, amongst many other things.
For me it smells like a state machine. Operations are already split into blocks. Just let each block return which block should run next.
Offline
I asked for the code to see what your goal was, and you shared very broken pseudo-code that requires absolutely nothing of what you asked about? I suspected this was an X-Y problem, but now it's now sounding like a (problematic) solution in search of a problem. You seem to be trying to write bad code just to justify the use of a bad not-really-a-goto goto function.
If you want help writing good code, tell us the actual goals.
FWIW, that pseudo-code could be done without any gake "goto" gymnastics (not to mention the effectively no-op function which has the same name as a variable):
#!/bin/bash
line=1
select cmd in forward backward edit quit; do
case $cmd in
forward) line=$((line+1)) ;;
backward) line=$((line-1)) ;;
edit) #TODO: edit line with lots of loops
continue ;;
quit) break ;;
esac
# TODO: display line on screen
echo $line # placeholder
done
Last edited by Trilby (2022-05-21 14:37:26)
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
For me it smells like a state machine. Operations are already split into blocks. Just let each block return which block should run next.
In a single state, and I'm assuming you mean, in bash, run each block in a function, with a return value. In simple cases I would agree, and the example I gave is very simplified. In some cases it is preferable to call non return functions. Consider my example, but control goes to the edit line function, within which control is selected by means of a call to a text edit function, that can be either an edit of the line components itself, or a call to another function (up arrow) at any time in the line edit function. You already have function return nesting of three levels, each requiring a test for certain values. Why introduce unesessary overheads when at any point you can jump directly to the next function. I'm a believer that different problems call for different programming paradigms, and when you start designing in unessesary
complexity solving code, then the paradigm is wrong.
Last edited by olly (2022-05-21 15:09:17)
Bullies are only weak people trying to compensate for their own inadequacy. If they can't compete intellectually, they bully.
Offline
I'm a believer that different problems call for different programming paradigms
Which is why we need to know what actual problem you are working on, not a completely artificial example made up in order to require the "paradigm" you seem set on using.
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
In simple cases I would agree, and the example I gave is very simplified. In some cases it is
I asked for the code to see what your goal was
Unless there're legal reasons prohibiting it, I'd suggest that's what you should do.
You original inquiry was "What I want to do is be able to break to the outside loop regardless of depth" but your example is just an event loop emulation in spaghetti code that could easily be replaced by proper function calls and that leaves everyone puzzled about the task, the goal and the sensibility of your approach.
Offline
I asked for the code to see what your goal was
No, there is no legal reason or reticence on my behalf. It's simply that the code is over a thousand lines long, so I demonstrate with pseudo (spaghetti) code. It's the structural concept (paradigm) I'm showing, which I believe is much cleaner, simpler and faster than other structures. It is not a request for programming lessons, I'm simply trying to find if there is a loop counter similar to function history array in bash. I'm not sure why everyone is aggressive, it's just a request about a detail of bash.
Bullies are only weak people trying to compensate for their own inadequacy. If they can't compete intellectually, they bully.
Offline
It is not a request for programming lessons, I'm simply trying to find if there is a loop counter similar to function history array in bash.
No, there isn't. Please mark the thread as SOLVED.
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
Nobody's aggressive, just confused.
You could move the code to github or a pastebin service.
1000 LOCs isn't much to just understand the issue you're facing (you're not asking to proof-read it or find a typo)
pseudo (spaghetti) code […] I believe is much cleaner, simpler and faster than other structures
I'd meditate about that…
Offline
pseudo (spaghetti) code […] I believe is much cleaner, simpler and faster than other structures
I'd meditate about that…
Not that pseudo code is. My proposition is that structured programming and/or functional programming might not be be as appropriate as other structures in some cases, including the use of goto to mitigate complexity.
Last edited by olly (2022-05-21 16:01:47)
Bullies are only weak people trying to compensate for their own inadequacy. If they can't compete intellectually, they bully.
Offline
My proposition is that structured programming and/or functional programming might not be be as appropriate as other structures in some cases
1) Of course that's true, now stop trolling trying to get someone to disagree with you an a point that as likely true as it is vacuously meaningless.
2) But who cares? You explicitly said this thread is not to discuss these points but only to get a concrete answer to a simple yes or no question. You have your answer. Mark the thread as solved.
Last edited by Trilby (2022-05-21 16:01:27)
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
olly wrote:My proposition is that structured programming and/or functional programming might not be be as appropriate as other structures in some cases
1) Of course that's true, now stop trolling trying to get someone to disagree with you an a point that as likely true as it is vacuously meaningless.
2) But who cares? You explicitly said this thread is not to discuss these points but only to get a concrete answer to a simple yes or no question. You have your answer. Mark the thread as solved.
I'm not sure that everyone on a forum specifically for arch users and computer scientists would agree that a debate about the fundamentals of programming is "vacuous". It might also be the case that although you don't know of such a bashism, others might.
Bullies are only weak people trying to compensate for their own inadequacy. If they can't compete intellectually, they bully.
Offline
Not a debate, but your statement.
"Sometimes something is better than another thing" is not debatable but self evident by its vagueness.
If your "structure" is indeed 1000+ spaghetti LOCs it's not "cleaner, simpler" and "faster" is something one doesn't have to "believe" but can just profile - and otherwise the example isn't representative of the problem.
Also, for your "bashism":
loop counter similar to function history array
is nonsense.
A counter (of any kind) is not an array.
I'm not sure what a "loop counter" is supposed to be, but google thinks I'm referring to the iterator which would be irrelevant to the previous discussion.
And I don't see at all how a function history would help with any of the suggested situations.
So how you want to have a "loop counter" that's similar to a "history array" is beyond me and reason - it doesn't exist because it cannot exist.
If you want to keep an array of anything, that's of course possible and if you want to somehow belong to your loops you'd just feed it at the beginning or end of each of your loops (depending on what you actually want to do - what we don't know)
I start to agree w/ Trilby that this thread is mostly an exercise in trolling…
Offline
I'm not sure that everyone on a forum specifically for arch users and computer scientists would agree that a debate about the fundamentals of programming is "vacuous".
And I never said it was. But 1) this is not what you introduced, and 2) you specifically said you didn't want this sort of discussion! You just want an answer to your yes or no question.
It might also be the case that although you don't know of such a bashism, others might.
So you asked a yes or no question, but you determined in advice which of those two answers you'd accept?
There is no hidden feature for this. And while I will readily admit there is always more I can learn, I know shell scripting pretty well (and you clearly don't), so I am quite confident in my answer that there is no current bash builtin / variable to determine the loop depth. If you don't like this answer, too bad, it's still true. If you want this to change, take it up with the gnu/bash dev team as a feature request ... be sure to show them your pseudo-ghetti code, they might enjoy the laugh.
Last edited by Trilby (2022-05-21 16:46:25)
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
My proposition is that structured programming and/or functional programming might not be be as appropriate as other structures in some cases
Not a debate, but your statement.
"Sometimes something is better than another thing" is not debatable but self evident by its vagueness.
Not that vague.
loop counter similar to function history array
So how you want to have a "loop counter" that's similar to a "history array" is beyond me
Is there not an environmental variable within a shell script in the form of a array called something like $FUNCTION that holds a history of function calls, which, by the number of elements, gives the depth of functions. If so, could not the same be done for nested loops,?
Last edited by olly (2022-05-22 14:20:59)
Bullies are only weak people trying to compensate for their own inadequacy. If they can't compete intellectually, they bully.
Offline
For me it smells like a state machine. Operations are already split into blocks. Just let each block return which block should run next.
Hi Dimich,
Thank you for a positive contribution. You might be a student, or not, but if you are interested in state machine processing please explore (if you have not done so) the State Space Search of single instance in infinite states, and have a go at The Two Jug Problem. I wish you all the best. Our thoughts and prayers are with you.
Bullies are only weak people trying to compensate for their own inadequacy. If they can't compete intellectually, they bully.
Offline
Is there not an environmental variable within a script in the form of a array called something like $FUNCTION that holds a history of function calls, which, by the number of elements, gives the depth of functions. If so, could not the same be done for nested loops?
#!/bin/bash
foo() {
printf "SNA"
}
bar() {
printf "FU\n"
}
foo; bar
[ -z ${FUNCTION} ] && echo "Doesn't seem so..."
If you mean the "history" function, that's a shell specific implementation (most likely as stack in C) and while you could just wrap your loops into functions to get there then I still don't see how logging functions/loops would relate to anything in this thread…
Offline
Is there not an environmental variable within a script in the form of a array called something like $FUNCTION that holds a history of function calls, which, by the number of elements, gives the depth of functions. If so, could not the same be done for nested loops?
#!/bin/bash foo() { printf "SNA" } bar() { printf "FU\n" } foo; bar [ -z ${FUNCTION} ] && echo "Doesn't seem so..."
If you mean the "history" function, that's a shell specific implementation (most likely as stack in C) and while you could just wrap your loops into functions to get there then I still don't see how logging functions/loops would relate to anything in this thread…
"${FUNCNAME[@]}"
return $(("${#FUNCNAME[@]}"-1))
break $(("${#LOOPNAME[@]}"-1))
Last edited by olly (2022-05-22 19:36:21)
Bullies are only weak people trying to compensate for their own inadequacy. If they can't compete intellectually, they bully.
Offline
We can try this w/ a lot of variables…
#!/bin/bash
foo() {
printf "SNA"
}
bar() {
printf "FU\n"
}
foo; bar
echo ${FUNCNAME[@]}
[ -z ${FUNCNAME} ] && echo "Doesn't seem so..."
It does this here:
#!/bin/bash
foo() {
echo "${FUNCNAME[@]}"
printf "SNA"
}
bar() {
printf "FU\n"
echo "${FUNCNAME[@]}"
foo
}
foo; bar
echo "${FUNCNAME[@]}"
[ -z ${FUNCNAME} ] && echo "Doesn't seem so..."
*Inside* a function - which seems to contradict the premise of your task.
Also, how do you want to identify the loop?
And while I still don't understand how this would help you (and blatantly assume it won't), you can really just head and tail every loop by in-/decrementing a counter.
Or use functions…
Offline
Try
clear
function_one {
echo "I am in function ${FUNCNAME[0]} with a depth of ${#FUNCNAME[@]}"
}
function_two {
echo "I am in function ${FUNCNAME[0]} with a depth of ${#FUNCNAME[@]}"
function_one
}
function_three {
echo "I am in function ${FUNCNAME[0]} with a depth of ${#FUNCNAME[@]}"
function_two
}
for function in one two three ; do
echo -----
function_"${function}"
done
Inside a function - inside a loop, that's the point.
There is no need to name loops, just count them.
Counting in and out of loops is an overhead and prone to errors when code is modified, which would become completely unnecessary with this feature.
I absolutely know this would help me.
As to why not just use functions? This is a larger question and has been an ongoing debate for a long time. It generally comes down to unrestricted code block execution and jumps. Google about the goto statement and structured programming / functional programming, there is a lot of literature about this on line. Is is noticeable, however, that quite an number of languages have reintroduced the goto statement, while bash has not. It's an interesting subject.
Last edited by olly (2022-05-23 10:28:27)
Bullies are only weak people trying to compensate for their own inadequacy. If they can't compete intellectually, they bully.
Offline
Try
I knwo how that variable works.
Counting in and out of loops is an overhead and prone to errors when code is modified, which would become completely unnecessary with this feature
You already opted for spaghetti code…
#!/bin/bash
shopt -s expand_aliases
alias until='((loopdepth++)); until'
alias while='((loopdepth++)); while'
alias for='((loopdepth++)); for'
alias done='done; ((loopdepth--))'
loopdepth=0
for ((i=0;i<1;++i)); do
echo "for $loopdepth"
while ((i<1)); do
echo "while $loopdepth"
until ((i>0)); do
((++i))
echo "until $loopdepth"
done
echo "while2 $loopdepth"
done
echo "for2 $loopdepth"
done
Google about the goto statement
Offline
Thank you!.
You have precisely made my point for me!
That is exactly the type of "work around" and overhead code that needs to be introduced to achieve a simple goal. Coding shows that if there is, at any time, a need to compensate for inadequacies in a structure, then the structure should be adapted. When I say Google the goto statement, I mean have a look at Wikipedia and get an understanding of the idea, particularly the introduction of the structured programming paradigm. As I have said before, many other languages have reintroduced it, some by emulation which is what I'm looking at. Bash is an evolving language, and an inbuilt loop counter would move toward that. It's not about out clevering each other, it's the bigger picture. I started this thread not just to ask about a loop counter, but to also maybe start a intelligent debate about the use of, and possible reintroduction in bash, of the goto statement. I thought the arch forum might be a place to do this. Try and prove me right.
Bullies are only weak people trying to compensate for their own inadequacy. If they can't compete intellectually, they bully.
Offline