HNHacker News
TopNewBestAskShowJobs

cben

68 karma · joined August 31, 2008

Long-time pythoneer. Created mathdown.net (collaborative markdown with math). Live in Israel. github.com/cben, gitlab.com/cben, beni.cherniavsky@gmail.com

[ my public key: https://keybase.io/cben; my proof: https://keybase.io/cben/sigs/JGI5fI4zkb-2MZpVugiAm-7WyT2s9AWqqNtSYT5QTIg ]

submissionscomments
cben··on Anecdotally, programmers dislike "reduce"
Ruby's `[1, 2, 3].inject(:+)` alias for `reduce` (name borrowed from Smalltalk) nicely reinforces that very mnemonic: you inject the operator _between_ the elements: 1 + 2 + 3. :+ here is symbol meaning "send + message", more general form takes a block:

    [1, 2, 3].inject { |a,b| a + b }
The downside of the "between" mnemonic is encouraging not handling an empty collection! Ruby's separate syntax to pass (args) {block} at least offers natural place to add initial value, but with symbol shorthand the API is harder to guess:

    numbers.inject(0) { |a,b| a + b }
    numbers.inject(0, :+)
(Also, it's always a left fold ((a) OP b) OP c, even if you give a symbol like :* which parses right-assiciative without parens — making the "inject operator between values" mental model less accurate.)
cben··on Intrusive linked lists (2019)
> benefits of abstracting and separating node types from payloads

If you mean being able to a generic `list<foo>` type (whether by C++ templates, macros, or good old void* casts), it's more than that. The benefit of non-intrusive is being able to create/manipulate/pass around multiple collections pointing to same payloads, without disturbing the payloads or the other collections in any way¹. That makes it easier to return and manipulate collections functionally (both in the narrow immutable sense, but also in the wider "treat collections like _values_ sense)... The deepest benefit arising from that I suppose is code modularity: different code areas need not be aware of each other's existence.

That all obviously comes at some tradeoff to performance. By definition, not having a full picture of the pathways your data travels means you can't choose the fastest representation!

¹The cheat is GC. For multiple unconnected collections to point to same payload, you need ref counting, or mark&sweep or similar to control its lifetime. Technically, GC does disturb the objects it's tracking (though that's well abstracted from other code).

However, you're largely right that specifically linked lists are rarely a good choice for non-intrusive collections => Arrays usually beat them, and if not then hash sets. (LISP & ML & Haskell do stick to lists for tail sharing — a choice which is arguably outdated by growing CPU / mem random access gap. I suppose Clojure's persistent vectors are an improvement.)

cben··on “Code was never the hard part” is an insult to all programmers
I'm not american, and didn't follow that one deeply, but presumably that's not just "due to bad req. gathering", it's also due to the structure of gov procurement? E.g. it wasn't the pained users who approve the payment to the contractors, right?

You could counter "if only performance was legally included in the contracts, a better site would be delivered." Maybe, but my point is there is big difference between internal "req. gathering" that informs work while everyone is long-term motivated for good user experience anyway, vs. external contract/deadline gathering for almost adversarial "deliver worst thing that passes and walk away" settings. Brushing both under same wording feels insufficient to me.

cben··on “Code was never the hard part” is an insult to all programmers
That's just one half of it: Intelligent defaults + configurability of what files/dirs to skip. That part has been iterated on in prior tools like `ack` and `ag` and `git grep` for like a decade, and ripgrep was informed by that tradition.

The other part is extreme optimizations, from I/O and OS aspects to CPU, both asymptotic complexity (from scratch NFA regex engine), concrete complexity (rust, SIMD) and ad-hoc opitimizations for statistically common uses like fixed strings...

Then there are some "product" choices driven by performance insights, e.g. no line numbering, defaulting to non-deterministic unsorted output order — these go against most programmers' intuition for "ideal tool I'd like", but turns out the speed gains are significant and what I really like is how fast it is :-)

Both usability & optimizations are described in depth by the author in https://burntsushi.net/ripgrep/, which is one of the best perf. readings ever, highly recommended.

cben··on User Interfaces of the Demo Scene
Also in Russian
cben··on An entire Herculaneum scroll has been read for the first time
This is a stunning achievement for many reasons! Having been born in USSR, a particular reason it moves me to tears how this vindicates Bulgakov's famous "manuscripts don't burn", which he presented as a plain metaphysical fact:

"Unfortunately I cannot show it to you," replied the master, "because I burned it in my stove."

"I'm sorry but I don't believe you," said Woland. "You can't have done. Manuscripts don't burn." He turned to his cat. "Come on, Behemoth, let us have the novel."

– towards the end of The Master and Margarita. In the battle against both censorship & entropy, recovering a 2kyo text which was considered forever lost is an incredible victory.

cben··on Ask HN: Am I getting old, or is working with AI juniors becoming a nightmare?
I know how to use a slide rule, but only because my grandpa taught me. He was an electrical engineer with serious mastery of analogue circuits and relays, and a passion to explain; but he never really grasped what my father was doing as digital chip engineer + programmer... My father gave me a great start on Unix, C & Perl. And I haven't managed to teach my children nearly as much code as I hoped (some Scratch/Snap! and python lists but not dicts yet), and they're already beginning to "but what for, AI..."

P.S. I'm reminded of the short story "My Father's Singularity" (https://clarkesworldmagazine.com/cooper_06_10/) wrt. the gradual way change accumulates until a significant gap has grown.

cben··on I shipped a transaction bug, so I built a linter
Great walkthrough teaching how to DIY a Go AST linter, thanks
cben··on Conway's Game of Life, in real life
Aliexpress has a lot of cheap "smart gomoku board" now, they are cheap rgb-lighted membrane button grids O(13x13) with firmware playing games like Go, Reversi etc. (https://he.aliexpress.com/item/1005010089221164.html, https://he.aliexpress.com/item/1005011840606955.html ...). These proved to be surprisingly fun with children, the tactile interface is neat, and they're a good middle ground that helps learn the rules of games (has 1-on-1 modes + solo against several levels of "AI") but not as brain-rot distracting like a tablet.

I haven't tried reverse-engineering one yet, I hope at least some of these are hackable? Conway's life would certainly be one fun use, but custom games are totally something I'd want to make too!

Are these actually membrane or are there some switches there? I assume membrane, if only based on the dirt-cheap price. Anyway in combination with lighting up + sound the feedback feels immersive enough, it's definitely more fun than poking a tablet.

cben··on Doom has been ported to an earbud
Caveat to those considering buying PineBuds for "open source firmware": OOTB they come with fully working but proprietary firmware (part source-available SDK, part closed). The hardware is not 100% documented. There is open firmware they can run, but for example ANC has not been replicated yet, at least not well (and personally I love the ANC enough that I kept the factory firmware)-:

- Pine64's general model is selling cheap, quite-good, not-fully-documented hardware with expectation community software will(?) grow around it. Some of their products grow fantastic support, some less so, some remain "dev kit" — do your homework.

cben··on Package managers keep using Git as a database, it never works out
That's not how I understood it. Full clones are big but simple — the server just sends all the packfiles. A first shallow clone needs some server work, but that's cachable, OK.

But then on subsequent interactions between a git client that made a shallow clone various time ago and the git server, it's AFAIU actually expensive for the git server to compute the portion this particular client doesn't yet have.

Intuitively, and very hand-wavingly, I suspect things could be improved by:

(1) clients relaxing "exact depth" requests to "give me approximately N days of stuff, over-sending being OK", and server relaxing "minimal traffic" to roughly map time ranges to whole packfiles — CPU/traffic tradeoff. (2) allowing servers to under-send too (makes (1) tradeoffs easier), by client asking for missing parts right away and/or later — needs on-demand fetch ability to be transparent to user. With "promisor" mechanism in "partial clones" this sounds more realistic? (3) storing history/trees/blobs in entirely separate packfiles(?) I suspect recent years work on bitmaps & MIDX move in this direction, only less naively?

I'm not saying Git can scale as well as a DB, but I do feel we sat on an effectively frozen Git format & protocol for a ~decade, and are now exploring more of the design space so hope future will be less clear-cut...

And specifically, partial clones remove the hard "fully offline vs. centralized" dichotomy we long clinged to. Assuming you stay online (necessary anyway if you consider HTTP/DB), things that used to be up-front UX decisions can now be matters of perf tuning!

* The most dramatic win is if you had to fetch info from every package's separate repo, like Go did. Then, a central DB/caching proxy can build global indexes, unlocking huge wins, no question. It's like "1+N" issues. However, most examples other than Go in the article talk of a single Git repo already storing a global view (still leaving opportunity for custom indexing and querying).

cben··on Package managers keep using Git as a database, it never works out
Obligatory link to the gold intro to So. Many. Aspects. of pkg manager design: https://medium.com/@sdboyer/so-you-want-to-write-a-package-m... Even if its section on "Central Package Registry" isn't very deep.
cben··on Ask HN: What are the best engineering blogs with real-world depth?
Totally. She has a fearless approach to learning complex topics (my favourite quote is simply "Computers are knowable", though I couldn't find it — I think she said it on some podcast?) that doesn't shy away from acknowledging ways in which stuff is genuinely hard (e.g. https://jvns.ca/blog/2024/03/22/the-current-branch-in-git/ is among the best usability/learnability dissections I've seen).
cben··on Are we stuck with the same Desktop UX forever? [video]
Computers are not a kitchen. They are clay, they are Lego, they are jungles of imagination. It's true that our current trajectory devolves their universality to a set of discrete isolated applications == multiplexing a set of appliances on one device.

That's an economic win sure, but it's tragic if we fail to unlock more of their flexibility for "end users"! IMHO that's the biggest unsolved problems of computer science: that it takes so much professional learning to unlock the real potential (and even that fails us programmers much of the time! How frequently do you say "I'll solve it myself" and the time invested is actually worth it? In the words of Steve Krouse we've not quite solved "End-programmer Programming" yet.)

I do want FOSS to follow through and offer live inspectors for everything, but no, I no longer believe users should "learn to code" as the salvation. We're nowhere near it being worth their time, we actually went downhill on that :-( Conversational AI and "vibe using" will play a role, but that's more like "adversarial interoperability", doesn't cover what I mean either.

I want cross-app interoperability to be designed in, as something everyone'd understand users want. I want agency over app state — snapshot, fork, rewind, diff etc. I want files back (https://jenson.org/files/), and more¹. I want things like versioning and collaboration to work cross-app. I want ideas and metaphors we haven't found yet — I mean it when I call it unsolved problem of CS! — that would unlock more flexible workflows for users, with less learning curve. The URL was one such idea - unlocking so much coordination by being able to share place[+state] in any medium.

I want software to be malleable (https://malleable.systems/) in ways meaningful to users. I want all apps to expose their command set for OS-level configurability of input devices & keyboard shortcuts (Steam Input on steroids). I want breakthroughs on separating "business logic" from all the shit we piled, so users can "view source" and intervene on important stuff, like they can in spreadsheets. (I want orders of magnitude smaller/simpler shit too.) I want the equivalent of unix pipes combinatorial freedom² in GUI apps. I want universal metaphors for automation, a future not unlike Yahoo Pipes promised us (https://retool.com/pipes) though I don't know in what shape. I want previewable "vector actions", less like record-macro-and-pray-the-loop-works more like multiple cursor editing. I want more apps to expose UX like PhotoShop layers, where users are more productive manipulating a recipe than they'd be directly manipulating the final result. (https://graphite.art/ looks promising but that's again for visual stuff; we need more universal metaphors for "reactive" editing... I want an spreadsheet-like interface to any directory+Makefile. I want ability to include "formulas" everywhere³.) I want various ideas from Subtext (https://www.subtext-lang.org/retrospective.html).

I want user access to the fruits of 100% reproducibility, including full control of software versions (which are presently reserved to VM/Docker/Nix masters). I want universal visibility into app behavior — what it accessed, what it changed on your computer/the world, everything it logged. Ad blockers actually achieve 2 ways to inspect/intervene: starting from the UI (I don't want to see this), and starting from network behavior (I don't want it to contact this), and both give users meaningful agency!

¹ I highly recommend following https://alexanderobenauer.com/ for his "Itemized OS" research ideas. His shared work with Ink & Switch https://www.inkandswitch.com/embark/ is a tantalizing demo too. ² http://conal.net/blog/posts/tangible-functional-programming-... was intriGUIng but still too nerdy for fitting naturally into end-user workflows. (But if you like such nerdy, https://www.tandisgame.com/ is somewhat related & fun) ³ https://calca.io/, https://worrydream.com/ExplorableExplanations/

cben··on The Mac calculator's original design came from letting Steve play with menus
I'm not sure of the timing (and whether you're sarcastic) but yeah, I found it funny compared to PARC showing Steve Jobs how the Smalltalk environment allowing modifying GUI behavior at run-time let them iterate quickly, sometimes in front of users (https://www.youtube.com/watch?v=uknEhXyZgsg&lc=UgwYCZ7PefOXO...).

I guess https://www.folklore.org/Calculator_Construction_Set.html is the closest you get with a compiled language :-)

P.S. https://web.stanford.edu/dept/SUL/sites/mac/parc.html has good historical context on that visit(s)

cben··on Ask HN: How would you set up a child’s first Linux computer?
I disagree. Assuming it's their own device, set up automated backup, but let them trash the OS. PCs/laptops are (still) pretty much un-brickable at software level. If they do, re-installing & fishing around the backup will be a learning experience, and the fact you trusted them "this is YOUR device" will be a positive ownership experience that is getting rare nowdays...

* Linux live USBs can be a nice safe intro to such power? Give them 2-3 with differnt-looking distros (even if cosmetic ;-), tell them "try this for a day, if you decide which one you like it you can install it permanently". Hmm, I should try this with my kids!

cben··on Ask HN: How would you set up a child’s first Linux computer?
[Python is great; my comment is only within block-based languages] For those actively teaching¹, consider Snap! (https://snap.berkeley.edu/) over/after Scratch. It's nearly a superset, similarly "low-floor" but much "higher ceiling" powerful language.

Data structures, control structures/message passing, functional programming... It's really "Scheme in Scratch clothing" under the hood.

In particular, its "build your own blocks" facilities are powerful enough (including macros i.e. custom control structures receiving "body" arguments as unevaluated lambdas) for you to build any scaffolding they need to focus on concepts you want them to learn at this stage.

¹If you don't have much time to sit with them, Scratch may win on "go find tutorials on youtube".

cben··on Ruby and Its Neighbors: Smalltalk
https://criu.org/ (Checkpoint/Restore In Userspace) is a long-running project (i remember the name over a decade ago) worth checking... Ooh, looks like they made progress in conveniently connecting it to containers.
cben··on Two Slice, a font that's only 2px tall
PICO-8 code editor uses one I think.
cben··on Dropbox Paper mobile App Discontinuation
Conversely, when you already collaborate with people in Dropbox, mainly via files, having real time co-editable docs under same folder with same sharing was nice, esp. for people who never remember where they put stuff :-)

Integration was not perfect, but it does create a json .paper file containing a url. But at least it makes you aware the doc exists every time you look at the folder.

Alas, with Paper desktop & mobile apps being deprecated, that's increasingly useless :-( Will the main app at least take over the ability to [double-]click these .paper docs to open them in a browser?

cben··on Raspberry Pi 500 Review: The keyboard is the computer, again
Radxa X4 board specifically has x86 N100, an M.2 slot (a short one) and GPIO (though you need to flash the on-board RP2040 to access them? haven't tried yet). I'm quite happy with it as a cheap desktop. Documentation is pretty OK? Nowhere like the tutorials ecosystem around RPi but Radxa are certainly trying to provide detailed info.

One sweet quality of RPi this lacks was being unbrickable — the entire state was on SD card; screw up and you can just write a new card. (Recent RPis complicate that with an a boot flash). But by now I've bricked enough RPis by electrical damage — including an 400 — to not be as excited about that :-]

I do agree with your analysis. All I'm saying is if one is considering a competitor, the X4 with x86 running mainline linux might be a safer bet than most less-documented ARM boards...

cben··on Ask HN: Platform for 11 year old to create video games?
I upgraded my son from Scratch to Snap! (https://snap.berkeley.edu/). Snap has a much higher ceiling, including collections, first-class code pieces, higher-order functions etc. It pretty openly describes itself as a "Scheme disguised as Scratch" :-)

A pragmatic pedagogical thing I love with Snap! is the ease of creating custom blocks, including macros / custom "C-shaped" control structures. If you have some time, this allows you to "scaffold" helpers that will allow him to create interesting stuff while focusing on things you want him to learn and hiding issues you don't.

* Example: I wanted to teach rendering a custom costume with e.g. health bar or text label. My son is already familiar with Snap!'s turtle-drawing primitives that can render lines & text but there was an impedance mismatch — you draw on the screen, and it does support snapshotting all current drawings to create a costume, but using that involves some careful save-and-restore of much global state (e.g. pen color). I built him a "draw costume" block that takes a body of turtle-drawing commands and affects only current character's costume. If you ask me, Snap! should have had similar API built-in; but what's more important it was easy for me to add one that looks and feels as-if it was builtin. This way I can decide what I want to teach ("you can compute how you appear") and what is incidental complexity.

cben··on Ask HN: Did you regret staying at a job for too long?
I regret not seeking internal transfer within my last employer. I "followed the flow" there for 8 years. Couple years ago I got less happy with project and passively talked with manager about "maybe switching projects in future" — yet stayed on out of laziness and liking the team. The point of no return was when manager/team started being unsatisfied with my performance too.

In retrospect, me unhappy + them unhappy = time to actively seek moving (which they'd still support back then); I stayed into a spiral of feedback => motivation => productivity => ... eventually I was laid off. I can't know how moving would have worked out but I regret not trying. [OT: and other passivity, not taking feedback seriously enough, sticking to WFH despite evidence it was challenging for me.]

cben··on Using Fibonacci numbers to convert from miles to kilometers and vice versa
You could add "without using multiplication or division" as a less arbitrary constraint. Early microprocessors (and some really cheap microcontrollers still) didn't have the circuitry.

That said a fixed-factor mutiplication can probably be done faster AND [more] precisely as a sum of some shifts. Or many other ways with a lookup table.

cben··on Using Fibonacci numbers to convert from miles to kilometers and vice versa
I learnt this from Concrete Mathematics (Graham, Knuth, Patashnik). Don't remember if main text or the side notes of accumulated student wisdom... (I dont mean on my copy, this textbook is _printed_ with tons of amusing/insightful side notes)

They also mention _approximate_ cm/inch conversion is doable by double shift on the Fibonacci scale - if golden ratio was exactly 1.6, its square would be 2.56, but actual phi² = 2.618 which is quite bad approximation for 2.54...

cben··on Entering text in the terminal is complicated
Ctrl+T does transpose-characters (and Alt+T transpose-words) in Emacs. I assume it's not a coincidencce, I see tcsh has `bindkey -e` / `-v` for Emacs/VI bindings. Same keys work in bash too (and anything else that uses readline) and fish too (independent editing implementation).
cben··on The Software Crisis
Some projects in a similar space: https://hisham.hm/userland/ https://arcan-fe.com/2021/04/12/introducing-pipeworld/ http://conal.net/papers/Eros/
cben··on Local First, Forever
I wish apps that open a document for editing would embed some kind of p2p "signalling" (webrtc or otherwise) in or near the file to bootstrap more real-time collaboration. That could be magic because it'd kick in IFF the file happens to be shared (by dropbox or similar) AND somebody else has it open for editing at same time...
cben··on Show HN: Shpool, a Lightweight Tmux Alternative
What benefit would you get if tmux itself became a control mode client?

You'd get pretty much same experience, with textual splits, modeful keyboard shortcuts to access scrollback & copy/paste etc. — which I'm not saying is bad but tmux already does that. Well, I suppose over ssh it'd allow you to access remote tmux session(s) from a local tmux, so maybe allowing little more flexibility mixing panes from multiple remote hosts(?) But still pretty much similar.

The whole point of control protocol was to allow native [G]UI where each pane feels like a native standalone terminal, no?

cben··on Alan Kay's talk at UCLA – Feb 2024 [video]
It's curious how the original 1981 paper [1] on TECO Emacs, written before I was born, describes many qualities I recognize in the ELisp Emacs I grew up on.

Emacs "happens" to be open source ;-), but the paper stresses how the system & language were designed to allow users to mold it at run time without the barrier of recompiling from source, and how empowering users led to better features than "careful design" could have achieved. Selected points I found notable:

- awareness that "An EMACS system actually implements two different languages, the editing language and the programming language". - Editing Language is tweakable (again at run time) by re-binding keys to macros / existing commands / custom commands. This gives agency to users with less programming skill! - Language separation being necessary so that tweaking Editing Language can't break Programming code. - Key bindings are shallow "keyboard sugar" over the concepts of Programming Language. Commands are (almost) regular functions. User can invoke any command by name, bypassing the sugar. - Buffer-local & mode-local bindings. - Commands (and generally as much of the system as possible) implemented in Programming Language which was chosen to be interpreted not compiled, so that users can redefine at run-time and experiment. - "The only way to implement an extensible system using an unsuitable language, is to write an interpreter for a suitable language and then use that one" :-D - "variable [and function] names are retained at run time; they are not lost in compilation"

- Commands are extensively parametrized by variables. User can achieve quite a lot by simply setting [global] variables. - Dynamic not lexical scoping deliberately choosen to make code less encapsulated and more reusable with tweaks. See paper why lexical is worse for dynamic - Unique concept of File/buffer-local variables! Again, if programmer went to the trouble of parametrizing code, maximize the payoff. - Commands and especially compiled code extensively parameterized by calling "Hooks" at interesting points. "These hooks can be thought of as compensating for the fact that some parts of the system are written in assembler language and cannot simply be redefined by the user." <<-- I found this especially thoughtful

- Social dynamics like "library system" for loading extensions written by others. Well, ater Emacs actually lagged behind for decades in ease of obtaining 3rd-party libraries. "too cathedral, not enough bazaar..." Much better now with MELPA, still not as smooth as say VSCode extensions. But I feel a trade-off — VSCode extensions are more "opaque".

[1] https://www.gnu.org/software/emacs/emacs-paper.html

Page 1 of 8Next →