Goto in bash (2012)
bobcopeland.com
bobcopeland.com
These days, we all understand why GO TO is bad. However, in this paper, Knuth does a good job at explaining ways that GO TO can be good. I found that the paper took time to get through, but was well worth the effort.
Here is a link to the paper: http://pic.plover.com/knuth-GOTO.pdf
http://repository.readscheme.org/ftp/papers/ai-lab-pubs/AIM-...
Having worked in the JavaScript-github-npm-node-environment-complex the last few years, I feel what Dijkstra had against GOTO has largely been lost on the current crop of CADTs (https://www.jwz.org/doc/cadt.html). The spaghetti is stronger than ever today.
Downvotes if you want. I've actually used GOTO before there was an option not to.
I've had way too many days of debugging webpack/browserify/react/jquery-whatever nonsense that leads to stupid dead-end threads on stackoverflow or the issues tab in Github. When you're debugging an 8th-party connector library that allows the 3rd-7th party piles of github crap to integrate into your app, and you find yourself stuck in the goddamn issues tab on Github to find the solution to your highly specific problem, something is wrong. It's time to throw it all away and start over.
I find it pretty ironic he calls HN users "man-children" by redirecting us to this image, but oh well.
I think it would be pretty amusing if HN automatically proxied links to his site through norefer.com or similar.
<a rel="noreferrer"
https://html.spec.whatwg.org/multipage/semantics.html#link-t...So there was a time when it was the only type of flow control I understood and going to C with these newfangled looping constructs was new and interesting because I understood just how useful they were compared to the GOTO statements I had needed to structure so carefully before.
A couple of jobs ago, I had to write a job to download a large set of files scattered in a deep hierarchy from the web interface of an internal distributed file system. Because the directory page was non standard and didn't contain any url, I couldn't simply use wget or curl in recursive mode, but had to do some light parsing of each tree level.
My simple bash one liner quickly grew in a larger script. Of course, this being bash, it was trivial to make it do the scraping and downloading in parallel, but I needed a way to limit the maximum number of concurrent downloads.
To make a long story short, I ended up reimplementing semaphores in bash on top of message passing via pipes and 'coproc' (which I had just found out).
In retrospect I could have probably implemented something simpler and more robust on top gmake (which interestingly also uses pipes to limit the number of subprocesses but doesn't need a supervisor process).
do_one_thing() {
local arg=$1
... do stuff with $arg
}
do_with_limited_parallelism() {
cat things-to-do.txt | xargs -P 10 -n 1 -- $0 do_one_thing "$@"
}
"$@"
That limits the number of concurrent processes, which is almost always good enough for limiting the number of concurrent downloads. If you have really tiny downloads, then the overhead of starting a connection per process may matter. In that case it's easy to do more than one download per process with say -n 50 instead of -n 1.http://make.mad-scientist.net/papers/jobserver-implementatio...
""" Rather than using complex schemes such as a central server, shared memory, sockets, etc. for synchronizing the various instances of make, he suggested we use the simplest, most basic UNIX construct: a pipe. Not only is this easy, but it’s also a relatively portable concept. Most operating systems these days implement some sort of pipe feature, because that paradigm is so useful.
The idea is ingeniously simple: the initial, top-level make creates a pipe and writes N one-byte tokens into the pipe. That pipe is shared between that make and all submakes, and any time any make wants to run a job it first has to read a token from the pipe. Once the job is complete, it writes the token back to the pipe. Since there are only N tokens, you know that you will never invoke more than N jobs. """
Unfortunately I didn't know how make -j was implemented at that time.
mkfifo queue
run_crawler root > queue &
parallel -a queue run_crawler > queue
add --group or -k to taste.So, is it just me that keep refining bash 'one liners' well past the point they should be implemented on a real language?
This morning I was scraping the images from the 2016 report and given they were like ~230 images I thought it could be cool to download them in parallel, but I quickly realized this would lead to such path and downloaded these in serial.
I still wonder what's the _right way_
Yikes.
I have just coined a name for this crude technique: "trumpolines". Under this nomenclature, the program is said to construct a trumpoline by extracting a suffix of itself beginning with the label into a local variable, and then effectively branches to it via eval.
This is vaguely reminiscent of "trampolines" in compiled languages like C, whereby machine code is constructed in local storage (on the stack) and then branched to (requiring an executable stack). GCC uses trampolines for indirection on pointers to GNU C nested functions.
Trumpolines are so named because they will trump the process's memory and stack resources.
To see for yourself: run a non-trivial batch script in cmd.exe with plenty of gotos and check out all the CreateFile calls in [Process Explorer](https://technet.microsoft.com/en-us/sysinternals/processexpl...).
cmd=$(sed -n "/$label:/{:a;n;p;ba};" $0 | grep -v ':$')
case ${1-start} in
start)
# your script goes here...
x=100 $0 foo
;;
mid)
echo "This is not printed!"
x=101 $0 foo
;;
foo)
x=${x:-10}
echo x is $x
esacI didn't stop and try to reason it out on my own, but then I clicked and saw the answer, and said "heh. cute." So there you go- enough people felt the same way I did, that the voting system moved this to the 4th link on the top page. /shrug. That's the internet for you!
"Prepare to cringe."
It's a dirty hack, this is Hacker News.
goto=42
while true ; do
case $goto in
1 )
code for label 1
goes here
break # finish
;;
42 )
code for label 42
goes here
goto=1
;;
esac
done
You don't have the syntactic sugar here, and there are some inconveniences, but think of the positives: this does not claim a new stack frame for each jump, let a lone a new stack frame holding a big string variable that holds most of the script source code.EDIT: /me sighs, this isn't the one I was looking for but it'll do for now. http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html / http://www.chiark.greenend.org.uk/~sgtatham/coroutines.h