Chris Collins

Lab · Playground

Rust and Go playground

Edit Rust and Go here; they are compiled and run by the official Rust and Go playgrounds, with the output shown in the page.

Code blocks on this page are editable — change them and press Run.

Rust and Go compilers are too large to run inside a browser, so these blocks send your code to the official playgrounds — play.rust-lang.org and go.dev/play — and show what comes back. That is the only time code on this site leaves your browser; the Open in links take the same code to the full playground.

Rust

Ownership, iterators, and traits
use std::collections::HashMap;
use std::fmt;

#[derive(Debug, Clone, Copy, PartialEq)]
enum Shape { Circle { r: f64 }, Rect { w: f64, h: f64 } }

trait Area { fn area(&self) -> f64; }

impl Area for Shape {
    fn area(&self) -> f64 {
        match *self {
            Shape::Circle { r } => std::f64::consts::PI * r * r,
            Shape::Rect { w, h } => w * h,
        }
    }
}

impl fmt::Display for Shape {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Shape::Circle { r } => write!(f, "circle(r={r})"),
            Shape::Rect { w, h } => write!(f, "rect({w}×{h})"),
        }
    }
}

fn main() {
    let shapes = vec![Shape::Circle { r: 1.0 }, Shape::Rect { w: 2.0, h: 3.0 }, Shape::Circle { r: 0.5 }];
    let total: f64 = shapes.iter().map(Area::area).sum();
    println!("total area = {total:.3}");

    let biggest = shapes.iter().max_by(|a, b| a.area().total_cmp(&b.area())).unwrap();
    println!("biggest    = {biggest}");

    let mut counts: HashMap<&str, usize> = HashMap::new();
    for s in &shapes {
        *counts.entry(match s { Shape::Circle { .. } => "circle", Shape::Rect { .. } => "rect" }).or_default() += 1;
    }
    let mut keys: Vec<_> = counts.into_iter().collect();
    keys.sort();
    println!("counts     = {keys:?}");
}

Go

Goroutines and channels: a concurrent prime sieve
package main

import "fmt"

func generate(ch chan<- int) {
	for i := 2; ; i++ {
		ch <- i
	}
}

func filter(in <-chan int, out chan<- int, prime int) {
	for {
		if i := <-in; i%prime != 0 {
			out <- i
		}
	}
}

func main() {
	ch := make(chan int)
	go generate(ch)
	for i := 0; i < 15; i++ {
		prime := <-ch
		fmt.Print(prime, " ")
		next := make(chan int)
		go filter(ch, next, prime)
		ch = next
	}
	fmt.Println()
}
Generics
package main

import (
	"cmp"
	"fmt"
	"slices"
)

func Map[T, U any](xs []T, f func(T) U) []U {
	out := make([]U, 0, len(xs))
	for _, x := range xs {
		out = append(out, f(x))
	}
	return out
}

func MaxBy[T any, K cmp.Ordered](xs []T, key func(T) K) T {
	return slices.MaxFunc(xs, func(a, b T) int { return cmp.Compare(key(a), key(b)) })
}

func main() {
	words := []string{"gopher", "go", "generics", "goroutine"}
	fmt.Println(Map(words, func(s string) int { return len(s) }))
	fmt.Println(MaxBy(words, func(s string) int { return len(s) }))
}