Quantum Mechanic

Recent Content

Clack Static Asset Middleware

posted on 2016-05-12 02:01:00

As part of my glacial march to get Knttl running the way I'd like, I wrote a middleware for the clack web framework to help me out!

When you're serving javascript and css files for a website, you want to inform the browser to keep a local copy as long as possible, because then it won't bother your webserver to download it again and the page will render faster for your users, too. There's a popular quote about programming

There are only two hard things in Computer Science: cache invalidation and naming things.
It seems this was said by a Phil Karlton.

So, like many things related to the it-was-never-meant-to-be-used-this-way world of web technology, there are some interesting best practices that evolved around this idea that, ideally, only one copy of a static file should ever need to be sent to a user, if their browser works well.

There are ways to tell a browser how long to hold onto a file before checking if there's a new version of it, but that only gets you so far. Presumably, your javascript is going to change, some day, and then you'll feel silly when all of your users are still running a three week old version of it that's still cached by their browsers.

The next bit is the hack that makes it all shine.

"Why not just change the filename when the file's contents change?" asked some bright engineer, somewhere. So, we do. We just attach a hash of the file to the filename and serve that. When the file changes, the filename we show the web browser changes, and we can tell the browser to just cache the file forever, or as close to forever as we can!

It's kind of a pain to generate a copy of all of your files with hashes attached, so what clack-static-asset-middleware does is store calculate some hashes of your files and just pretends those files exist and serves up whatever you tell it about.

I also wrote some helpers you can load to use this stuff easily with Djula, like so:

<a href="/" class="logo u-pull-left" title="Home">
<img src="{% asset-path "small-logo.png" %}"
width="54" height="60"
alt="Knttl" />
So, to summarize:
  1. Have style.css
  2. Template asks for hashed filename, gets something like style_2867f3f83a6a91ad4a19a6cd45536152.css
  3. Browser asks for style_2867f3f83a6a91ad4a19a6cd45536152.css
  4. Server says "Aha! I have fooled you! Here's style.css! Keep it as long as you like!"
  5. Browser says "Golly gee! I will, mister Server! I'll never ask for style_2867f3f83a6a91ad4a19a6cd45536152.css again!"
  6. Hooray!
So check out clack-static-asset-middleware, which will hopefully be in quicklisp soon!

We Can Has Doggle

posted on 2016-05-10 01:41:00

I have been a bad blogger lately, as always, but there's something worth throwing a few words onto the internet about.

We've adopted a dog! A little over a week ago, we took a trip out to the North Shore Animal League America and adopted a very mixed breed dog who we've named Wedge after the legendary starfighter pilot from the Battle of Yavin (and the X-Wing series of books that I loved in my teens). It only took us eight hours after the staff lost our application for a while and left us sitting in the dog meeting area hungry and uncertain.


Wedge came from a pupply mill, which means he was probably brought up in a situation where he was kept in a cage all the time and probably wasn't treated like he was a sentient being all that often. If you look around online, you'll find that adopting a mill dog can mean signing yourself up for a fair bit of doggy rehab (figuratively speaking).

For the first week we had him, Wedge was afraid of just about anything at just about any time. You couldn't even give him a treat, half the time! He would walk up to take it and then it was as if the realization of how close he'd come to me hit him about two feet out from my hand. Then he'd turn so fast that his butt and head were going different directions for a moment. It was cute and sad all at the same time!

I'd never really expected to get a dog - the one we had growing up didn't like to do much but steal food and be ornery - so I wasn't really looking for another dog experience. After our trip to Portland, OR, though (which I'm now realizing I didn't write about here! More soon!), we were left with feelings about things that were missing from our lives. Things like really good coffee, vegan donuts, and maybe having a cute dog to stop us from being all depressive a lot of the time (therapist recommended!). Naturally we picked a dog with it's own emotional problem.

Now, Wedge is calming down and doesn't run away from me when I move around the rooms of our tiny apartment anymore. I haven't really had to train a dog before, though I grew up with one, so this is a bit of a challenge. Hopefully, he'll come out of his shell in the next few months and we can take him camping over the summer.

This was kind of fun to write!

posted on 2016-01-16 20:43:00

(defun zip (&rest sequences)
(apply #'map 'list (lambda (&rest args) `(,@args)) sequences))

(zip '(1 2 3) '(2 3 4))
;; => ((1 2) (2 3) (3 4))

Literate .emacs with org mode!

posted on 2016-01-03 17:56:00

For a while now, I'd been meaning to convert my .emacs to the exciting, new style using org mode's literate programming capabilities.

I'd been impressed by the clarity of Sacha Chua's and, while I haven't quite hit that level of cleanliness, yet, I feel much better about how mine looks, now. I also started using John Wiegley's use-package, which I don't completely understand, yet, but it seems to be a real boon for cleaning up loading and configuring packages.

Even setting up slime, which I use through the quicklisp setup, is easy to load:

(use-package slime
:load-path "~/quicklisp/slime-helper.el")

First wikipedia edit!

posted on 2016-01-03 17:45:00

I was working on my typing practice, today, learning the Colemak layout, and came across a small typo in the Wikipedia article on Morris Engines!

It was a simple typo (form -> from), but I decided that was a level I was comfortable contributing at. I didn't notice there was a checkbox for minor edits like typos on the submission page, so I fully expect someone to crawl out of the internet and point it out to me.

Blog Walk Roundup 2015-12-10

posted on 2015-12-10 13:34:00

I spent a bunch of time collecting things around the web today. I think some of these are worth a read, so I'll link a bunch here.

Additionally, I participated in my first Massdrop and got my Code WASD Clears keyboard, yesterday. It's really nice to type on! If you're interested in playing that game, consider using my referral thing (https://www.massdrop.com/r/D2EFXE), because I like what they've done and I'd like a goodie box!

Neat blog comment policies

From Tim Chevalier's Blog:
If you comment, I have a few requests:

  1. Refrain from phobic or discriminatory speech, or speech that (in the words of s.e. smith) suggests that "people don't deserve autonomy, dignity, and a place in society."

  2. Refrain from comments that have the effect of silencing or derailing (see Derailing for Dummies for additional examples).

  3. As a corollary, refrain from questioning the existence of privilege or systematic oppression. There are many resources available online and offline for learning about these issues.

  4. Provide a name or pseudonym that reflects a consistent online presence (as opposed to so-called "throwaway" or "sockpuppet" identities).

Apparently, this is stolen from Christie Koehler's.

Rust stuff

At work, we've been looking at using Go for a rewrite of a major project. I keep trying to dig into it and have been annoyed by a bunch of things. I still think it could be a nice idea, there, but I have this problem where I get strong affinities for things pretty quickly and I've gotten pretty interested in Rust as, perhaps, and alternative to Go.

I've barely used it yet, but it seems to have nice easy package management, immutable data, a helpful compiler, a type system I can get behind, and whose documentation I can find! For some reason, I feel like it's been difficult to find good explanation of Go.

In any event, I've started working through Rust's book, after using the emacs setup shared here. This has been a long time coming, because I've been hearing about Rust over the years and keep meaning to try it. Reading the blogs above, it turned out that Tim Chevalier worked on Rust, so there was a handy link to a presentation to remind me to check it out!

Both languages are current better than the python 2.7 we use at work, because they both use unicode! Something that should just be standard at this point!

extern crate rand;

use std::io;
use rand::Rng;
use std::cmp::Ordering;

fn main() {
println!("Guess the number!");

let secret_number = rand::thread_rng().gen_range(1, 101);

println!("Please input your guess:");

loop {
let mut guess = String::new();

io::stdin().read_line(&mut guess)
.expect("Failed to read line");

let guess: u32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => continue,

println!("You guessed: {}", guess);

match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => {

Using Emacs to Study Japanese

posted on 2015-12-06 03:02:00

Tonight, I took my first steps into the world of emacs lisp!

Last January, when I had more time and energy to devote to studying Japanese, I started wondering about using org mode to help me. I was reading articles from the NHK News Easy website and spending a lot of time going back and forth between that, jisho.org, and emacs (where I was keeping my notes).

If you haven't used it, already, jisho is a wonderful site that is the best of what you could hope for in an online dictionary. It's fast, clean, and usually returns the most helpful results without having to fight it too much. I've also spent a bunch of time using LEO and, while I appreciate it, it suffers a bit from over design that hurts usability.


I really wanted to find a way to work in emacs with org mode. Maybe just copy articles from the NHK into a study log and then look up words and insert them under the sentence they were from. Last January, I wrote to the makers of jisho and Kim Ahlstrom was nice enough to write back and let me poke around with an API he'd been working on. Today, I spent a few hours learning my first emacs lisp and making a few functions to query it and format some nice defintions for me!


Figure 1: It doesn't get much more exciting than this!

Starting with a background in Common Lisp was probably pretty helpful, because I was ready to understand the plist's and the like that were involved. Some of the json handling was nicer than in Common Lisp, since emacs seems to let keywords be lowercase by default, as are most of the json key names that they're decoded from. In CL, you need to do a lot of :|property-name| because the reader upcases everything. I also learned that you can modify that behavior and that it is terrifying. I recently had an experience like this, trying to make json access easier for myself:

CL-USER> (readtable-case *readtable*)
CL-USER> (setf (readtable-case *readtable*) :preserve)
CL-USER> :thing
CL-USER> (print "Hello, world!")
; Evaluation aborted on #<SB-INT:SIMPLE-READER-PACKAGE-ERROR "Package ~A does not exist." {1004729173}>.
CL-USER> (PRINT "Hello, world!")

"Hello, world!"
"Hello, world!"
CL-USER> (cl:print "Hello, world!")

"Hello, world!"
"Hello, world!"

Hopefully, I'll be able to share this emacs-jsiho integration work, soon, because I think people would like it. I was asked not to make the API public, so I will wait until I have permission to share. I'm excited to have finally dipped a toe into elisp and, hopefully, I'll have time to refine my code and make it even more useful (like selecting from a list of possible results after searching!) in the meantime, anyway. I was pretty impressed with how easy it was to do API call, parse the JSON and then crawl through it. I have the impression that some parts of elisp are even moldier than CL, but maybe people are making a good effort to modernize it and lower bars.

Emacs for Writers and Notmuch

posted on 2015-11-29 17:03:00

Bored on a Sunday morning and ended up watching Emacs For Writers – a presentation by Jay Dixit, who I'm going to have to look into more, since he seemed like a cool person. It was about how he learned to use org mode to do the work that several word processing programs didn't quite do. He had a lot of fun customizations in his emacs and I might have to watch it again when I'm bored to work out somee other neat things to change. I think it might also finally be time to put my ~/.emacs.d into git so I can get at it on multiple computers and share the things I find at work/home with myself.

One of the things that flashed by in the video was notmuch, the emacs mail browser. Email is more of a pain in the butt than anything useful, these days, as family and friends use phones to contact me and work primarily uses a chat system, but what the hell, I thought, let's try doing email in emacs again (I'd previously tried gnus).

I primarily used the guide here, with some tweaks from here. Ended up modifying the latter a bit to gel with the GObject Introspection that might have come into existence after the wiki-page/python module were written. Works fine with it, though.

import gi
gi.require_version('GnomeKeyring', '1.0')
import keyring

def get_password(account):
return keyring.get_password('offlineimap', account)

It turns out that setting up offlineimap is the bulk of the work and doesn't run automatically, so I basically would need to automate running it or check my mail manually in a two-step offlineimap -> notmuch workflow? I probably won't actually continue using it, but we'll see!

Making a knitting tool

posted on 2015-11-28 19:01:47

Hey there, friends!  Over the years, I've been aspiring to making interseting web apps in Common Lisp.  At the same time, Sarah's been kniting more and more and I've gotten to see some of that world.  Lots of people use Ravelry for posting their work and it's got a strong community.  I thought it might be interesting to try to make something that formatted knitting patterns in an easy to follow way.  Maybe eventually work up to some sort of markdown extension.  We'll see where it goes.

A few weeks ago, I stuck an early version up at knttl.co!  I'm sure there are all sorts of little bugs in it.  But it's fairly pretty and quick and runs on top of PostgreSQL and Common Lisp!  It's running Eitaro Fukamachi's woo web server, which is nice and snappy.  It's ona very low tier DigitalOcean VM and I haven't configured everything that well for the environment, so it crashes if it gets too much traffic.  While it's working, though, it's pretty darn quick.  I wish I had more time/effort available to work on it, but it's hard to find the motivation after full time programming work during the week.  If you find knttl interesting or useful, though, please let me know!

Exploring the Hudson Valley

posted on 2015-10-19 00:32:40

Sarah and I took off from work this past week, which I'd been meaning to do for a while now.  You tell yourself you'll take a break when you finish a project and then it goes on for four months and then you say, 'enough.'

Looking south over the Hudson from the walkway.

We took a  few days to recover and relax at home, in Queens.  Because sometimes it doesn't feel like we get to use our home that much.  We didn't want to just sit around at home for the whole week, though, and Sarah found something that involved the term "vegan brunch," and I was sold.

We spent two nights at the Catskill Animal Sanctuary, which is a nice, vegan BnB that's attached to and supports a rescue sanctuary for farm animals.  I haven't really had the opportunity to spend a lot of time with other people who don't eat animals.  I had a friend in high school, knew one or two people in college, and otherwise haven't really had too many around.  I could do with more people around, period, but the proportion of veg*ans has been historically low.  It was nice to  have someone else asking me not to put anything not vegan in the fridge.  I can do that.  That's the way I live, too.  It was nice not to be the weird one for a few days.

The first night, we had vegan pizza at the Catskill Mountain Pizza Co. in Woodstock.  There were a bunch of people crowded around the bar, watching the baseball game and most were wearing different hats.  It was was open and friendly and felt good to be there.

Me and Jailbird
Me and Jailbird

The next morning, we took a tour of the Sanctuary. Goats are delightfully weird and were easy targets for petting. I also got to hold a rooster.

Jailbird was rescued from a meth lab.  Some of the chickens were boiler chickens -- the kind that are bred for ovens.  They grow so fast and big that they have a fraction of the lifespan of their not-engineered-for-food brethren, and joint problems to boot.  The same goes for the pigs and cows.  Another popular origin story was the pig who was supposed to be a cute little pet and grew to normal pig size.  Some were re-rescued from animal shelters for cats and dogs, where people had left them.

One downside of being around vegans is the popularity of anti-science and, specifically, anti-vaccination.  It seems like people come to it from different directions, but it always saddens me.  It's strange to discuss with people older than me how terrible the old diseases are.  How their unvaccinated children put others at risk; including others who have compromised immune systems and can't be vaccinated, even if they want to be.  I think on some level, I see it as a sort of social pact.  Sort of like how we try to be polite to each other and don't set each others houses on fire.  Putting everyone else at greater risk like that falls into that sort of category in my mind.

These piggles will be 800lbs as adults.  It is not a healthy size for a piggle.
These piggles will be 800lbs as adults. It is not a healthy size for a piggle.

People keep telling me that when I become a parent, my whole viewpoint will change.  I don't imagine becoming a parent will make me so constitutionally different from who I am that I wouldn't vaccinate my children.

Later that night, we explored Saugerties, which was another little town in the area.  We got some yarn for a knitting project I'm going to try and walked out a lighthouse on the Hudson. The lighthouse was also a BnB. It was a little disappointing and the path was soggy.

Saugerties lighthouse.
Saugerties lighthouse.

There were several stores that had vegan options and I was super happy.  I had a vegan ice cream sandwich, which I posted about earlier, and we had tasty soup for lunch and dinner at Rock da Casbah, which was very friendly and provided a tempeh burger and vegan mac 'n cheese.

An animal sanctuary is a place that raises a lot of questions.  Questions like: 'What do you do with the sheep wool, that you have to cut anyway?' and 'Have you seen a rise in goat/chicken/duck rescues as part of the modern homesteader movement?' and 'What sort of relationship can we aspire to with animals?'  They're tough questions, but I missed having real tough questions in my life.  They're things that make it feel more meaningful.  The real hard problems in my day to day life have been dealing with other people for too long, and it filled me with hope and aspirations for what my life could be.

Thanks for reading.