$ echo $((1*2))
2
$ string="hello, world"
$ echo ${string/hello/goodbye}
goodbye, world $ echo $((1*2))
2
$ string="hello, world"
$ echo ${string/hello/goodbye}
goodbye, world bash-3.2$ echo $((1.5+0.5))
bash: 1.5+0.5: syntax error: invalid arithmetic operator (error token is ".5+0.5")
https://unix.stackexchange.com/questions/40786/how-to-do-int...I gave up INTEGER BASIC for APPLESOFT several decades ago, and never looked back.
(LOADING INTEGER INTO LANGUAGE CARD)
]INT
>PRINT 1.5 + 0.5
*** SYNTAX ERROR
>FP
]PRINT 1.5 + 0.5
2
It's 2019, and you're struggling to do in bash what you could have done on an Apple ][ in 1979, but the syntax you need to use is even WORSE than BASIC, so your code looks like line noise from when your mom picks up the phone while you're using a 300 baud modem. Is that really progress?https://en.wikipedia.org/wiki/Integer_BASIC
>Integer BASIC was phased out in favor of Applesoft BASIC starting with the Apple II Plus in 1979. This was a licensed but modified version of Microsoft BASIC, which included the floating point support missing in Integer BASIC.
https://en.wikipedia.org/wiki/Applesoft_BASIC
>Applesoft BASIC is a dialect of Microsoft BASIC, developed by Marc McDonald and Ric Weiland, supplied with the Apple II series of computers. It supersedes Integer BASIC and is the BASIC in ROM in all Apple II series computers after the original Apple II model. It is also referred to as FP BASIC (from "floating point") because of the Apple DOS command used to invoke it, instead of INT for Integer BASIC.
Notice that there are even machine language instructions for cos, atan, tan, sin, ln, etc. How do you call those instructions in bash?
https://docs.oracle.com/cd/E18752_01/html/817-5477/eoizy.htm...
>x86 Assembly Language Reference Manual: Floating-Point Instructions
>The floating point instructions operate on floating-point, integer, and binary coded decimal (BCD) operands.
https://en.wikipedia.org/wiki/Turing_tarpit
>54. Beware of the Turing tar-pit in which everything is possible but nothing of interest is easy.
But I think that most people who use bash simply have no clue how expensive forking another process is, and not enough experience to realize that software always ends up growing up to be much more complex than they originally expected, and think that "1+1" is as much arithmetic as they will ever need.
https://en.wikipedia.org/wiki/Greenspun%27s_tenth_rule
>Any sufficiently complicated C or Fortran program contains an ad-hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.
https://en.wikipedia.org/wiki/Jamie_Zawinski#Principles
>Every program attempts to expand until it can read mail. Those programs which cannot so expand are replaced by ones which can.
You're talking to someone who ran a web farm in the 90s so yeah, I saw the evolution from CGI to mod-perl and on. I mean I know the cost of forking. But come on, aren't you taking your criticism a bit far?
I also had an Apple ][+. Actually, one wasn't available so we Frankensteined one together from an Apple ][ and an Applesoft language card by swapping the motherboard ROMs and language card ROMs.
We both have some perspective from the Apple ][ days, and can appreciate how astronomically fast computers are compared to how slow they used to be.
But doesn't it give you pause (literally and figuratively) when you see people thoughtlessly and casually write code in 2019 that runs slower on a high-end MacBook Pro than the equivalent code would run on an Apple ][ in 1979?
People should take a momemt to reflect on what they're trying to accomplish and if there are better ways of going about it, before writing Rube-Goldbergesqe bash scripts heavily punctuated with line noise, haphazardly stringing together Unix processes and temporary files with cryptically abbreviated commands using mysteriously curt flags and parameters (like "dc -l", or is it "bc -l", and is that dash-ell or dash-one? I can't remember, and we haven't even gotten to the part about how I have to quote and escape the arithmetic expression parameter)!
It's not as if they're making thoughtful trade-offs, and that as a result of choosing to use bash despite all its weaknesses, they're actually developing more robust, easier to read and maintain code than they would have had they used Python.
You're making a false equivalence like "there is slow arithmetic on both sides". No: one side is astronomically slow, requiring millions of instructions, the other side is tolerably slow, requiring hundreds of instructions. There is no comparison.
Again, this isn't about Python. That's just an example. It's about forking or not forking. You know, the topic of this thread.
If you like, I could translate my Python argument to JavaScript, and you could explain how a bash JIT compiler could optimize out all the instructions necessary to fork "bc" to call the cos instruction.
Let me head you off at the pass before you ask "Why would I ever want to calculate a cosine in a bash script?" when you should be asking "Why would I ever want to use a language that doesn't let me calculate a cosine? Or even draw a circle?"
To illustrate my point: Perhaps you want to write a script that draws a pie chart to illustrate your disk space. That's a typical sysadminy scripty thing to do, right?
With bash, you'd have to call out to many other processes to do that. Why is that? Tell me why hasn't anyone come up with a way to draw like the canvas API in bash, without forking off dozens if not thousands of processes?
Don't you think floating point would be useful for calculating disk space usage more accurately than integer percentages, and the canvas api would be useful for drawing pie charts?
If you think you'd never need to do something like that in bash, then you have an enormous blind spot from bash tragically lowering your expectations, imagination, and productivity as a programmer.
Because bash can't even perform the simplest APPLESOFT BASIC floating point math operations or HGR hires graphics HPLOT drawing commands.
So you would first have to fork off to one process to multiply and add a few numbers and calculate a cosine, and then you'd have to fork off to another process to multiply and add a few numbers and calculate a sin (because "bc" can only return one result at a time, thank you). Then you would have to pass those numbers to another program to draw them, probably with a here-file, some loops, a bunch of variable substitutions, temporary variables, intermediate files, lots and lots of string concatenation, converting back and forth between binary floating point numbers and strings, all meticulously decorated with a phalanx of quotes, escapes, double and triple backslashes, back-ticks, colons and exclamation marks before single character codes, and double secret parenthesis.
You're being feisty, whatever.
> We are discussing the overhead of forking processes to do math, which Python doesn't have to do.
Python uses dynamic dispatch on boxed types for every single operation. You're right this /only/ takes hundreds of instructions, but that just shows my analogy is appropriate. That's the turtle, in case you didn't understand it. I think it's silly for you to say this is "tolerably slow" for anyone but yourself. For other people, a fork per operation is completely tolerable. (I'm not one of those people...)
> [...] explain how a bash JIT compiler could optimize out all the instructions necessary to fork "bc" to call the cos instruction.
If anyone cared, bash could implement "bc" as a builtin the same way it does "echo". That'd be ugly, but it seems like the kind of thing the GNU folks would do if it was a common enough use case.
So I'll make an analogy too: A turtle -vs- a snail are the same order of magnitude slow. The Nazis -vs- the protesters are not of the same order of magnitude evil in Charlottesville, just like forking a new process -vs- dynamically dispatching to a function in the same process are not of the same order of magnitude slow in Unix.
And I'll reiterate:
With Python (and JavaScript) it's POSSIBLE and even NORMAL for a JIT compiler to optimize the code to call mul instructions directly. PyPy is a thing, it's free, and it works just fine, thank you:
But it's IMPOSSIBLE to implement a bash JIT compiler (or even AOT compiler) that optimizes out the millions of instructions that are required to make a system call to fork "bc" to call that same "mul" instruction. In Linux, you simply can't optimize out system calls. (Unless Alexia Massalin's Synthesis kernel is giving you a free piggy back ride ;).
https://en.wikipedia.org/wiki/Alexia_Massalin
http://infolab.stanford.edu/~manku/quals/summaries/gribble-s...
And no, integrating "bc" into bash isn't a valid solution, or they would have done it ages ago. How about integrating the canvas API into bash too, while you're at it? Tell me when you convince them to accept your pull request!
Are you intentionally invoking Godwin's law because you know your argument is untenable?
> PyPy is a thing, and it works just fine, you know
I like PyPy. It's not perfect, but it's pretty good. Maybe you should recommend that in the first place next time.
> But it's IMPOSSIBLE to implement a bash JIT compiler [...] to fork "bc"
Never say never. Before V8, everyone thought JavaScript had to be as slow as Python too. Now we have PyPy and LuaJIT, which I would've thought were impossible.
> And no, integrating "bc" into bash isn't a valid solution, or they would have done it ages ago
You seem really hung up on "bc". You do realize that "echo" wasn't always a builtin, and that they added it for performance reasons, right? If anyone cared enough, they could add "bc" as a builtin. Hell, the expression evaluator for integers is well on it's way. You're right that probably nobody cares enough to build in "bc", but I wouldn't be surprised to see a triple paren or square bracket math interpreter with floating point support in bash someday. Heh, maybe they'll even add complex numbers. And a bash JIT is exactly the kind of thing some grad student would do for the absurdity of it all.
> [...] you ask "Why would I ever want to calculate a cosine in a bash script?"
I wouldn't ask that. This kind of argument strategy is silly too. You should choose your own words, and I'll choose mine. Leave the fake dialogs to Aristotle.
> To illustrate my point: Perhaps you want to write a script that draws a pie chart to illustrate your disk space. With bash, you'd have to call out to another language to do that. Why is that? Tell me why hasn't anyone come up with a way to draw like the canvas API in bash, without forking off dozens if not thousands of processes? Don't you think that would be useful?
I routinely use gnuplot as plotter in a child process. This works with bash, python, C++, or any other language which supports popen (that's fork, dup, and exec).
> Because bash can't even perform the simplest APPLESOFT BASIC floating point math operations [...]
I'm not defending bash. I'm saying that putting Python much ahead of it is silly. Why would you want to run a race with either a snail or a turtle? Silly parables about the tortoise and the hare aside, pick a cheetah or something.
> And of course needlessly converting all those numbers back and forth between strings and floating point so many times.
Python tediously checks if the vtable contains the necessary operator, evaluates the function pointer it finds, which checks the other operand's type, unpacks the 8 bytes of doubles from each 32 byte struct, finally performs the operation, then allocates a new 32 byte structure for the return result, which is checked to see if an exception occurred, and then pushed onto the stack. I probably missed some steps, and I certainly ignored the sophomore level interpreter loop overhead.
I mean, yeah that's faster than fork, but I'm not sure it's a huge win over anything else.
This is not "astronomically slow" on any hardware from this millennium.
> Let me head you off at the pass before you ask "Why would I ever want to calculate a cosine in a bash script?" when you should be asking "Why would I ever want to use a language that doesn't let me calculate a cosine? Or even draw a circle?"
Because there are places for languages that can't do everything you'd ever want. Sometimes they can be extra specialized for a common task you do often: for bash, this happens to be "how can I glue together things quickly?"
> Tell me why hasn't anyone come up with a way to draw like the canvas API in bash, without forking off dozens if not thousands of processes?
Because this isn't something that bash would be good at, as you've mentioned. It's a task that would be a lot better suited to some other tool, which bash could then interact with.
How do you call those in Python ;)
Fundamentally, you're making a big deal about something that isn't really that horrible. Not everyone has Python on their system, and a fork() is not a terribly costly operation for a shell script. Sure, it might take an extra microwatt, but arguing that this is the same as Bitcoin mining or rolling coal is an argument in the extreme.
Simple! You shell out to your math-compiler:
https://github.com/skx/math-compiler/
That compiles your math down to assembly language, which has got to make sure they're super-fast, right? ;)
https://en.wikipedia.org/wiki/Incompatible_Timesharing_Syste...
https://dspace.mit.edu/handle/1721.1/6153
https://github.com/PDP-10/its/blob/master/doc/info/ddt.33
https://github.com/PDP-10/its/blob/master/doc/_info_/ddtord....