Projects

Table of Contents

M-λ

This is a programming language implemented in Racket. Specifically, a reflective untyped lambda calculus with call-by-name semantics and first class continuations, which makes apparent some connections between modal logics, metaprogramming, recursion theory, and continuation handling constructs.

The core of the project is a pattern matching interpreter, which makes evaluation order independent of the metalanguage (Racket) by passing and reducing a defunctionalized continuation. The value of the language is theoretical, not practical. It's syntax and semantics are as follows:

RACKET
<sym>   ≡ x: (symbol? x)
<wff> ::= (→ <sym> <wff>)      := abstraction
        | (<wff> <wff>)        := application
        | (□ <wff>)            := quotation
        | (▷ <wff> <wff>)      := quote combination (the "Kleene" operator)
        | (ε <wff>)            := evaluation
        | (ρ <wff>)            := "reset" (continuation delimiter)
        | (σ <wff>)            := "shift" (introduces delimited continuation)
        | (callcc <wff>)       := "control" (introduces global continuation)
        | (dropcc <wff>)       := "abort"   (eliminates global continuation)

The syntax was chosen to reflect an extended Curry-Howard correspondence between modal logic S4 and reflective lamba calculi, with quotation, evaluation, and the Kleene operator giving rise to "code combinators". That correspondence is roughly summarized below:

Code Combinator Modal Formula Axiom
(→ x (→ y (▷ x y))) \(□(A → B) → (□A → □B)\) K
(→ x (ε x)) \(□A → A\) T
(→ x (□ x)) \(□A → □□A\) 4

Some interesting points arise in considering the language.

One is that we can derive an infinite hierarchy of staged Quines, with the base of the hierarchy being:

SCHEME
'(□ ((→ x (▷ x (□ x))) (□ (→ x (▷ x (□ x))))))

Another is that we have two possible routes into recursive computations. This can be demonstrated as follows. First, we define basic arithmetic values with a familiar Church encoding:

SCHEME
(define zero '(→ f (→ x x)))
(define succ '(→ n (→ f (→ x (f ((n f) x))))))

and a basic branching operator:

SCHEME
(define iszero '(→ f ((f (→ z (→ x (→ y y)))) (→ x (→ y x)))))
(define ifzero `((→ p (→ a (→ b ((p a) b)))) ,iszero))

Then we can define addition, recursively, by application of the Y combinator to a function over the numerals:

SCHEME
(define Y '(→ f ((→ g (f (g g))) (→ g (f (g g))))))
(define plus `(→ f (→ n (→ m (((,ifzero n) m) ((f (,prev n)) (,succ m)))))))
(define add-direct `(,Y ,plus))

Alternatively, we can define addition by applying a staged fixpoint to the code of a function over expressions:

SCHEME
(define sfix '(→ e ((→ x ((ε x) x)) (▷ (□ (→ t (→ y (t (▷ y (□ y)))))) e))))
(define splus `(→ e (→ n (→ m (((,ifzero n) m) (((ε e) (,prev n)) (,succ m)))))))
(define add-staged `(,sfix (□ ,splus)))

For some of the theoretical backdrop to this project, see Kleene Second Recursion Theorem: A Functional Pearl (Anonymous, 2018, in Proceedings of the ACM).

nice-org-html

This is an Emacs package (available on Melpa) that generates pretty static websites from Org Mode markup files and user-chosen Emacs themes. Emacs has a built-in mechanism for exporting .org files and publishing projects comprised of linked .org files, but this mechanism generates very basic HTML, with an outdated appearance when rendered in the browser. This package addresses that shortcoming, in part by leveraging the variety of open-source themes available for Emacs, and in part by using schematic s-expressions to complete HTML component templates. The package provides an Org Export backend, a publishing function, and a publishing-function-generating macro, which enable users to customize the look-and-feel of generated web pages by just specifying values for parameters. This package is used, together with the built-in publisher, to generate the website you are viewing now. Customization is achieved by a single macro call:

EMACS-LISP
(nice-org-html-publishing-function
 :theme-alist
 ((dark . spacemacs-dark) (light . spacemacs-light))
 :default-mode dark
 :headline-bullets (:h1 "" :h2 "" :h3 "▷" :h4 "" :h5 "")
 :header
 (("Ewan Townshend" . "home")
  ("About" . "about")
  ("Projects" . "projects")
  ("Thoughts" . "thoughts"))
 :footer
 (("© 2025" . nil)
  ("LinkedIn" . "https://www.linkedin.com/in/ewan-townshend")
  ("GitHub" . "https://github.com/ewantown")
  ("Resumé" . "other/sw-resume.pdf")
  ("Email" . "mailto:ewan@etown.dev")))

Guiser

This is a web application enabling users to design multiple “personas”, and generate and post social media content under the guise of a persona to associated accounts on major social media platforms (LinkedIn, Twitter / X, and Threads). The intent of Guiser was three-fold. On one hand, it is a useful tool for social media marketing, enabling a single marketing professional to masquerade as numerous “organic” content creators. On the other hand, its creation was a prescient commentary on the direction of social media in the wake of programmatically accessible large language models. Finally, as a project, it provided an opportunity to work with technologies that comprise the “backbone” of modern web applications with increasing frequency. In this regard, the application was written in JavaScript and TypeScript, uses the MERN stack, and has four OAuth integrations (Google, LinkedIn, Meta, Twitter/X), five external REST API integrations (LinkedIn, Meta, Twitter/X, MongoDB Atlas), and one internal REST API to handle client-server transactions.

search-factory

This is a Racket library providing very general data structures for defining problems with graphs, and higher-order functions that produce deterministic and stochastic graph search functions to client specifications. The library abstracts away points of variance among graph search procedures, including many outlined in Russell and Norvig's Artificial Intelligence: A Modern Approach, as functions passed as closures to more general parameterized search procedure constructors. Use of the library facillitates fine-grained specification of strategies for solving basic tree and graph search problems, constraint satisfaction problems (including 3SAT, etc.), and optimization problems, all within a unified framework.

LifeInteractive

This is a Java implementation of a novel single-player game based on Conway's zero-player Game of Life (a cellular automaton). The non-existence of this variant on Conway's game was a conceptual itch I wanted to scratch. The idea is that a user interacts with a grid of cells ("lifeform") evolving "naturally" from an initial state in accordance with the rules of Conway's game, by controlling an avatar that moves about the grid firing "bullets" and "seeds". If a bullet collides with a live cell, the user gains a point, and the cell is killed, thus influencing evolution of the lifeform. Firing a seed costs the user a point, but if the seed collides with a live cell, a new cell spawns at the point of collision, thus influencing evolution of the lifeform. As a result of these rules, a user's score is maximized by behaviour that "cultivates" the lifeform, rather than extinguishing it. The choice of Java for implementation was due to the relative ease of developing a platform-independent desktop GUI for interacting with a lifeform. The interactive form of the game, with an '80s arcade aesthetic, turned out to actually be quite fun. But more generally, the intent of the program was to serve as a visualized "sandbox" for tinkering with programmatically controlled gameplaying agents.