Tutorials

Writing Racket Macros: define-syntax and phases

19 May 2023

There are a bunch of different ways of writing a macro in Racket. There are also some tricky things around phases to keep in mind. This is to help me keep them all straight.

3+1 ways to make a macro #

This form:

(define-syntax-rule (foo args ...) (use args ...))

is equivalent to:

(define-syntax foo
  (syntax-rules ()
    ([foo args ...] (use args ...))))

Which, is in turn equivalent to:

(define-syntax foo
  (λ (stx)
    (syntax-case stx ()
      [(gensymed-foo args ...) #'(use args ...)])))  ; gensymed-foo is like foo but doesn't match in the template

because syntax-rules expands to syntax-case with some fancy wrapping around it.

...

Make an Emacs Buffer Open the Way You Want

27 Dec 2022

Are you tired of having a particular buffer pop open in the wrong direction? Do you wish, for example, that the Racket REPL buffer showed up on the right in a vertical split, rather than below in a horizontal one? Look no further. I give you, display-buffer-alist:

  (add-to-list 'display-buffer-alist
               '("\\*Racket REPL </>\\*"
                 (display-buffer-in-direction)
                 (direction . right)))

That little snippet will make sure when you hit C-c C-k inside of a racket-mode buffer, a REPL will pop up on the right-side instead of on the bottom. I find that much more comfortable to use.

...

Continuations—what are they?

17 Nov 2022

I had a friend ask me what continuations are, and why they're useful. There's a ton of literature about continuations; this is just a simple example meant to showcase something small and hopefully grokkable.

You will need to understand a little bit of Racket, but if you know any Scheme, that should be good enough. If you just want a quick primer, check out Learn X in Y minutes for Racket.

#lang racket

;;; Export these symbols
(provide fail pick non-deterministic-factor)

;;; Global stack of choices (only visible to this module)
(define *choices* '())

;;; Pop a value off of the alternate choices stack
(define (fail)
  (if (null? *choices*)
      #f
      (let ([next-choice (car *choices*)])
        (set! *choices* (cdr *choices*))
        (next-choice))))

This next function pick is where we capture the continuation. I've named it return-from-pick to illustrate that when you call this function, it will jump back to the point in the code where pick returns. However, this works even if you use the continuation after the thing the called pick itself has returned.

...

How to write a type checker/type inferrer with good error messages

27 Jul 2022

All the source for this may be found on my Codeberg repository.

Synopsis #

Experimental type checker/inferer for a simple lambda calculus

Description #

This is a type inference system for a little language. (Described below.) It uses a fusion of type inference algorithms from PLAI, ESP, and μKanren. (See Resources)

Broadly speaking, our type inference engine works by:

  1. generating typing constraints from the program
  2. solving those constraints

We’ll describe each of those in more detail.

...

Adding a Clock to the Tab-Bar in Emacs 28

20 Jul 2022

Today I figured out how to add a tab-bar to Emacs. I didn’t like having it in the mode-line: it gets duplicated for every window and my mode-line space is precious. In contrast, the right side of the tab-bar was always blank.

microKanren Reading

4 Jul 2022

μKanren (“micro-Kanren”) is a tiny, embeddable logic programming language. It’s easy to understand and implement in almost any language. It’s a great case study of an embedded language: unlike other common “embedded” languages like SQL or regex, which normally are represented as just plain-old strings, μKanren takes more advantage of the host language’s features.

I recommend reading the original paper: it’s short, well-written, and easy to understand.

I did a write-up which you can read on Codeberg. The README is my set of notes that I made while walking through the implementation of the paper, and the repository contains an implementation in Racket. I’ve included some fun use cases like a type checker/inference engine that takes up only 37 lines of code!

...

FreeBSD on a Raspberry Pi 4 with 4GB of RAM

28 Dec 2020

This is the story of how I managed to get FreeBSD running on a Raspberry Pi 4 with 4GB of RAM, though I think the setup story is pretty similar for those with 2GB and 8GB.1

I also managed to get Rust built from source, (kind of) which is nice because the default Rust installer doesn’t seem to work for FreeBSD running on a Raspberry Pi.

...

FreeBSD on a Raspberry Pi

12 Feb 2020

I’m a FreeBSD guy. My first computer was a FreeBSD machine that my dad had running in a closet. I learned how to use Emacs as well as the command line on that black-screen white-text no-mouse interface. That’s how real programmers spend their childhood! 😎 😜

I’ve only heard good things about FreeBSD. While not known as particularly desktop-friendly (various Linux distros win here) I’ve heard tales of its rock-solid stability. I wanted to try running on FreeBSD again, just to see what all the fuss was about.

...

Citations with Pandoc

6 Feb 2019

Today I figured out how to get Pandoc to automatically generate MLA citations for me!

I used Pandoc and the Biblatex bibliography format. What’s nice about this is that you can enter in all the information you know about the source, keep it nice and organized in a file, and then change the citation style on the fly. Imagine if you thought you had to use MLA, but then realized you needed to switch to APA citation styles. You can do that instantly with Pandoc and Biblatex.

...

Mastodon