100 Helloslanguages
Home / Languages / Wren

Wren

2013fraglet
scriptingobject-orientedscripting.wren
docker run --rm --platform="linux/amd64" 100hellos/wren:latest

MCP + fragletc

MCPstdinargs
This language supports code execution via MCP and the fragletc CLI. Stdin piping and argument passing are both supported.
Install fragletc →

Wren is a small, fast, class-based concurrent scripting language that combines the simplicity of Lua with the power of class-based object-oriented programming. It was created by Bob Nystrom, who is also known for his work on the Dart programming language and the book "Game Programming Patterns".

Language Features

  • Class-based Object-Oriented: Unlike prototype-based languages like JavaScript, Wren uses traditional class-based inheritance
  • Fiber-based Concurrency: Built-in support for cooperative multitasking using fibers
  • Small and Fast: The entire VM is only a few thousand lines of C code
  • Statically-typed Methods: Method calls are resolved at compile time for better performance
  • Clean, Readable Syntax: Influenced by languages like Ruby and Python
  • Embeddable: Designed to be embedded in applications, similar to Lua

Hello World Explanation

The Wren Hello World program is remarkably simple:

System.print("Hello World!")

The System class provides basic system functionality, and print is a static method that outputs text to standard output. Unlike many languages, Wren doesn't require a main function or any boilerplate code.

History

Wren was created by Bob Nystrom and first released in 2013. It was designed to be a modern alternative to Lua for game development and other embedded scripting needs. The language combines the simplicity and small footprint of Lua with more familiar class-based object-oriented programming concepts.

Further Exploration

Hello World

#!/bin/sh
wren /hello-world/hello-world.wren "$@"

Coding Guide

Language Version

Wren (latest from wren-cli repository)

Execution Model

  • Interpreted, runs directly from source
  • Top-level code executes immediately
  • No explicit main function required
  • Class-based object-oriented programming

Key Characteristics

  • Class-based inheritance (not prototype-based)
  • Dynamic typing
  • Case-sensitive
  • Clean, Ruby/Python-influenced syntax
  • Fiber-based concurrency support
  • Statically-typed method calls (resolved at compile time)

Fragment Authoring

Write valid Wren code. Your fragment becomes the script body. Code executes at the top level, so classes, functions, and statements run immediately in order.

Available Libraries

Standard Wren libraries are available:

  • System - system operations (print, clock, etc.)
  • Math - mathematical functions
  • Random - random number generation
  • IO - file I/O operations
  • OS - operating system interface
  • Meta - reflection and metaprogramming

Common Patterns

  • Print: System.print("message")
  • Classes: class MyClass { }
  • Methods: methodName { } or methodName(arg) { }
  • Variables: var name = value
  • Lists: [1, 2, 3]
  • Maps: {"key": "value"}
  • String interpolation: "Hello, %(name)!"
  • Fibers: Fiber.new { }

Examples

// Simple output
System.print("Hello, World!")

// Class definition
class Person {
  construct new(name) {
    _name = name
  }

  greet {
    System.print("Hello, %(_name)!")
  }
}

var person = Person.new("Alice")
person.greet

// List processing
var numbers = [1, 2, 3, 4, 5]
var sum = 0
for (number in numbers) {
  sum = sum + number
}
System.print("Sum: %(sum)")

// Map operations
var fruits = {
  "apple": 5,
  "banana": 3
}
System.print("Apples: %(fruits["apple"])")

// String interpolation
var name = "World"
System.print("Hello, %(name)!")

// Function-like methods
class Calculator {
  static add(a, b) { a + b }
  static multiply(a, b) { a * b }
}

System.print("5 + 10 = %(Calculator.add(5, 10))")
System.print("5 * 10 = %(Calculator.multiply(5, 10))")

Caveats

  • Classes must be defined before use
  • Method calls are resolved at compile time
  • Use var for local variables
  • Private fields start with underscore (_field)
  • String interpolation uses %(expression) syntax
  • Fibers are cooperative (yield control explicitly)

Fraglet Scripts

Echo Args

#!/usr/bin/env -S fragletc --vein=wren
import "os" for Process
System.print("Args: " + Process.arguments.join(" "))

Stdin Upper

#!/usr/bin/env -S fragletc --vein=wren
import "io" for Stdin
var line = Stdin.readLine()
var upper = ""
for (c in line.codePoints) {
  if (c >= 97 && c <= 122) {
    upper = upper + String.fromCodePoint(c - 32)
  } else {
    upper = upper + String.fromCodePoint(c)
  }
}
System.print(upper)

Test

#!/usr/bin/env -S fragletc --vein=wren
// In a world where every character is secretly a quantum particle...
class QuantumLetter {
  construct new(char, spin) {
    _char = char
    _spin = spin // Up or down, who knows until we observe it!
  }

  // Schrödinger's toString - collapses the quantum state
  toString { _spin ? _char : (_char.bytes[0] + 1).toString }
}

class QuantumMessage {
  construct new() {
    // Initialize our quantum letters in superposition
    _letters = [
      QuantumLetter.new("H", true),
      QuantumLetter.new("e", true),
      QuantumLetter.new("l", true),
      QuantumLetter.new("l", true),
      QuantumLetter.new("o", true),
      QuantumLetter.new(" ", true),
      QuantumLetter.new("W", true),
      QuantumLetter.new("o", true),
      QuantumLetter.new("r", true),
      QuantumLetter.new("l", true),
      QuantumLetter.new("d", true),
      QuantumLetter.new("!", true)
    ]
  }

  // Collapse the quantum superposition
  observe { _letters.map { |l| l.toString }.join("") }
}

// The quantum measurement that changes everything... or does it?
System.print(QuantumMessage.new().observe)

Connections

influenced by

Container Info

image100hellos/wren:latest
build scheduleWednesday
fragletenabled