HN user

jasone

617 karma
Posts6
Comments114
View on HN

The C47/R47 appears to use the 4-level XYZT stack design by default, but it has an option to use an 8-level stack (XYZTABCD). I really like the unlimited stack option that can be enabled in Free42, but 8 levels might be enough to keep from feeling cramped in practice.

The former merely exposes a `BlogPostRepository` class. The latter requires some mechanism for creating a generic object of concrete type, which is a lot bigger change to the implementation. Does each parametrized generic type have its own implementation? Or does each object have sufficient RTTI to dynamically dispatch? And what are the implications for module API data structures? Etc. In other words, this limitation avoids tremendously disruptive implementation impacts. Not pretty, but we're talking PHP here anyway. ;-)

The addition of infinite pages made my RM2 unusable. It's far too easy to accidentally scroll, and hugely disruptive. I checked for tuning improvements for a couple of software updates, then set it aside permanently. That such a "simple" change could doom the device made me decide to go back to real paper, in all likelihood forever.

Hard disagree. Yacc has unnecessary footguns, in particular the fallout from using LALR(1), but more modern parser generators like bison provide LR(1) and IELR(1). Hand-rolled recursive descent parsers as well as parser combinators can easily obscure implicit resolution of grammar ambiguities. A good LR(1) parser generator enables a level of grammar consistency that is very difficult to achieve otherwise.

This is an interesting read. As a software engineer who accidentally discovered the depth of Scrabble in middle age, I fell down a slightly different Scrabble rabbit hole. The probabilities behind the imperfect bag/rack state knowledge fascinate me, and I spent most of a year writing a strong Scrabble engine to explore the problem. I've put that aside for now, but it remains a background pressure on the computing problems I tackle.

I've spent a lot of time over the years using bit shifting to multiply/divide by powers of 2 in low-level code. At some point I grokked the connection with (base 2) logarithms and found myself using them as a mental estimation tool with surprising effectiveness.

Many of us programmers have powers of 2 memorized through at least 2^20 (and 2^10 ~= 1000 is close enough for decomposing and converting larger values), which makes rough conversion to/from the log domain trivial. The trick in estimation is to round to the nearest whole number when converting to the log domain, and try to alternate rounding direction for inputs that are not close to the upper/lower extrema. Keep a running total of the log-domain value as a whole value, and take the antilog as the final step. Given these simple rules, most estimates come within a factor of 2 of the intended value, and with minimal cognitive load. All you need to remember is the current sum and which direction to round the next input.

As an Idaho resident, I dearly hope not. And I'd be really surprised if such legislation did pass. Toxic extreme-right rhetoric appeals to a nontrivial proportion of Idahoans, and some politicians are pandering to the fringe of society that wants to see everything burn. But my rough estimate is that only 20-25% of Idahoans think that way.

There are often situations in which the rational approach is to upstream enhancements, if only because it reduces ongoing maintenance of a derivative product. This is especially true of foundational infrastructure. BSD/MIT-like licensing works well for such software (perhaps less well in general).

jemalloc does not assume a particular page size; it configures page size at build time. By default the configured page size is the actual page size (usually 4KiB), but optionally it's some power-of-two multiple of the actual page size. In the early days of jemalloc the page size was queried at startup rather than burned into the binary, but that dynamic flexibility was never of any use in practice, and it inhibited compiler optimizations.

This was the idea that I kicked around for years before eventually writing a Scrabble engine in 2018. But by the time I got to the point where Monte Carlo simulation of the opponent's rack leave became feasible, I questioned the utility. Part of the problem is that if your opponent knows you incorporate such a simulation into the analysis, it's possible to subvert the analysis. And the most obvious counter is to not do the simulation. Another issue is that the advantage gained by opponent rack leave simulation is subtle, and it's costly to run enough games to measure the overall utility. I ended up instead putting my effort into controlling search depth termination with uncertainty estimation (spend more time on the portions of the tree that are more volatile).

I got sucked into a variant of Scrabble insanity. In 2018 I spent close to six months writing a Scrabble engine, initially as an exercise to learn OCaml. But the algorithmic challenges pulled me deep down a fascinating rabbit hole. Eventually I was recording IRL games with my wife so I could analyze the positions, trying to understand why/how to exchange more often, and trying to make the engine ever stronger. It still lacks an end-game mode (where perfect play is possible due to empty letter bag), but by the time I put it aside, it appeared to be at least as strong as Quackle. (Fair comparison is hard since more CPU time allows deeper analysis.)

It's a project I hope to go back to someday, and maybe follow up on some of the human-like play options and variants I came up with along the way. The tournament word list is proprietary and at the time there were apparently no reasonable licensing options (licensing has since improved), which put a damper on releasing my engine.

Dune (https://dune.build/) is the preeminent build tool for OCaml development. I don't love its input syntax (s-expressions), and I sometimes miss the ability to write high-level functions to reduce boilerplate (especially for unit tests), but it always gets the dependencies right, and it's fast. This is in stark contrast to some of my experiences with various other build systems, and I am super happy that the default option for OCaml build systems is so good.

Minor nit: In a language like Erlang, function calls (including tail recursion) are instrumented to implement things like preemption, GC, and statistics updates. But loops (backward branches) can just as easily be instrumented, and various imperative language runtimes do so.

Erlang is somewhat unusual among contemporaries in how it multiplexes actors onto system threads. This has historically been quite difficult to get 100% right because even if you manage to make all system calls non-blocking (e.g. TCP socket I/O), "non-blocking" disk I/O can still stall computation for a relative eon. I'm pretty excited about io_uring because it provides a general solution to this problem.

Around 1993 I had my tonsils out, which involved general anesthesia. Back then they administered a prep drug that put the patient in a weird dissociated awake state that I would describe as not realizing you're awake. This being my third time through the process (knee surgery, wisdom teeth, now tonsils), I tried really hard to maintain self awareness.

We'll, it sorta worked. In this state I somehow recognized that the device placed on my fingertip must be a blood sensor of some sort, and that squeezing my finger might mess with the readings. I made it through two rounds of setting off alarms before the nurses caught me. I was immensely pleased with myself!

Even better IMO is to use different prefixes for outer vs inner tmux sessions. These are the first lines of my .tmux.conf:

    # Use C-a for outer sessions, and C-x for nested sessions.
    unbind-key C-b
    set-option -g prefix C-a
    bind-key -n C-x send-prefix

I used screen for about a decade before switching to tmux. The biggest immediate benefit was that terminal configuration across systems was much less brittle. My backspace key backspaced, color consistently worked, etc. Over the past 10+ years of tmux use I've become increasingly more sophisticated in my usage (in particular 1) nested tmux sessions, 2) heavy use of the kakoune text editor's tmux integration), yet my .tmux.conf file has all of 15 lines of content. One other thing: tmux has yet to crash on me, but screen certainly did so numerous times.

These are books that I've reread major portions of repeatedly because they consistently trigger broader thinking about their subject matter.

Purely Functional Data Structures by Chris Okasaki broadened how I think about algorithmic complexity analysis, after decades of mostly imperative programming. Other books on lambda calculus, type theory, OCaml, Haskell, etc. preceded this in my reading list, but this book clinched my love of functional programming.

The Garbage Collection Handbook by Richard Jones, Antony Hosking, and Eliot Moss provides broad, yet sufficiently detailed, coverage of automatic memory management that most techniques can be understood and implemented without digging into the primary literature. That said, this book (actually its predecessor, Garbage Collection by Jones and Lins) inspired me to dig deep into memory management, and jemalloc is one of the incidental results.

I really don't care if my code gets ingested and regurgitated by Copilot, but it seems rather a stretch to imagine that this is fair use, in part because it separates me from the legal protections afforded by the licenses I released my software under. In my ideal world, Copilot would be legally viable, and releasing my software without restriction wouldn't be risky.

As a long-time open source software developer, I have favored the 2-clause BSD and MIT licenses because they are the simplest licenses that provide me some liability protection. I would release code into the public domain if that didn't increase the likelihood of being sued, whether for liability, or for someone else claiming intellectual rights to code I actually wrote.

The brain doesn't engage in the same process when presented with translated subtitles, to such an extent that you're better off watching a familiar show with no subtitles. However it can be helpful to have same-language closed captioning to improve distinction of word boundaries, accents, etc. Netflix has been great in recent years for this, in my case watching German-language shows.