Wren
2013fragletMCP + 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 functionsRandom- random number generationIO- file I/O operationsOS- operating system interfaceMeta- reflection and metaprogramming
Common Patterns
- Print:
System.print("message") - Classes:
class MyClass { } - Methods:
methodName { }ormethodName(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
varfor 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)