Pink Moon 2024

Case Duckworth

April 23, 2024

Hi and welcome to the Pink edition of MOONBOOKS, a moonthly installment of all the things I've written in the past cycle. I've been inspired by my friend dozens's moonbooks to build my own compendia. Here is the first of those.

Today is Shakespeare's deathday and (maybe) birthday, which is why he haunts all of his plays. I hope that what's inside these pages—a few poems (but nowhere near enough for a full NaPoWriMo), a couple of lists, a README, a format proposal, and a (micro)blog or twoߞhaunt you, in a good way, for oh, maybe ten minutes? Can we do that?

Copyright & Acknowledgements

The writing contained herein is © 2024 Case Duckworth. It's distributed under a Creative Commons Attribution-ShareAlike 4.0 International license. If you do create a derivative work, I'd love to see it! Please email me.

The sheep image in the lam piece is by my friend m455. Thanks buddy! Thanks to dozens for the inspo. The cover image is by George Hoden and has been released to the public domain.

Dedication

This book is dedicated to my family.

After everyone else went to bed

I puttered around a while. Had
some tea. Made a quesadilla.
I made a few false starts at this,
but I think
this one will stick. Has to,
anyway. I have less than a half-
hour to make it work. How long
is a poem? How do you measure it's
done? The urge to end there
is strong but I'll avoid it.
Too twee. Too meet-cute in
the moonlight outside a childhood
home, too perfect to be true.

again

we try again, we fail
again, fail better, again,
and for what
               there is no
purpose inherent in trying
no reason to be better except

for our own reasons and
isn't that enough
             who said it
wasn't enough

                 the birds
keep singing on the branches
waving in the wind as it
blows its way to the sea
rough as salt and we
can see it all and again

Heads of state

I'm over hearing about the heads of state
what about the knees of state, the shoulders
of state, or the flat feet of state
where are they walking to slapping like that
on the floor of state in the house of state
on the street where state lives

state needs a haircut, thinks the brain of state
the hands of state text state's hairdresser
to find out when they have an appointment

state heads out the door and the sidewalk
is warm on the soles of state's feet
the sun is shining on the long hair of state
the ears of state hear birds in the trees
state thinks, being a state is okay sometimes

Eclipse

it happened today even if the clouds eclipsed it,
in that way that things happen
even if you don't notice them. they're funny
like that. if a tree falls in
a forest, that kind of thing. one hand clapping.

the thing is the next one isn't for seventy years.
the thing is i don't know if
i'll be around for it. there are a few things i
want to do and to see the sun shut off
like a light is one of them. if just for better

metaphors. sometimes you have to be there, see
the tree falling, hear it as
it hits the ground hard and birds fly off around.
even though it happens without you.
you want to hear it speaking in its own voice.

Good soups

minestrone

miso

tomato

borscht (veggie)

mulligatawny (in name only)

chili (with beans, fight me)

ramen noodle

pho

hell, any noodle

ice water

the kind with croutons in

ok: a minimal build system in posix sh

ok is a minimal build system that's kinda like make in that you plop a file describing your build in your project's folder, then run a system command that reads the file and builds the project. it's written in posix sh and is designed to be strictly more expressive than posix make, which is awful.

Installing ok

ok is just a shell script, so you can mv or cp it to your $PATH. It requires a somewhat-modern posix-compliant shell (i am not going to figure out what "somewhat-modern" means), as well as the following utilities:

sed

grep

cut

if you don't have these, congratulations! You are really doing something interesting with your system.

Using ok

If the project you're hacking on has an okfile (by default, ./ok), you can just run ok and it'll do whatever the author made the default target. You can also run ok with the following flags:

-h | shows a help message, then exits
-q | runs ok in "quiet" mode; that is, no messages are printed
-x | runs ok with "set -x" turned on; this is a shell feature that might help you debug some weirdness
-n | runs ok in "dry-run" mode; that is, no recipes are run
-B | run all targets as if they were "new," like make -B
-f FILE | use FILE as the okfile instead of ./ok
-C DIR | change to DIR before doing anything, like make -C

ok -h will also print the targets it's found in the okfile, along with explanatory comments provided on the target's first lines. See the example provided below for an idea.

Writing okfiles

of course, the real part of using ok is writing the okfile. This section describes the format of that file, which is a shell script sourced by ok, to help you write good okfiles for your own projects.

an okfile is simply a shell script where every function defined is a target. The first function in the script is the default target that runs if no target is specified. ok has a few utility functions to make writing targets easier:

ok

print, then run the command given after it on the command line. if -q has been passed, suppress printing; if -n has been passed, suppress running. if the command fails, ok will exit with 100 + the command's exit code.

dep

define a dependency on the targets specified as arguments. the dependencies will be run in the order of the command line before continuing with the current recipe.

fr

define a series of file rules. See the next section for a description of these.

allfiles

print all the files defined in the fr call.

File rules (fr)

while writing shell functions is fine and dandy to simulate make's .PHONY rules, it does nothing for the main use of make: generating files from other files. The solution i landed on for ok was the fr function, which is short for file rules. This section describes the format of fr's input, as well as suggestions for use.

fr reads lines from standard input, processes them, and outputs them to an frfile in the current directory (which can be safely deleted, and is in fact rebuilt on every invocation). I recommend using a heredoc for building the file rules, since that allows free-form text as well as programmatic rule generation (something make does not do).

each line fr reads will be parsed as a TARGET, a JOB, and the JOB's DEPS. The TARGET is the target file to build, JOB is the job to run to build that file, and DEPS are all the dependencies of TARGET.

DEPS can include both build and order dependencies. Build dependencies are appended to JOB as arguments, while order dependencies merely force TARGET to be built if it's newer than them. TODO: THERE IS A BUG IN THIS IMPLEMENTATION. ORDER DEPENDENCIES ARE CURRENTLY IGNORED.

JOB should be a function defined in the okfile or a one-word command, since fr doesn't do any special $IFS magic. I recommend creating an ok function that encapsulates JOB's logic and including that in the fr block.

fr example

since fr is possibly the most complex thing to understand for ok, here is an example. This okfile is how i build a simple 'hello, world' program in C:

          for c in *.c
          do echo "${c%.c}" build "$c"
          done | fr

          : "${CC:=cc}"

          default() { dep allfiles; }

          build() { # build an executable from a c source file
          ok "$CC" "$1" -o "$TARGET"
          }

as you can see, providing a heredoc to fr's input means i can build up the flies i want to build dynamically, rather than having to update the okfile every time. This fr invocation produces the following file:

          hello	ok build	hello.c

in this simple example, i could've written this just as well:

          fr<<..
          hello build hello.c
          ..

you can depend on all files that need building using the 'allfiles' target, so it's a good idea to put a 'dep allfiles' somewhere in your build functions. you can see it above in the 'default' rule.

Copying and contributing

ok is distributed under a standard BSD 3-clause license. Contributions are welcome; feel free to email me with feedback, questions, or patches.

Inspiration

thanks to akkartik, whose basic-build gave me the inspiration for ok.

ass+content Feeds

ass is a perfectly cromulent format for a feed, but it cannot express the full range of forms expressed by RSS or Atom. This docuent defines a text/ass+content format, which extends ass with optional content data.

It's similar to the sfeed internal format, but not as complex. It's also not dissimilar to the twtxt format, but then ass itself isn't dissimilar to that.

Format of a ass+content feed

A feed is a text file where every line is an item. An item consists of the following:

An ISO 8601-formatted date

The item URI

optional: The item's title

optional: The item's auxiliary url

optional: The item's content

Items 1, 2, and 3 are as in ass. Items 4 and 5 are the additions of this document. All items are separated by the TAB character (ASCII 9). Item 5 can include tabs as well, since it's the last item.

Auxiliary URI

The auxiliary URI is another URI that an item can refer to. Specifically, this URI can be used to point to an item's enclosure in RSS terminoloty, e.g. a podcast media file.

Item content

Item content is the text that usually appears in the RSS or Atom <content> element. This text can contain any characters, except for the newline (ASCII 10), which should be escaped with the string "\n".

Example

The following example was adapted from the RSS feed found at https://feeds.libsyn.com/117500/rss.

# Our opinions are correct
2024-04-04T07:00:00Z	https://ouropinionsarecorrect.libsyn.com/we-failed-the-turing-test-walex-hanna-and-emily-m-bender The Turing Test is bullsh*t (w/Alex Hanna and Emily M. Bender)	https://pdcn.co/e/traffic.libsyn.com/secure/ouropinionsarecorrect/OOAC_Ep_149_Turing_Dogs_MASTER.mp3	We're talking about the Turing Test,...
2024-03-21T15:47:00Z	https://ouropinionsarecorrect.libsyn.com/queer-horror-with-dr-chuck-tingle Queer Horror! (with Dr. Chuck Tingle)	https://pdcn.co/e/traffic.libsyn.com/secure/ouropinionsarecorrect/OOAC_Ep_148_MASTER_v3.mp3	<p>It's a scary time for LGBTQIA+ folks ...

lam 00. lam!

I'm implementing a lisp. In lua. For fun!!

It's called lam, which could be

short for a Lisp Acdw Made

a reversal of MAL, the popular make a lisp project

the thing you go on when a scheme goes wrong

.... other things .... ????

Anyway, in this series I'm going to take you on a tour of all the parts of lam, from the reader to the types to evaluating and all the rest. Along the way, I'll talk about my successes, failures, false starts, and everything else that comes with trying something new. Stay tuned, yall :)

general plan for posts

I'm planning on covering each lua module in lam in turn, and in roughly this order:

read, where I convert program text into a lisp structure (one of the benefits of lisp is that the AST is the code)

type, where I define all the types of the language as well as a few utility functions

eval, where the read-in forms are evaluated to produce a value

load and repl, closely-related modules that marry read, type, and eval to load files and, you know, run a repl.

core, the primitive environment of lam

You may notice other files in the repo. They are either leftovers from rewrites – which I plan on eventually rewriting themselves – or vendored dependencies: specifically utf8.

Modules I still want to write but either need rewriting or ... writing include

test, the test suite

lang, a macro library

errs (or maybe oops), an error & debugging library

... probably others

That leaves one file unaccounted for:

util.lua

Since the util module isn't long or important enough for its own post, I'll quickly talk about it here. I hope to keep shrinking the size of util until I can delete this file (and section on this page) altogether.

util.error(desc, ...)

This function wraps lua's error to make writing errors a little easier on myself. I'm not sure how helpful this is, really. I need to write another error-handling library to really make it work.

util.pop(tbl)

Another convenience fuction. Lua's table.remove removes an element from a table, but by default it removes it from the end. pop removes it from the beginning.

shitty lisp club

I'm part of a little club where we're writing shitty lisps. Check us out at the #shittylisp hashtag on fedi! (I think I've linked that right .. that's federation for you.)

Sofaware

You may've noticed it's been a while since I've written anything about my wm in scheme. That's because it's become sofaware, or softwares that have landed, comfortably, softly, on the sofa.

I have a lot of softwear on the sofa. In fact if you look at my git thing, you'll see plenty of projects that I've rested on the sofa. It's okay to set things on the sofa and maybe (or maybe not!) pick them back up again.

This post has been inspired specifically by my project subtext, which is an attempt at a groff-like, flexible document preparator using only POSIX shell and awk. It's a good idea, but it's a pain to keep track of all the state I need to to render correctly, and because of the layers of awk and shell that eventually generate html, it's really hard to debug issues.

Even before I get to that problem though, I have the issue that I don't really know how I would organize it. There are a lot of options and I haven't fully thought them all out and decided on the best one.

Ultimately, I've just lost interest in the thing. I keep trying to rewrite it, but keep getting frustrated. So on the sofa it has gone, and maybe later, it'll come off again.

And that's okay.

Pink moon toots

March 25. the mediator between head and hands must be the heart!

March 25. "Come out," said Frog. "It's a beautiful day!"
"No," said Toad. "I am in my flop era."

March 27. my #shittylisp can now read from ports, which is great. now to fix eval...

March 28. sure wish I could work on my #shittylisp tonight but I have been computering far too much today

March 29. wow, hob, cob, lob, nob ...

more words should end with -ob

March 29. technically, I'm not being pedantic

March 31. I've implemented quasiquote in my #shittylisp ! it's a little ugly but it works! https://git.acdw.net/lam/tree/eval.lua#n54

April 1. #napowrimo time yuns time to write a poem every dayyy

April 2. TIL you can swipe on Firefox mobile's address bar to switch tabs

April 3. last night was a productive one for my #shittylisp ! implemented proper lambda lists, # literal syntax (booleans and chars), and did some general cleaning up

April 4. what if LinkedIn but on the fediverse

April 4. ah shit I forgot to write a poem yesterday

April 7. CW: #shittylisp
rewriting now for reorg of the code. I think I'm putting off writing lisp code...

April 7. dang I'm tired

April 9. #shittylisp reorganization nearly complete. probably because of typos or weird logic changes i half-thought thru, i have some bugs to work out before pushing. like how sending EOF doesn't quit, and some others i don't remember right now

April 9. ya boi just found a dime

April 9. shit AND a nickel! things are really looking up for me

April 9. I want salad but have no lettuce

April 9. I have reorganized my #shittylisp modules to make more sense (to me) and am ready to start implementing macro expansion (scary!)

April 10. screeoop

April 10. something I will eventually have to figure out with my #shittylisp is how to represent bignums, ratios, complex numbers, and the like. now that I think about it maybe it's not so hard? tho exact and inexact, hm. I think I'll have to look at the number representation in lua

April 11. tired: README.md
wired: README.txt
inspired: README.doc

April 12. if your blog post has illustrations generated by ai, I will close the tab. just don't!

April 13. CW: work
welp I didn't think to bring my work laptop so I got nothin to do except scroll fedi while the kid sleeps

April 14. some guys are all, I fix my own car! I'm the type that does my own taxes

April 15. CW: new board game
Topology! easy if you can open the box

April 16. hmm maybe I should make my #shittylisp a #shittykernel

April 17. the first time I ever heard about bukowski was in the modest mouse song and to date it's his most accurate description

April 17. I've fixed two major bugs in my #shittylisp by essentially correcting two typos.

April 18. data centers
why not
dada centers

April 20. I think I'm going to start writing blogs about my #shittylisp development... I'm gonna have to go back to the beginning but I think it'll be fun!

any requests for what you want to read about re lisp development?

April 20. my zeroth #shittylisp blog post is out now!

https://funputer.biz/lam_00.lam.html

April 23. I'm in the south of France.
Nice.

April 23. butts tbh

April 23. you're telling me a python wrote this code?!