Indexing In UCL

I’ve been thinking a little about how to support indexing in UCL, as in getting elements from a list or keyed values from a map.  There already exists an index builtin that does this, but I’m wondering if this can be, or even should be, supported in the language itself.

I’ve reserved . for this, and it’ll be relatively easy to make use of it to get map fields. But I do have some concerns with supporting list element dereferencing using square brackets. The big one being that if I were to use square brackets the same way that many other languages do, I suspect (although I haven’t confirmed) that it could lead to the parser treating them as two separate list literals. This is because the scanner ignores whitespace, and there’s no other syntactic indicators to separate arguments to proc calls, like commas:

echo $x[4]      --> echo $x [4]
echo [1 2 3][2] --> echo [1 2 3] [2]

So I’m not sure what to do here. I’d like to add support for . for map fields but it feels strange doing that just that and having nothing for list elements.

I can think of three ways to address this.

Do Nothing — the first option is easy: don’t add any new syntax to the language and just rely on the index builtin. TCL does with lindex, as does Lisp with nth, so I’ll be in good company here.

Use Only The Dot — the second option is to add support for the dot and not the square brackets. This is what the Go templating language does for keys of maps or structs fields. They also have an index builtin too, which will work with slice elements.

I’d probably do something similar but I may extend it to support index elements. Getting the value of a field would be what you’d expect, but to get the element of a list, the construct .(x) can be used:

echo $x.hello     \# returns the "hello" field
echo $x.(4)       \# returns the forth element of a list

One benefit of this could be that the .(x) construct would itself be a pipeline, meaning that string and calculated values could be used as well:

echo $x.("hello")
echo $x.($key)
echo $x.([1 2 3] | len)
echo $x.("hello" | toUpper)

I can probably get away with supporting this without changing the scanner or compromising the language design too much. It would be nice to add support for ditching the dot completely when using the parenthesis, a.la. BASIC, but I’d probably run into the same issues as with the square brackets if I did, so I think that’s out.

Use Parenthesis To Be Explicit — the last option is to use square brackets, and modify the grammar slightly to only allow the use of suffix expansion within parenthesis. That way, if you’d want to pass a list element as an argument, you have to use parenthesis:

echo ($x[4])       \# forth element of $x
echo $x[4]         \# $x, along with a list containing "4"

This is what you’d see in more functional languages like Elm and I think Haskell. I’ll have  see whether this could work with changes to the scanner and parser if I were to go with this option. I think it may be achievable, although I’m not sure how.

An alternative way might be to go the other way, and modify the grammar rules so that the square brackets would bind closer to the list, which would mean that separate arguments involving square brackets would need to be in parenthesis:

echo $x[4]         \# forth element of $x
echo $x ([4])      \# $x, along with a list containing "4"

Or I could modify the scanner to recognise whitespace characters and use that as a guide to determine whether square brackets following a value. At least one space means the square bracket represent a element suffix, and zero mean two separate values.

So that’s where I am at the moment. I guess it all comes down to what works best for the language as whole. I can live with option one but it would be nice to have the syntax. I rather not go with option three as I’d like to keep the parser simple (I rather not add to all the new-line complexities I’ve have already).

Option two would probably be the least compromising to the design as a whole, even if the aesthetics are a bit strange. I can probably get use to them though, and I do like the idea of index elements being pipelines themselves. I may give option two a try, and see how it goes.

Anyway, more on this later.

🔗 Goodbye to Apple’s Smart Keyboard Folio, the best iPad Pro accessory

I’ve never considered hoarding accessories before, but I might start. The Smart Keyboard Folio is perfect for how I use the iPad: a great stand and decent enough keyboard that doesn’t get in the way when I just want to read.

Free idea for anyone interested in making a mockumentary: a band that specialises in “Musak,” the type of music you hear in lifts or dental offices. They’re trying to make it to the big leagues — a well known department store, like a Myer or Macies — and they’re up against other bands getting better gigs, the Musak industry “big-wigs,” and their own shortcomings. Sort of like “Spinal Tap” meets the doctors waiting room.

It’s ironic to think that part of my job is to make sure that the nice artwork that I see on our 500 and 404 error pages are never seen by anyone else.

Ah, hello, my “is this article helpful?” popup friend, the ugly cousin of all the “please rate this experience” solicitations everyone seems to get. Oh, and I see you’re the super helpful one that covers up the very text I’m trying to read.

A HTML modal over prose with the prompt 'Is this article helpful?' with a 'Yes' and 'No' button

It’s always fascinating browsing the early methods and properties of the DOM. It feels a bit like an archeologist shifting through strata uncovering facts about some long lost civilisation. “Oh, they didn’t call them query parameters back then. Instead, they were known as search strings.”

One other skill I wish I had was good audio mastering skills. Been going through some more tapes last night and it would be so sweet to be able to remove the loud hiss some of them have. I know what I need to do in principal, but translating that into an FX chain in Logic Pro is where my gap lie.

Browsing some of the WeblogPoMo posts on Mastodon the past few days. A lot of great posts, plus some really talented web designers out there. Wish I had their artistic or web-design skills.

Of course I deployed something that broke other services because of dodgy permissions. So…

Autogenerated description: A glass jar on a desk about half fill with gold coins with a hand above it dropping two gold coins into the top. The room should be lit with sunlight and there should be a paper label on the jar with the text 'Permission Bug Jar' written in black marker.

My second favourite word to write in a Jira ticket, after augment, is “decommission”. I’m basically using it as an euphemism for “rip this unused code out”. To have made a few tickets with this word today feels glorious. 😊

As Someone Who Works In Software

As someone who works in software…

  1. I cringe every time I see society bend to the limitations of the software they use. It shouldn’t be this way; the software should serve the user, not the other way around.
  2. I appreciate a well designed API. Much of my job is using APIs built by others, and the good ones always feel natural to use, like water flowing through a creek. Conversely, a badly designed API makes me want to throw may laptop to the ground.
  3. I think a well designed standard is just as important as a well designed API. Thus, if you’re extending the standard in a way that adds a bunch of exceptions to something that’s already there, you may want to reflect on your priorities and try an approach that doesn’t do that.
  4. I also try to appreciate, to varying levels of success, that there are multiple ways to do something and once all the hard and fast requirements are settled, it usually just comes down to taste. I know what appeals to my taste, but I also (try to) recognise that others have their own taste as well, and what appeals to them may not gel with me. And I just have to deal with it. I may not like it, but sometimes we have to deal with things we don’t like.
  5. I believe a user’s home directory is their space, not yours. And you better have a bloody good reason for adding stuff there that the user can see and didn’t ask for.

My favourite gym t-shirt. All the Aussies would get this reference.

A black T-shirt is displayed with the text 'WE'RE GOIN TA BONNIE DOON' printed on the front in bold white letters, with the line Bonnie Doon Hotel below it on the right.

This I got from an op-shop but I have been to the Bonnie Doon Hotel a few times. It’s actually pretty nice.

📺 Taitset

Discovered another YouTube channel about Victorian railways this evening. This one’s more about history and operations and less pure cab-rides. A lot of fascinating information about locations that I’m very familiar with.

It’s already May and I’m way behind on my reading goals for the year.

Screenshot of the Micro.blog reading goals for 2024, showing 1 book read with a goal of reading 10. The single book cover is blank.

The trouble is that the book that I want to read next is one I’ve read before, which doesn’t really count towards my goal. Well, I guess it could, since I haven’t listed it here. Maybe I’ll let myself this one pass.

On the train. Overhead announcement comes through from the control centre mentioning that a way to get service updates is to follow Metro on Twitter. Not X, Twitter. Even 1.5 years out.

Such is the staying power of Twitter as a brand, compared to what it’s called now. I’d be curious to know if those not using X or are not interested in tech know about the rebrand at all. Everyone knew about Twitter, even if they never used it.

Tape Playback Site

Thought I’d take a little break from UCL today.

Mum found a collection of old cassette tapes of us when we were kids, making and recording songs and radio shows. I’ve been digitising them over the last few weeks, and today the first recorded cassette was ready to share with the family.

I suppose I could’ve just given them raw MP3 files, but I wanted to record each cassette as two large files — one per side — so as to not loose much of the various crackles and clatters made when the tape recorder was stopped and started. But I did want to catalogue the more interesting points in the recording, and it would’ve been a bit “meh” simply giving them to others as one long list of timestamps (simulating the rewind/fast-forward seeking action would’ve been a step too far).

Plus, simply emailing MP3 files wasn’t nearly as interesting as what I did do, which was  to put together a private site where others could browse and play the recorded tapes:

The landing page, listing the available tapes (of which there's only one right now.
Playback of a tape side, with chapter links for seeking.

The site is not much to talk about — it’s a Hugo site using the Mainroad theme and deployed to Netlify. There is some JavaScript that moves the playhead when a chapter link is clicked, but the rest is just HTML and CSS. But I did want to talk about how I got the audio files into Netlify. I wanted to use `git lfs` for this and have Netlify fetch them when building the site. Netlify doesn’t do this by default, and I get the sense that Netlify’s support for LFS is somewhat deprecated. Nevertheless, I gave it a try by adding an explicit `git lfs` step in the build to fetch the audio files. And it could’ve been that I was using the LFS command incorrectly, or maybe it was invoked at the wrong time. But whatever the reason, the command errored out and the audio files didn’t get pulled. I tried a few more times, and I probably could’ve got it working if I stuck with it, but all those deprecation warnings in Netlify’s documentation gave me pause.

So what I ended up doing was turning off builds in Netlify and using a Github Action which built the Hugo site and publish it to Netlify using the CLI tool. Here’s the Github Action in full:

name: Publish to Netify
on:
  push:
    branches: [main]
jobs:
  build:
    name: Build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: true
          fetch-depth: 0    
          lfs: true
      - name: Setup Hugo
        uses: peaceiris/actions-hugo@v3
        with:
            hugo-version: '0.119.0'
      - name: Build Site
        run: |
          npm install
          hugo          
      - name: Deploy
        env:
          NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
          NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
        run: |          
          netlify deploy --dir=public --prod

This ended up working quite well: the audio files made it to Netlify and were playable on the site. The builds are also quite fast; around 55 seconds (an earlier version involved building Hugo from source, which took 5 minutes). So for anyone else interested in trying to serve LFS files via Netlify, maybe try turning off the builds and going straight to using Github Action and the CLI tool. That is… if you can swallow the price of LFS storage in Github. Oof! A little pricy. Might be that I’ll need to use something else for the audio files.