On 2023-08-03 18:57, Phil Budne wrote:
On the subject of "no printf", there is not
one, not two, but THREE
ways to format strings, easily compounded with print:
print("%s %s" % ("hello", "world"))
print("{1} {two}".format("hello", two="world"))
print(f"{greeting} {populace}")
I'm pretty sure the last method (which initially made me vomit, due to
violating my hardwired ideas about complicating the lexer, as if it
can even be thought of as a separate layer), BUT I Seem To Recall that
it allows a class to implement a formatting method, which may (or may
not) work for complex numbers.
Actually, there's no need to move away from printf(3) for customization.
glibc provides register_printf_specifier(3), register_printf_modifier(3),
and register_printf_modifier(3), with which you can register %S for
printing your very nice struct. You can even register modifiers, such as
%vS for printing your structure in a different manner.
Of course, those APIs are not portable, but that's a matter of porting
them; you don't need to invent a completely new formatted print variant
just to do that.
How does one even specify the equivalent of "%+'0#8.5f" in the new {}
formats??
Of course, there may be reasons to move away from printf(3): C++ seems
to have a faster thing with std:format (or so they claim; I didn't try
it). But if speed is not a problem, I'd keep the good ol' syntax that
everybody knows. No need to make everybody learn a "cool" new print
function, that probably won't be as tunable as printf(3) is.
Another thing is type safety. printf(3) is actually type-safe. At least
as long as you use powerful compilers that can diagnose misuses of
printf-like APIs. GCC provides [[gnu::format()]] for a reason. And if
you customize printf with your own formats, Clang has tools for checking
those too.
Type "hinting" has been mentioned: again, it's almost like a whole new
version of the language. You need to pick a type checker, and likely
turn up the knobs to achieve any actual safety, and then deal with the
fact that not all packages supply hints out of the box. It kind of
offers the desert-topping/floor-wax dichotomy: You can easily/quickly
write small programs with dynamic typing for quick one-offs, AND write
better armored code for libraries & production code.
On tabs vs spaces: Python3 forbids mixing them. Again, fascist, but
"it's for your own good".
So yes, Python sucks, but I continue using it, and unlike sendmail
(which I continue to run, as I have a 200+ line .mc file it would take
me at LEAST a week to replicate the effects of in another MTA), I
don't tell people Python is unsuitable at any speed.
I'd probably happily write Go or Rust, given a situation (existing
project/program) where its use was inevitable, and I DO have a program
I think is a good candidate for rewriting in Go, but on the whole,
it's a useful tool for many kinds of programmers, and in many
situations, which I think is somewhat remarkable.
I'll go a little step further, and claim that newlines being significant
is another bad decission. It's one of the things I dislike from
languages, including sh(1). My scripts end up having a lot of escaped
newlines, because I find the pipe to be more readable and pleasant as
foo \
| bar
rather than
foo |
bar
While I can forgive that in the shell, because interactive mode is as
important as scripts, I can't do the same with Go. Go is a programming
language, and having newlines be significant is nonsense. Saving from
typing ;s is a similar excuse that the one python used for saving typing
{}s. And the consequence is that due to that fascist rule of go, I
can't put the opening brace of a function declaration in a new line; it
must be sticked to the same line as the function declarator.
I never enjoyed Go, and that was the main reason. In any case, I never
found a need for it. Most (all?) of what I do can be done with sh(1)
or C.
Alex