Weeknotes 2024 W45: Open

November 4​–​10, 2024
1900 words

Quick bits:


Shower thoughts:


I am in the process of writing an article titled “The intricacies of implementing memoization in Ruby.”

I’m making good progress on it. The first draft is nearing completion; I have maybe three hundred words left to write. I’m hoping for the article to be ready for publication coming weekend, but that is probably optimistic.

Are there good places (besides my personal blog) to publish articles related to Ruby?


This is the first time that I am writing an article with Scrivener rather than DMark. I’m rather pleased with the setup. But Scrivener is not perfect, and I keep thinking about better ways of writing.

I write my stuff in Markdown in Scrivener, and it feels just a little awkward. I use Scrivener styles for marking up pieces of text,2 but the abstraction is leaky: being able to use Scrivener styles and raw Markdown markup sometimes leads to incorrect Markdown and missing escape sequences.

I also think that Markdown itself is inadequate as a format for technical writing. It’s better in some Markdown dialects (like pandoc’s) but then there’s the issue of Markdown dialects not being portable. Purely from a markup perspective, I much prefer DMark.

Once again, I am thinking about writing my own editor. I greatly value semantic markup, so I’d love to have a way to mark up text, whether fiction or non-fiction, as a node graph that can be translated into various formats like Markdown, HTML, (La)TeX, and DocBook. In many ways, this is why I created DMark.

Perhaps it is time to experiment with ProseMirror and try to whip up a prototype. I think it’d be neat to have an editor for a DMark-like markup language with a visual representation, not unlike how Bear uses markup that gets automatically hidden. In any case, onto the Ideas page it goes.


I quite like Lu Wilson’s talk What it means to be open given at Heart of Clojure 2024.

I like working in the open. I already do that to an extent: my week­notes are a prime example of that.

But there is also a lot that I work on behind closed doors:

Still, I’d like to create more stuff in the open. I’d love to publish stuff that is woefully unfinished, feature-incomplete, buggy, undocumented, scrappy af. The biggest hurdle I am facing here is, most likely, a psychological one.


I hit a particularly weird bug in my Ruby code the other day. Take a look at the following:

p 100
p [100, 200]
p [100, 200, 300]

In Ruby, the #p method debug-prints the given argument. (Parentheses are optional.) This, as you could expect, yields the following output:

100
[100, 200]
[100, 200, 300]

Everything is normal so far. But in my particular case, the output that I got was quite different from what I expected:

100
sample.rb:15:in `[]': wrong number of arguments (given 3, expected 1..2) (ArgumentError)

To clarify:

  1. The first line debug-prints the argument as usual. (This is good and expected.)

  2. The second line does nothing.

  3. The third line throws a bizarre ArgumentError.

It turns out that this happens when p is reassigned to a local variable, e.g. p = 300. The second and third lines (with the square brackets) are then treated as calls to the #[] method, i.e. p[100, 200] and p[100, 200, 300], respectively. The first line is still treated as a method call to #p.

So, p is treated differently depending on the shape of the expression, and whether or not there is a (local) variable named p.

This is easy to verify by looking at the parse tree.5 Here is the parse tree for p 100:

s(:send, nil, :p,
  s(:int, 100))

Nothing unusual: this calls #p with the argument 100.

Parsing p [100] yields the following:

s(:send, nil, :p,
  s(:array,
    s(:int, 100)))

Also nothing unusual here: this calls #p with the argument [100].

But it gets very different when first assigning a value to a local variable p. Here is what p = 300; p [100] parses as:

s(:begin,
  s(:lvasgn, :p,
    s(:int, 300)),
  s(:send,
    s(:lvar, :p), :[],
    s(:int, 100)))

Despite having over 17 years of experience with Ruby, I had never bumped into a situation like this.6 Wild!

And yes, Integer#[] can be called with one integer as an argument (a bit offset) or two arguments (a bit offset and a bit slice size). This is why p [100, 200] did “nothing:” it didn’t print anything, but silently returned a slice of bits.


Entertainment:


Tweets and toots:

Politics links:

Entertainment links:

Silly links:

Tech links:

Miscellaneous inks:


  1. Better known as Kristallnacht (lit. “crystal night”) which is a term I don’t like: it is a euphemism (it’s not about the glass!) and misleading because the November pogroms happened during daylight too. ↩︎

  2. I wrote about this in Week­notes 2024 W41: Acquired taste↩︎

  3. This definitely applies to fiction. It might not apply to non-fiction, but I assume it does. I couldn’t find much about that; does anyone have experience here? ↩︎

  4. Back then, it was still a Subversion repository. Later, it got converted into a Mercurial repository, and finally converted into a Git repository. The repository predates the existence of GitHub, even. My web site existed even before that. It’s been a ride! ↩︎

  5. I am using whitequark/parser but this works just as well with Prism, too. ↩︎

  6. It has also never occurred to me to define a local variable named p. After all, doing that would prevent me from using p as a debug-print method. ↩︎

  7. Alan Wake II (Remedy Entertainment, 2023), published by Epic Games Publishing. ↩︎

  8. Shirley Jackson, We have always lived in the castle (London: Penguin, 2009). ↩︎

You can reply to this weeknotes entry by email. I’d love to hear your thoughts!
If you like what I write, stick your email address below and subscribe. I send out my weeknotes every Sunday morning. Alternatively, subscribe to the web feed.