4 ms·
Fun shell function fact: used to be if you `break` or `continue` in a function without a loop, bash would find the loop: breaker_breaker() { break; } f
by ridiculous_fish 5y ago
Fun shell function fact: used to be if you `break` or `continue` in a function without a loop, bash would find the loop:
breaker_breaker() { break; }
foo() { breaker_breaker; }
while true; do
echo Loop
foo
done
bash dynamically crawled up the call stack until it hit a break-able loop. If you squint it almost looks like exception handling! Anyways this no longer works in bash, though it still does in zsh.
- Sniffnoy 5y agoHeh, kind of like dynamic scoping, except as applied to control flow...
- barosl 5y agoThat's very impressive, it almost feels like a legit useful hack. Why was it not fixed in zsh? Did they decide it was working as intended?
- naniwaduni 5y agoWell, bash's new behaviour (noisily complain and do nothing, reporting success) doesn't do anything useful, so implementing it gratuitously breaks old code to no gain. Dynamic stack-crawling is more or less the most popular historical behaviour (though afaict the Bourne/Korn lineage just silently fails breaks outside the enclosing function); it's just generally consistent with everything else in the shell that's globally/dynamically scoped. Even in the shells where you can't break out of your enclosing function, `eval break` still breaks through loops in your current context, and that kind of looks like a function you called that called break if you squint. (POSIX expressly leaves this case undefined with a carveout for break/continue inside the body of a function lexically contained within a loop.)
- dllthomas 5y ago> If you squint it almost looks like exception handling! It also reminds me of TCL's "uplevel": https://www.tcl.tk/man/tcl8.4/TclCmd/uplevel.html https://www.tcl.tk/man/tcl8.4/TclCmd/uplevel.html
- cryptonector 5y agoBash does kinda have something like uplevel, and I use it: `typeset -n`.
- dllthomas 5y agoThat's more pass-by-reference, right? Which can be used to set things in the calling context, to be sure, but seems meaningfully different from "run this code N frames up", partly because it is limited in what it can do and partly because it can only change variables that you are actually mentioning in what you pass in. (... unless I miss something.)
- cryptonector 5y agoNo, it's pass-by-name, which can feel like pass-by-reference. And yes, it's only that.
- dllthomas 5y agoI usually associate "call-by-name" with laziness. Isn't this more pass-by-reference that may happen to be implemented using names under the hood? Alternatively, how would you distinguish them?
- wruza 5y agoPerl does that as well.