Coby's Recursive Adventures

A daily-ish log of activities at my Summer 1 batch (May - August 2021) at the Recurse Center.

My goals

Projects

Dear diary...

Tues, May 18

Today (the second day of my batch) felt like even more of a whirlwind than the first day! I can't believe it's only Tuesday - it feels like a week has already gone by. ๐Ÿ™ƒ

I anticipated feeling pulled in many, many different directions and successfully averted getting sucked into too many projects! This is a minor victory for me and I'm proud. ๐Ÿ™Œ

Here's the breakdown of what I actually accomplished today:

Weds, May 19

This morning I realized that when I started this log I made the first entry for the 15th of May (the day after my last day of work for this leave of absence), rather than the 18th (the actual date/second day of RC). My job ending apparently held more gravity than the thing I was pausing it to go do. An interesting Freudian slip.

Tomorrow:

Thurs, May 20

Fri, May 21

Mon, May 24

Tues, May 25

Weds, May 26

Friday, June 4

This whole week was very insular for me. Didn't do a lot of checkins, declined all coffee chats, focused almost exclusively on core design decisions and code for Bread. It was awesome. I'm going to be doing more of that this week but I'll probably do a couple coffee chats and maybe seek out some pairing sessions, since last week felt pretty lonely at times.

Friday, June 11

Wednesday, June 16

Thursday, June 17

โ€  Meaning it's just an accretion of immutable facts, as opposed to more traditional databases/stores like MySQL or MongoDB which are "place-oriented" where stuff gets overwritten

โ€ โ€  I know I'm totally drinking the Kool-Aid here, but there are a lot of those.

โ€ โ€ โ€  To be clear, only one post should be highlighted in green at the bottom, since post-6833... already existed at the left.

Friday, June 18

Friday, June 25

Monday, June 28

Tuesday, June 29

Wednesday, June 30

Thursday, July 1

Friday, July 2

Monday, July 5

Tuesday, July 6

Wednesday, July 7

Thursday, July 8


The problem is that I have a vector of samples (tiny sub-millisecond clips of audio) which I need to simultaneously read (older samples) from and write (new samples) to. I need to do this because a looper, by nature, needs to both record and play back audio at the same time.

The audio crate CPal's feedback example, on which my prototype is sort of based, uses this [producer/consumer pattern](producer/consumer pattern) where you "split" ownership of a data structure into a producer you can write to and a consumer you can read from. Antoine Van Gelder offers another example of this in his talk Bare Metal Audio Programming with Rust.

For my application I want to use a Vec<f32> to hold audio samples, not a Queue. Vec doesn't support split() so we needed to find a way to do something similar with this type. Chris's suggestion was to use an Arc<Mutex>.

However, once we got out of the wrestling match with the type system that ensued, that led to a pretty similar problem: cannot borrow as mutable, i.e. basically you can't share the same Arc instance between two callbacks, because either the audio input or output (read or write) callback needs to "own" that variable--but not both.

But wait a second, isn't Arc designed to be shared? Yes and no. You need to clone() it first, and move the clone to some other owner. Turns out this is how RingBuffer::split() is implemented!

Here's what I ended up with. It doesn't do what I want yet, but it does compile:

    // let idx = some magical value that represents where we are in the playback buffer.
    
    // pre-allocate capacity for ten seconds of audio samples
    let samples: Arc<Mutex<Vec<f32>>> = Arc::new(Mutex::new(vec![0.0; 44100 * 10]));
    
    // Split our Arc into consumer/producer so we can read from/write to it
    // within separate input/output audio callbacks.
    let input_samples = samples.clone();
    
    let input_data_fn = move |data: &[f32], _: &cpal::InputCallbackInfo| {
      for &sample in data {
        (*input_samples.lock().unwrap())[idx] = sample;
      }
    };
    
    let output_data_fn = move |data: &mut [f32], _: &cpal::OutputCallbackInfo| {
      for sample in data {
        *sample = (*samples.lock().unwrap())[idx];
      }
    };

There's still an issue, though: lock(). This is a big no-no in real-time programming (which includes audio programming) where you need ironclad guarantees about how fast your operations will complete. Locking foils this guarantee because it's inherently contentious. I may need to reimplement one or both sides of this equation using a lockless API, like Queue perhaps...however, I still need random access which is why I chose Vec in the first place. So this is still an open question. But I still learned a lot today so this was pretty successful as far as failures go.

Friday, July 9

Monday, July 12

Tuesday, July 13

Wednesday, July 14

Thursday, July 15

Friday, July 16

Monday, July 19

Wednesday, July 21

Also, here are some cool resources about various pieces of inspiration for living more sustainably:

Thursday, July 22

Friday, July 23

Interlude: Programming language goals

One goal I had at the beginning of my batch was to write a simple Lisp that compiles to WASM (or potentially to a specific WASM runtime like Wasmer).

This prompts a crucial question: what should the language be called? Yeah, the language probably won't ever reach anywhere close to 1.0 because I don't want to spend years of my life building and maintaining a programming language. It probably won't ever get to a point where it's even useful. But naming things is still fun, and for me personally it gives any given project a little extra motivation in my mind to get it to a satisfying place. So here's a list of potential names I like:

I think for now I will go with Flower.

Here are some language features/characteristics that would ideally exist in my language of choice:

I almost certainly will not get around to implementing all these features, but this is what I currently imagine would be in the programming language of my dreams...

Monday, July 26

Started off with Compiler Appreciation Club talking about macros. On Veit's recommendation I watched Racket author Matthew Flatt's talk Let's build a hygienic macro expander. Very cool stuff!

This inspired me to start on Flower, a Lisp that compiles to Wasm. I flailed around most of the day trying to figure out how to write raw Wasm binaries or WAT files from Rust, but pretty much all the resources I found are about compiling Rust code itself to Wasm, meaning that to take advantage of all the Rust->Wasm tooling out there, I would have to invoke the Rust compiler programmatically. So any compiler I write on top of that would have this black box at the center, and I'm not very interested in building such a system right now.

Tuesday, July 27

More of the same. Flailed for a long time seeing if I could represent a WAT AST as Rust vectors, but ultimately decided that I'm still enough of a Rust n00b that if I'm going to be learning all this stuff about compilers, parsing, etc., I'd rather do it in a language I'm already comfortable in. So hello, Clojure! It's good to be back in the REPL. :D

Also solved a few more LeetCode challenges. They were "medium" difficulty but felt pretty easy so that was a nice confidence boost.

Wednesday, July 28

Wednesday, August 4

The last week was a bit of a wash in terms of writing code. I've been feeling a bit overwhelmed again as I approach the end of my batch, and I'm finding it hard to choose a direction to go in. Here are some things I worked on that kind of fizzled:

Other stuff this week:

Thursday, August 5

Got inspired to move back to working on Bread CMS for my last couple days in-batch. Got a full "end-to-end" test working -- e2e in the sense that it tests the whole request/response lifecycle with all core plugins composed together.

In the afternoon I went down to Olympia and hiked around the lovely Watershed Park Trail.

Friday, August 6

Today I worked more on Bread CMS, refining the internationalization system. It was rewarding and satisfying to see code I'd worked on months and months ago get smaller and simpler. I plan to continue working on this over the next few weeks.


I can't believe my batch is over!

I deeply appreciate this community and the connections I've made. Recurse is a truly special place, even when it's only virtual. I can't wait to visit in-person someday!

Thank you to the RC Faculty for fostering such an amazing space. And thank all of you in my batch. I'm so grateful to know you all.

I'll still be around at the occasional checkin or group, and I'll be posting in #alumni-checkins! See you around!