The classic game Pong, written in lambda calculus, and a thin layer of Rust.

Overview

What?

The good old game Pong, written in lambda calculus, and a thin layer of Rust.

Why?

I was bored.

No, seriously, why?

Everyone keeps saying that lambda calculus and Turing machines are Turing complete and therefore could, theoretically, be used for any computation that can be done. What a bore! I wanted to show it in practice.

Why the Rust layer? (Or, why not do everything in lambda calculus?)

Two reasons, mostly.

First, while lambda calculus is Turing complete, it doesn't have any way of doing I/O, let alone having a GUI.

Second, lambda calculus can, given a state, compute the next one, but -- since it's a pure functional language -- cannot store the state, which is necessary for the game to work.

Also, you'll notice that a native Rust implementation of Pong has also been provided; it's meant for comparing both the code and the programs' performance.

Running

First and foremost, install cargo if you don't have it.

Then, install the lambda_calc interpreter with

$ cargo install lambda_calc

By default, cargo will install the binary to $HOME/.cargo/bin. Make sure to add that directory to your PATH environment variable, or install somewhere included in your PATH, using the --root option (run man cargo-install for details).

Then, install SDL2 if you don't have it already. On Debian-based systems, simply run

$ sudo apt install libsdl2-2.0-0 libsdl2-dev

Clone this repository and go to its root. From there, run the lambda calculus pong with

$ cargo run --release -- -l lambda/pong.txt

And the native Rust implementation with

$ cargo run --release -- -n

The --release flag instructs Rust to optimize the resulting program. (It's slow enough with that, let alone without it...)

How?

In a nutshell:

The main program spawns a lambda calculus interpreter process, which parses the definitions from a source file, and keeps waiting for input. The lambda calculus source must define the following symbols, which compute

  • initState: the first state;

  • nextState: the next game state, given its current state and the user input;

  • gameOver: whether the game is over, given its state;

  • getScreenRects: the list of rectangles that must be rendered, given the game state.

The main program then begins to supply input to the lambda calculus interpreter process. At the very first frame, the first state is obtained with initState. Then, every frame,

  • the next state is computed with nextState;

  • it's decided whether to close the window, with gameOver's result;

  • the rectangles given by getScreenRects are rendered.

The game state is simply stored and never parsed in any way; only the lambda calculus functions are required to understand its representation.

However, the results of gameOver and getScreenRects must be parsed, and so must be in an encoding understood both by the main program and the lambda calculus code. Booleans use Church enconding, while the list of rectangles is a Church list, where each rectangle is a 4-tuple containing the integers (x, y, w, h), whose meanings can be seen here. In turn, each integer uses a custom encoding.

Performance

In a modern i5, the lambda calculus implementation (-l) takes a bit more than 20 seconds to start, but has an ok-ish frame rate and is actually playable.

You might also like...
Serverless setup for activity pub (using lambda+dynamodb) in Rust

Serverless ActivityPub About This is an experiment to have free/cheaper activitypub instances running on AWS (making use of free tiers as much as poss

A tool to run web applications on AWS Lambda without changing code.
A tool to run web applications on AWS Lambda without changing code.

AWS Lambda Adapter A tool to run web applications on AWS Lambda without changing code. How does it work? AWS Lambda Adapter supports AWS Lambda functi

A lambda extension to hot reload parameters from SSM Parameter Store, Secrets Manager, DynamoDB, AppConfig

A lambda extension to hot reload parameters from SSM Parameter Store, Secrets Manager, DynamoDB, AppConfig

A high-performance Lambda authorizer for API Gateway that can validate OIDC tokens
A high-performance Lambda authorizer for API Gateway that can validate OIDC tokens

oidc-authorizer A high-performance token-based API Gateway authorizer Lambda that can validate OIDC-issued JWT tokens. 🤌 Use case This project provid

Hardware Abstraction Layer for AVR microcontrollers and common boards

avr-hal Hardware Abstraction Layer for AVR microcontrollers and common boards (for example Arduino). Based on the avr-device crate. This is a new vers

Tracing layer to quickly inspect spans and events

tracing-texray First, a word of warning: This is alpha software. Don't run this in prod or anywhere where a panic would ruin your day. tracing-texray

Rust Hardware Abstraction Layer (HAL) crate for the Vorago VA108xx family of MCUs

HAL for the Vorago VA108xx MCU family This repository contains the Hardware Abstraction Layer (HAL), which is an additional hardware abstraction on to

Garden monitoring system using m328p Arduino Uno boards. 100% Rust [no_std] using the avr hardware abstraction layer (avr-hal)

uno-revive-rs References Arduino Garden Controller Roadmap uno-revive-rs: roadmap Components & Controllers 1-2 Uno R3 m328p Soil moisture sensor: m328

A tracing layer for macOS/iOS's `oslog`

tracing_oslog This is a tracing layer for the Apple OS logging framework. Activities are used to handle spans, Example use tracing_oslog::OsLogger; l

Owner
null
cargo-lambda is a Cargo subcommand to help you work with AWS Lambda.

cargo-lambda cargo-lambda is a Cargo subcommand to help you work with AWS Lambda. The new subcommand creates a basic Rust package from a well defined

null 184 Jan 5, 2023
The lambda-chaos-extension allows you to inject faults into Lambda functions without modifying the function code.

Chaos Extension - Seamless, Universal & Lightning-Fast The lambda-chaos-extension allows you to inject faults into Lambda functions without modifying

AWS CLI Tools 5 Aug 2, 2023
λ-calculus parser made by rust

Lambda Calculus Parser This is a parser for λ-calculus expressions. It takes a λ-terms as input, parses it and returns a JSON representation of the te

Lee ByeongJun 4 Apr 17, 2023
Untyped Concatenative Calculus

Untyped Concatenative Calculus The untyped concatenative calculus, implemented in Rust. A toy programming language and prototype for Dawn. Native REPL

The Dawn Programming Language 16 Aug 23, 2022
A thin-hypervisor that runs on aarch64 CPUs.

How to build the hypervisor By Rust toolchain (TBD) By docker Requirements Docker (Tested by Docker version 20.10.8, build 3967b7d28e) I tested by non

RIKEN R-CCS 54 Dec 12, 2022
Thin wrapper around [`tokio::process`] to make it streamable

This library provide ProcessExt to create your own custom process

null 4 Jun 25, 2022
Examples of how to use Rust with Serverless Framework, Lambda, API Gateway v1 and v2, SQS, GraphQL, etc

Rust Serverless Examples All examples live in their own directories: project: there is nothing here, just a simple cargo new project_name with a custo

Fernando Daciuk 9 Dec 17, 2022
📦 🚀 a smooth-talking smuggler of Rust HTTP functions into AWS lambda

lando ?? maintenance mode ahead ?? As of this announcement AWS not officialy supports Rust through this project. As mentioned below this projects goal

Doug Tangren 68 Dec 7, 2021
A Rust runtime for AWS Lambda

Rust Runtime for AWS Lambda This package makes it easy to run AWS Lambda Functions written in Rust. This workspace includes multiple crates: lambda-ru

Amazon Web Services - Labs 2.4k Dec 29, 2022
Rust Lambda Extension for any Runtime to preload SSM Parameters as 🔐 Secure Environment Variables!

?? Crypteia Rust Lambda Extension for any Runtime to preload SSM Parameters as Secure Environment Variables! Super fast and only performaned once duri

Custom Ink 34 Jan 7, 2023