toybox is pretty cool, but there is one big problem (though I am biased): the `bc` it has is old and outdated and not much better than the GNU `bc`.
The last update was several years ago because Rob wanted to maintain the version in toybox himself. It has not gotten much love since.
Source: I am the author of the `bc` in toybox. My current version [1] is much faster and has more math libraries and extensions. Even Android uses my current version rather than the version in toybox.
Edit: mistakenly said that toybox has my `dc`. It does not. Busybox does, and I mixed them up. I've corrected the above.
Do you know by any chance why POSIX bc has this weird limitation that function and variable identifiers should have a mere single letter (a-z)?
That is a good question.
I have a (very) educated guess, but it's still only a guess.
I think there were two reasons.
The first is historical practice. POSIX themselves say that they don't codify new standards. Instead, they codify existing practice as standards. In practical terms, this means that they look at what all implementations that they care about do, figure out what is common among them, and codify that as a standard.
As far as I can tell, at the time that POSIX was first codified, there was at least one `bc` implementation that only accepted single letter names. So that's what they codified.
Some evidence for this reason: in the Rationale section of the `bc` standard [1], they mention historical practice and implementations several times.
(As an aside, the reason that that implementation only accepted single letter names is because it was a compiler for `dc`, and `dc` only accepts single letter names because of its reverse polish notation and "one letter per command" design.)
The second reason, while related to the fact that historically, `bc` was a frontend to `dc`, is slightly different: it's easier to implement that way.
If you look at the original source of the original Robert Morris and Lorinda Cherry `bc` (which I have because I'm a nerd), its parser only looked for the second letter of each keyword. They could do that because all other identifiers would be single letters. It worked, and they also probably wanted to spend little time on it since most of the users would be programmers like themselves who could deal with such limitations easily, though that is an assumption on my part. (Someday I would like to talk to Morris and Cherry about it, as well as Philip Nelson, the author of the GNU `bc`.)
By the way, the original Morris and Cherry implementation was the implementation in use at the time of codifying POSIX that only allowed single letter names. Its direct descendant is still in use today as the `bc` for the Plan 9 operating system.
So that's my guess. Take it with a grain of salt.
Thank you very much for this thorough reply. That is probably it.
Now, suppose I want to write a POSIX shell script that does trigonometric calculations. Should I actually use `bc`? Is there a "translator" that reads `GNU bc` or your `bc` for example, and converts it into POSIX-compliant bc? (meaning converting the symbols to one letter in a way that does not produce conflict, declaring all used variables in a function in the first line (auto), etc)
> Now, suppose I want to write a POSIX shell script that does trigonometric calculations. Should I actually use `bc`?
Yes, you should; `bc` includes trigonometric functions even in POSIX accessible by the `-l` flag.
However, I'm not sure why you would; if you know you have a `bc` implementation other than a strict POSIX `bc`, I would just use that, even in a POSIX shell script.
POSIX is extremely limited; it does not even have `else` for `if` statements! It also does not allow you to use comparison operators outside an `if` statement or loop header. It does not have `continue`.
On the other hand, my `bc` is known to work in just about every POSIX system, and there are ports for it in OpenBSD and NetBSD. It is also the system `bc` in FreeBSD for FreeBSD 13. It also builds on Linux for either glibc or musl, and there are packages for it in Arch AUR, Gentoo, and other smaller distros. And it's easy to build from source with zero dependencies.
In short, if you're going to write a shell script to do math, I'd personally find it more appealing to actually check for and install my `bc` than to use strict POSIX.
> Is there a "translator" that reads `GNU bc` or your `bc` for example, and converts it into POSIX-compliant bc? (meaning converting the symbols to one letter in a way that does not produce conflict, declaring all used variables in a function in the first line (auto), etc)
For the record, my `bc` and GNU `bc` still require the auto list. That's part of the standard, so we cannot really get away from it.
But as for the existence of a translator, no, there is not a translator. I could probably write one, and putting it in my `bc` would be easiest since my `bc` already has a parser.
However, I do not think that would be a good use of time; trying to translate some features, especially `continue` would be tough. `continue` would be tough because I would have to translate the loop into two loops and when exiting the loop, differentiate the case between exiting for a `continue` and an actual exit, and if on `continue` let the outer loop loop.
Also, some features just could not translate, I'm afraid. My `bc` has a full PRNG, which can generate numbers of arbitrary size and precision. There just would not be a way of translating that feature.
And putting the translator in my `bc` would sort of be useless; if you installed it for the translator, why not just use it?
If this message sounds annoyed, it's because I'm annoyed at POSIX, not you. The fact that they have not even standardized `else` really gets my goat; all implementations, besides the Plan 9 one, have `else`, even one that translates for `dc`. There's no excuse for not having it. And they also seem to limit it on purpose, with not allowing comparison operators outside of `if` and loops. (Oh, and you can only use ONE operator per `if` and loop!) Grr...
tl;dr: Yes, use `bc` for trigonometry in shell scripts, but use a full-featured `bc` if at all possible.
I've bookmarked your gitea bc repo, not just for bc, but as an example of a neatly managed FOSS project, like providing performance comparison, fuzzing, project structure, the fact of using self-hosted gitea itself, etc
Skimming through [1], I see neither of Winget [2] nor Chocolatey [3] have any `bc` implementations as of yet. Maybe you can send them a PR? It may help adoption in other distros in the future.
[1] https://repology.org/project/bc/versions
[2] https://github.com/microsoft/winget-pkgs
[3] https://community.chocolatey.org/packages?q=%22bc%22
Hope your implementation wins ;)