HNHacker News
TopNewBestAskShowJobs

cb321

1,490 karma · joined July 25, 2020

submissionscomments
cb321··on Python is not a great language for data science
Like Python, R is a 2 (+...) language system. C/Fortran backends are needed for performance as problems scale up.

Julia and Nim [1] are dynamic and static approaches (respectively) to 1 language systems. They both have both user-defined operators and macros. Personally, I find the surface syntax of Julia rather distasteful and I also don't live in PLang REPLs / emacs all day long. Of course, neither Julia nor Nim are impractical enough to make calling C/Fortran all that hard, but the communities do tend to implement in the new language without much prompting.

[1] https://nim-lang.org/

cb321··on APT Rust requirement raises questions
You might enjoy https://nim-lang.org/ which has a Python-like syntax with even more flexibility really (UFCS, command-like calls, `fooTemplate: stuff` like user-defined "statements", user-defined operators, term-rewriting macros and more. With ARC it's really just about as safe as Rust and most of the stdlib is fast by default. "High quality" is kind of subjective, but they are often very welcoming of PRs.

Anyway, to your point, I think a newbie could pick up the basics quickly and later learn more advanced things. In terms of speed, like 3 different times I've compared some Nim impl to a Rust impl and the Nim was faster (though "at the extreme" speed is always more a measure of how much optimization effort has been applied, esp. if the language supports inline assembly).

https://cython.org/ , which is a gradually typed variant of Python that compiles to C, is another decent possibility.

cb321··on Ion: Modern System Shell in Rust
"Popularity" probably has more to do with Apple moving to Zsh than anything else. Zsh has been more powerful than Bash for literally the entirety of the existence of both. It surely was back in like 1993 when I first looked at them. The "emacs of shells" might not be the worst summary.

Fish is a more recent addition, but I hate its `for loop` syntax, seemingly copied from BSD C Shell, which this Ion shell seems to have copied (or maybe Matlab or Julia?). Baffles me to impose a need for `end` statements in 2025. In Zsh, for a simple single command, I need only say `for i in *;echo $i` - about as concise as Python or Nim. In the minimalism aesthetic, Plan 9 rc was nicer even before POSIX even really got going (technically POSIX was the year before Plan 9 rc) for quoting rules if nothing else.

I think it's more insightful to introspect the origins of the "choosing something outside bash" rule you mentioned. I think that comes from generic "stick to POSIX" minimalism where Bash was just the most commonly installed attempt to do only (mostly) POSIX shell.. maybe with a dash of "crotchety sysadmins not wanting to install new shells for users".

Speaking of, the dash shell has been the default on Debian for a long while. So, I think really the rule has always been something "outside POSIX shell", and its origins are simply portability and all those bashisms are still kind of a PITA.

cb321··on Show HN: An easy-to-use online curve fitting tool
These are all big topics, but any "parametric curve fitting" like this tool uses is parameter estimation (the parameters of the various curves). That already makes strong modeling assumptions (usually including IID, Gaussian noise, etc.,) to get the parameter estimates in the first place. I agree it would be even better to have ways to input measurement errors (in both x- & y- !) per your example and have non-bootstrap options (I only said "probably"), residual diagnostics, etc.

Maybe a residuals plot and IID tests of residuals (i.e. tests of some of the strong assumptions!) would be a better next step for the author than error estimates, but I stand by my original feedback. Right now even the simplest case of a straight line fit is reported with only exact slope & intercept (well, not exact, but to an almost surely meaningless 16 decimals!), though I guess he thought to truncate the goodness of fit measures at ~4 digits.

cb321··on Show HN: An easy-to-use online curve fitting tool
The fit diagnostics at the top of the plot are inadequate. This needs at a minimum error estimates on the estimated parameters (probably bootstrap) and ideally some kind of "error envelope" on the plot.
cb321··on The terminal of the future
Any article about this topic that does not at least mention https://arcan-fe.com/about/ feels incomplete. (Also, Arcan is already available.)
cb321··on SPy: An interpreter and compiler for a fast statically typed variant of Python
"Great" smells very subjective. I went to https://forum.nim-lang.org/ . Put "flask" in the search box. Second hit (https://forum.nim-lang.org/search?q=flask) is this: https://forum.nim-lang.org/t/11032 . That mentions not one but 2 projects (https://github.com/HapticX/happyx & https://github.com/planety/prologue).

If either/both are not "great enough" in some particulars you want, why not raise a github issue? (Or even better look into adding said particulars yourself? This is really the main way Python grew its ecosystem.)

cb321··on AI's Dial-Up Era
Besides your chart, another point along these lines is that the article cites Azhar claiming multiples are not in bubble territory while also mentioning Murati getting essentially infinite price multiple. Hmmmm...
cb321··on State of Terminal Emulators in 2025: The Errant Champions
I can confirm that I just do it over ssh fine all the time -- gnuplot, img2sixel as an "image-cat", etc. (`st` with patches to add sixel support as discussed in various places in these comments.)
cb321··on State of Terminal Emulators in 2025: The Errant Champions
I 100% agree `st` is pretty great and comparing bare bones is unfair.

Thanks for that link! I suppose I should have provided a link to the variant I use which is https://github.com/bakkeby/st-flexipatch though I do have like 14 of my own private patches. :-) Because it really is a simple, hackable codebase.

I will say, though, that I doubt there are many unicode conformance patches floating about. I don't know though, and I haven't looked.

cb321··on State of Terminal Emulators in 2025: The Errant Champions
`st` used to have a patch set for sixel graphics on its web site. I use an old version all the time to do gnuplots in terminals with nice scrollback. It seems to have been retired in favor of the kitty graphics protocol.
cb321··on Notes by djb on using Fil-C
While I agree with everything you wrote, the "better ways" have a "cap" on how effective they can be. The root causes -- both in-group preference[1] and laziness/delegation to the "smart loudmouth contemporaries/smart-enough predecessors" -- will be things for the foreseeable future among humans. Some might even call them eternal / instinctive. Our whole civilization is based upon delegation/layering, but trust sure is tricky! Even the smartest humans fall prey to Gell-Mann amnesia[2] on topics beyond their expertise. Personally, I think most of what you wrote all connects to the cluster of wicked problems[3] that I think of as "Humanity Complete" (after NP-Complete transformability).

[1] https://en.wikipedia.org/wiki/In-group_favoritism

[2] https://en.wikipedia.org/wiki/Gell-Mann_amnesia_effect

[3] https://en.wikipedia.org/wiki/Wicked_problem

cb321··on Notes by djb on using Fil-C
Since anything/0 = infinity, these kinds of things always depend upon what programs do and as a sibling comment correctly observes how much they interfere with SIMD autovectorization and sevral other things.

That said, as a rough guideline, nim c -d=release can certainly be almost the same speed as -d=danger and is often within a few (single digits) percent. E.g.:

    .../bu(main)$ nim c -d=useMalloc --panics=on --cc=clang -d=release -o=/t/rel unfold.nim
    Hint: mm: orc; opt: speed; options: -d:release
    61608 lines; 0.976s; 140.723MiB peakmem; proj: .../bu/unfold.nim; out: /t/rel [SuccessX]
    .../bu(main)$ nim c -d=useMalloc --panics=on --cc=clang -d=danger -o=/t/dan unfold.nim
    Hint: mm: orc; opt: speed; options: -d:danger
    61608 lines; 2.705s; 141.629MiB peakmem; proj: .../bu/unfold.nim; out: /t/dan [SuccessX]
    .../bu(main)$ seq 1 100000 > /t/dat
    .../bu(main)$ /t
    /t$ re=(chrt 99 taskset -c 2 env -i HOME=$HOME PATH=$PATH)
    /t$ $re tim "./dan -n50 <dat>/n" "./rel -n50 <dat>/n"
    225.5 +- 1.2 μs (AlreadySubtracted)Overhead
    4177 +- 15 μs   ./dan -n50 <dat>/n
    4302 +- 17 μs   ./rel -n50 <dat>/n
    /t$ a (4302 +- 17)/(4177 +- 15)
    1.0299 +- 0.0055
    /t$ a 299./55
    5.43636... # kurtosis=>5.4 sigmas is not so significant
Of course, as per my first sentence, the best benchmarks are your own applications run against your own data and its idiosyncratic distributions.

EDIT: btw, /t -> /tmp which is a /dev/shm bind mount while /n -> /dev/null.

cb321··on Nim 2.2.6
While it's ecosystem probably does not even match Julia's let alone Python's or the C/FORTRAN-verses, since Nim has been around for almost 20 years and publicly since 2008, there are still a lot of accumulated packages. Some are listed at: https://github.com/ringabout/awesome-nim for really a large (and even so still incomplete!) list of things you might be interested in. Hard to say how well maintained they are. That said, you do probably have to be prepared to do a lot of work yourself and work around compiler limitiations/bugs. Also, binding to C libs is very straightforward with a near trivial FFI.

I suppose it very much depends on the programmer & setting, but like 3 times I've looked for Rust projects similar to Nim ones and found the performance of the Rust quite lacking. Of course, any language that allows you access to assembly makes things ultimately "only" a matter of programmer effort, but the effort to get performance out of Nim seems very competitive in my experience. I've seen at least one ancient 1990s C project be more flexible and much faster in Nim at like 6% the LOC (https://github.com/c-blake/procs for the curious).

cb321··on Nim 2.2.6
Actually echo is not a statement - Nim's syntax is just much more flexible than Python so what looks like a statement in Python is actually just a UFCS/Command-Line "call" (of macro/template/generic/procedure aka "routine"). It is super easy to roll your own print function [1] and there is no penalty for doing so except that the std lib does not provide a "common parlance". So, that wheel might get reinvented a lot.

A lot of things like this in cligen because it is a leaf dependency (the literally 1..3 identifier CLI "api") and so many "drive by" PLang tester-outers might want to roll a little CLI around some procs their working on.

Also, beyond the echo x,y is same as echo(x,y) or x.echo(y) or x.echo y, the amount of syntax flexibility is dramatically more than Python. You can have user-defined operators like `>>>` or `!!!` or `.*`. There are also some experimental and probably buggy compiler features to do "term re-writing macros" so that your matrix/bignum library could in theory re-write some bz*ax+y expression into a more one-pass loop (or maybe conditionally depending upon problem scale).

I sometimes summarize this as "Nim Is Choice". Some people don't like to have to/get to choose. To others it seems critical.

Someone even did some library to make `def` act like `proc`, but I forget its name. Nim has a lot more routine styles than Python, including a special iterator syntax whose "call" is a for-construct.

[1] https://github.com/c-blake/cligen/blob/master/cligen/print.n...

cb321··on Uv is the best thing to happen to the Python ecosystem in a decade
Nim compile+link times can be sub-100 milliseconds with tcc [1] (just saw 93 ms on my laptop) which can yield pretty reasonable edit-compile-test cycles.

The grandparent's scientific/Go interests suggests a need for a large, working ecosystem and there are probably several places in ArrayMancer which need some love for "fallback cases" to work with tcc (or elsewhere in the as you note much smaller Nim eco-system).

EDIT: E.g., for ArrayMancer you need to make stb_image.h work with tcc by adding a nim.cfg/config.nims `passC="-DSTBIW_NO_SIMD -DSTBI_NO_SIMD"` directive, though. And, of course, to optimize compile times, just generally speaking, you always want to import only exactly what you really need which absolutely takes more time/thought.

[1] https://github.com/TinyCC/tinycc

cb321··on What we talk about when we talk about sideloading
I mentioned a knob - it did the trick with literal mechanical friction { instead of electrical friction = potentiometer :-) }.
cb321··on What we talk about when we talk about sideloading
All very true and "balk en masse" is what I meant by "first exposé". (Ancient wisdom, even, if you think about individuals and mortages/car loans and having a steady job, etc. rather than just businesses.) Maybe we'll anyway see some market segments succeed with "pay 2x more for your screwdriver, but it will at least be your screwdriver" slogans, and then have screwdrivers to do with what we will, like the proverbial "pound sand". ;-)
cb321··on What we talk about when we talk about sideloading
I'm not an expert on the case law, but supposedly United States v. General Electric Co. et al., 82 F.Supp. 753 (D.N.J. 1949) indicates that whatever design trade-offs might have existed, corporate policy makers were really just trying to screw consumers [1] (which is why they probably had to agree on short lifespans as a cartel rather than just market "this line of bulbs for these preferences" vs. "this other line for other people" -- either as a group or separate vendors). I keep waiting for the other shoe to drop where they figure out how to make LED bulbs crappy enough to need replacement.

EDIT: and, shucks, @kragen beat me to it! :-)

[1] https://en.wikipedia.org/wiki/Phoebus_cartel#cite_ref-USvGE-...

cb321··on What we talk about when we talk about sideloading
I would say the situation is worse as this "subscription-esque" model is "spreading" to areas beyond software. Exercise equipment like ellipticals and bicycles - whose software is/could be borderline +/- resistance level trivial - has been moving to "only works with an online subscription" business models for a long time.

I mean, I have had instances that controlled resistance with like a manual knob, but these new devices won't let you set levels without some $30+/month subscription. It's like the planned obsolescence of the light bulb cartels of the 1920s on steroids.

Personally, I have a hard time believing markets support this kind of stuff past the first exposé. I guess when you don't have many choices or the choices that you do have all bandwagon onto oligopoly/cartel-like activity things, pretty depressing, but stable patterns can emerge.

Heck, maybe someone who knows the history of retail could inform us that it came to software "from business segment XYZ". For example, in high finance for a long-time negotiated charging prices that are a fraction of assets under management is not uncommon. Essentially a "percent tax", or in other words the metaphorical "charging Bill Gates a million dollars for a cheeseburger".

EDIT: @terminalshort elsethread is correct in his analysis that if you remove the ability to have a platform tax, the control issues will revert.

cb321··on Show HN: Ordered – A sorted collection library for Zig
Being truly unordered like a set is not something you can do in a physical computer program unlike a mathematical abstraction. Anything stored is "ordered" in some way, either explicitly by virtual (or physical) memory addresses or implicitly by some kind of storage map equation (like a bitmap/bitvector or N-D C/Fortran array). It just might not be a useful ordering. (I.e., you may have to loop and compare.)

One might qualify such as "system-ordered", or in the Python insert-ordered dict, qualify with "insertion-ordered", though hash tables in general are sort of a melange of hash-ordering. The same container may also support efficient iteration in multiple orders (e.g., trees often support key order as well as another order, like VM/node pool slot number order).

So, in this context (where things are obviously elements of a computer program), it isn't obvious that hair-splitting over ordered vs. sorted in their purest senses is very helpful when what is really missing is qualification.

Of course, like in many things, people tend to name computer program elements after their abstractions. This is where confusion often comes from (and not just in computing!) .. borrowing the names without all the properties (or maybe with more properties, as in this case, though that is all probably a bit iffy with the frailty of how you enumerate/decompose properties).

EDIT: In a similar way, in a realized computer, almost any "set" representation can also be a "map". You just add satellite data. Even a bit-vector can have a "parallel vector" with satellite data you access after the bits (which could even be pointful in terms of cache access). This can cause similar confusions to the "ordered" vs. "sorted" stuff.

cb321··on Scripts I wrote that I use all the time
I used to do this, but unary kind of sucks after 3; So maybe others might like this better before their fingers get trained:

    ..() { # Usage: .. [N=1] -> cd up N levels
      local d="" i
      for ((i = 0; i < ${1:-"1"}; i++))
        d="$d/.."  # Build up a string & do 1 cd to preserve dirstack
      [[ -z $d ]] || cd ./$d
    }
Of course, what I actually have been doing since the early 90s is realize that a single "." with no-args is normally illegal and people "cd" soooo much more often than sourcing script definitions. So, I hijack that to save one "." in the first 3 cases and then take a number for the general case.

    # dash allows non-AlphaNumeric alias but not function names; POSIX is silent.
    cd1 () { if [ $# -eq 0 ]; then cd ..; else command . "$@"; fi; } # nice "cd .."
    alias .=cd1
    cdu() {           # Usage: cdu [N=2] -> cd up N levels
      local i=0 d=""  # "." already does 1 level
      while [ $i -lt ${1:-"2"} ]; do d=$d/..; i=$((i+1)); done
      [ -z "$d" ] || cd ./$d; }
    alias ..=cdu
    alias ...='cd ../../..' # so, "."=1up, ".."=2up, "..."=3up, ".. N"=Nup
and as per the comment this even works in lowly dash, but needs a slight workaround. bash can just do a .() and ..() shell function as with the zsh.
cb321··on Summary of the Amazon DynamoDB Service Disruption in US-East-1 Region
Oh, it's fine. At your leisure. I didn't mean to go against the assertions themselves, but more just kind of speak to their "unargued" quality and often sketchy presentation. Even that Simon piece has a lot of this in there, where it's sort of "by defenition of 'complexity'/by unelaborated observation".

In engineered systems, there is just a disconnect between on our own/small scale KISS and what happens in large organizations, and then what happens over time. This is the real root cause/why, but I'm not sure it's fixable. Maybe partly addressable, tho'.

One thing that might give you a moment of worry is both in that Simon and far, far more broadly all over academia both long before and ever since, biological systems like our bodies are an archetypal example of "complex". Besides medical failures, life mostly has this one main trick -- make many copies and if they don't all fail before they, too, can copy then a stable-ish pattern emerges.

Stable populations + "litter size/replication factor" largely imply average failure rates. For most species it is horrific. On the David Attenborough specials they'll play the sad music and tell you X% of these offspring never make it to mating age. The alternative is not the https://en.wikipedia.org/wiki/Gray_goo apocalypse, but the "whatever-that-species-is-biopocalypse". Sorry - it's late and my joke circuits are maybe fritzing. So, both big 'L' and little 'l' life, too, "is on the edge", just structurally.

https://en.wikipedia.org/wiki/Self-organized_criticality (with sand piles and whatnot) used to be a kind of statistical physics hope for a theory of everything of these kinds of phenomena, but it just doesn't get deployed. Things will seem "shallowly critical" but not so upon deeper inspection. So, maybe it's not not a useful enough approximation.

Anyway, good luck with your housing meetup!

cb321··on Summary of the Amazon DynamoDB Service Disruption in US-East-1 Region
That minimalist post mortem for the public is of what sounds like a Rube Goldberg machine and the reality is probably even more hairy. I completely agree that if one wants to understand "root causes", it's more important to understand why such machines are built/trusted/evolved in the first place.

That piece by Cook is ok, but largely just a list of assertions (true or not, most do feel intuitive, though). I suppose one should delve into all those references at the end for details? Anyway, this is an ancient topic, and I doubt we have all the answers on those root whys. The MIT course on systems, 6.033, used to assign reading a paper raised on HN only a few times in its history: https://news.ycombinator.com/item?id=10082625 and https://news.ycombinator.com/item?id=16392223 It's from 1962, over 60 years ago, but that is also probably more illuminating/thought provoking than the post mortem. Personally, I suspect it's probably an instance of a https://en.wikipedia.org/wiki/Wicked_problem , but only past a certain scale.

cb321··on Pica Numbers
I am not sure you'll be satisfied but this article by mhoye has a section on Watson and typewriters that seems relevant and is fun to read regardless: https://exple.tive.org/blarg/2019/10/23/80x25/

Parenthetically, I think much discussion around this neglects the constraints / true ultimate causes of human eye resolving power (in minutes of arc not DPI|millimeters) and cognitive "line tracking" (think narrow newspaper columns). I.e., they are from the perspective of device manufacturers / producers not receiving brains / consumers. At least in theory, the former is trying to please the latter after all, but eyes/brains haven't really evolved much in this respect since antiquity / the dawn of writing. This is just a pet peeve of mine that maybe you share, and clearly in the realm of 2x..4x not few% and so not on track with your question like the article I linked :-) TLDR - while a "standard viewing distance" is good enough for eye charts, I guess it's too complicated for "marketing hardware" and it's all too easy to get caught up in manufacturer framing.

cb321··on Python 3.14 is here. How fast is it?
Even better, in Nim these little CLI tools could use https://github.com/c-blake/cligen and have had terminal colorized, auto-generated help for many years now with much less dev-effort than raw argparse. Start-up time of statically linked Nim programs is like O(100..500 microseconds, just like C programs).
cb321··on No_color: Disabling ANSI color output by default
> do the right thing by checking if the standard output is an actual tty (isatty)

This is a very questionable heuristic. I'm not sure the exact date that support began, but I have been piping color output to `less -r/-R` for decades. This can be nice even for less than multi-terminal-page output just for "search".

isatty(stderr) would actually be more accurate for my specific use cases for when I don't `|&` or maybe even `isatty(stdin)`, but those are also imperfect heuristics.

The point is, since "auto" is a questionable heuristic, it is not so crazy/wrong to just default to color-on and have an off switch and that off switch is what NO_COLOR is about (as explained by the very first sentence in the linked article). Desirable defaults ultimately depend upon the distribution of your user's tastes (as always, more|less).

cb321··on A comparison of Ada and Rust, using solutions to the Advent of Code
Nim (https://nim-lang.org), mentioned elsethread Re: numeric ranges like Ada, only needs a library for this: https://github.com/SciNim/Unchained

FWIW, physical dimensions like meters were the original apples-to-oranges type system that pre-dates all modern notions of things beyond arithmetic. I'm a little surprised it wasn't added to early FORTRAN. In a different timeline, maybe. :)

I think what is in "the" "stdlib" or not is a tricky question. For most general/general purpose languages, it can be pretty hard to know even the probability distribution of use cases. So, it's important to keep multiple/broad perspectives in mind as your "I may be biased" disclaimer. I don't like the modern (well, it kind of started with CTAN where the micros seemed meant more for copy-paste and then CPAN where it was not meant for that) trend toward dozens to hundreds of micro-dependencies, either, though. I think Python, Node/JS, and Rust are all known for this.

cb321··on Zig builds are getting faster
I use tcc with Nim all the time and it yields almost interpreted REPL-like code-iteration speed (like 100-500ms per compile-link - almost ENTER-see-results).

As a warning, you need to be sure --lineDir=off in your nim.cfg or config.nims (to side-step the infinite loop mentioned in https://github.com/nim-lang/Nim/pull/23488). You may also need to --tlsEmulation=on if you do threads and you may want to --passL=-lm.

tcc itself is quite fast. Faster for me than a Perl5 interpreter start-up for me (with both on trivial files). E.g., on an i7-1370P:

    tim "tcc -run /t/true.c" "/bin/perl</n"
    58.7 +- 1.3 μs  (AlreadySubtracted)Overhead
    437 +- 14 μs    tcc -run /t/true.c
    589 +- 10 μs    /bin/perl</n
{ EDIT: /n -> /dev/null and true.c is just "int main(int ac,char*av){return 0;}". }
cb321··on Python with braces. Because Python is awesome, but whitespace is awful
I actually noticed that other comment you mentioned and almost said something at that time. The style is just not mentioned much and Python is about 1000x more well known than other offside-rule PLangs like Haskell. There are also enough exceptions, in Nim at least, that a true bracy fan would have at least some disappointments here & there.

In general Nim's syntax affords much, much more choice than Python, from UFCS to user-defined operators to macros to term re-writing macros to etc., etc. It's really a step up from Python in so many ways with a lot of compile-time checking and safety and essentially the same perf as C++. It's a shame it's not a little more popular.

← PreviousPage 3 of 29Next →