Working examples from the Lambda Smalltalk examples/ directory. Each file is executable as-is.
Run any example: lambda-st run examples/01_basics.st
01_basics.st
"
Lambda Smalltalk - Basics
Smalltalk is SVO: Subject Verb Object
'hello' size
S V
File read: 'config.txt'
S V O
Just tell WHO to do WHAT.
"
"--- Print with newline ---"
'Hello, World!' printNl.
"--- Print without newline ---"
'No ' print.
'newline' print.
'' printNl.
"--- Variables ---"
| x y |
x := 10.
y := 20.
(x + y) printNl.
"--- String size ---"
'hello' size printNl.
"--- String uppercase ---"
'hello' asUppercase printNl.
"--- String lowercase ---"
'HELLO' asLowercase printNl.
"--- String trim ---"
' hello ' trim printNl.
"--- String concatenate ---"
('Hello' , ' ' , 'World') printNl.
"--- String repeat ---"
('-' * 10) printNl.
"--- String replace ---"
('hello' replaceAll: 'l' with: 'L') printNl.
"--- Number to string ---"
42 asString printNl.
"--- String to integer ---"
('123' asInteger + 10) printNl.
"--- String to number ---"
'3.14' asNumber printNl.
"--- Arithmetic ---"
(10 + 5) printNl.
(10 - 5) printNl.
(10 * 5) printNl.
(10 / 5) printNl.
(10 / 3) printNl.
"--- Exact Fraction ---"
((1 / 3) * 3) printNl.
"--- LargeInteger (overflow) ---"
(2147483647 + 1) printNl.
(1000000000 * 1000000000) printNl.
"--- Modulo ---"
(7 \\ 2) printNl.
"--- Floor division ---"
(-7 // 2) printNl.
"--- Power ---"
(2 raisedTo: 10) printNl.
"--- Absolute value ---"
(-5) abs printNl.
"--- Square root ---"
16 sqrt printNl.
"--- Min / Max ---"
(3 min: 7) printNl.
(3 max: 7) printNl.
'=== Done! ===' printNl.
02_collections.st
"
Lambda Smalltalk - Collections
Smalltalk is SVO: Subject Verb Object
array size - Array, tell me your size
array first - Array, give me your first element
array select: [] - Array, select elements matching this
Just tell WHO to do WHAT.
"
"Load high-level collection methods"
FileStream fileIn: 'lib/Collections.st'.
"--- Array literal ---"
#(1 2 3) printNl.
"--- Array size ---"
#(10 20 30) size printNl.
"--- Array first ---"
#('a' 'b' 'c') first printNl.
"--- Array last ---"
#(1 2 3 4 5) last printNl.
"--- Array at index (1-based) ---"
| arr |
arr := #(10 20 30 40 50).
(arr at: 3) printNl.
"--- Create array of size N ---"
| a |
a := Array new: 3.
a at: 1 put: 'x'.
a at: 2 put: 'y'.
a at: 3 put: 'z'.
a printNl.
"--- Iterate: do ---"
| sum |
sum := 0.
#(1 2 3 4 5) do: [ :each | sum := sum + each ].
sum printNl.
"--- Transform: collect (map) ---"
(#(1 2 3) collect: [ :x | x * 2 ]) printNl.
"--- Filter: select ---"
(#(1 2 3 4 5 6) select: [ :x | x > 3 ]) printNl.
"--- Filter: reject ---"
(#(1 2 3 4 5 6) reject: [ :x | x > 3 ]) printNl.
"--- Find first match: detect ---"
(#(1 2 3 4 5) detect: [ :x | x > 3 ]) printNl.
"--- Find index: indexOf ---"
(#(1 2 3) indexOf: 2) printNl.
"--- Check contains: includes ---"
(#(1 2 3) includes: 2) printNl.
"--- Reduce: inject:into ---"
(#(1 2 3 4 5) inject: 0 into: [ :acc :x | acc + x ]) printNl.
(#(1 2 3 4 5) inject: 1 into: [ :acc :x | acc * x ]) printNl.
"--- Sum ---"
#(1 2 3 4 5) sum printNl.
"--- Sort ---"
#(3 1 4 1 5 9) sort printNl.
"--- Reverse ---"
#(1 2 3) reverse printNl.
"--- Sort by: sortBy ---"
(#(3 1 4 1 5) sortBy: [ :a :b | a < b ]) printNl.
"--- Unique ---"
#(1 2 2 3 3 3) unique printNl.
"--- Flatten ---"
#(#(1 2) #(3 4) #(5)) flatten printNl.
"--- Join ---"
(#('a' 'b' 'c') join: '-') printNl.
"--- Is empty ---"
#() isEmpty printNl.
#(1) isEmpty printNl.
"--- Max / Min ---"
#(3 1 4 1 5) max printNl.
#(3 1 4 1 5) min printNl.
"--- sumOf: / maxOf: / minOf: (block version) ---"
| people |
people := #(#('Alice' 30) #('Bob' 25) #('Carol' 35)).
(people sumOf: [:p | p at: 2]) printNl. "=> 90"
(people maxOf: [:p | p at: 2]) printNl. "=> 35"
(people minOf: [:p | p at: 2]) printNl. "=> 25"
"--- Average ---"
#(10 20 30 40 50) average printNl.
"--- Iterate with index: doWithIndex ---"
#('a' 'b' 'c') doWithIndex: [ :elem :idx |
(idx asString , ': ' , elem) printNl.
].
"--- Take first N: take ---"
(#(1 2 3 4 5) take: 3) printNl.
"--- Drop first N: drop ---"
(#(1 2 3 4 5) drop: 2) printNl.
"--- All but first: allButFirst ---"
#(1 2 3 4 5) allButFirst printNl.
"--- All but last: allButLast ---"
#(1 2 3 4 5) allButLast printNl.
"--- Copy with element: copyWith ---"
(#(1 2 3) copyWith: 4) printNl.
"--- Copy without element: copyWithout ---"
(#(1 2 3 2 4 2) copyWithout: 2) printNl.
"--- Partition by predicate: partition ---"
(#(1 2 3 4 5 6) partition: [ :x | x > 3 ]) printNl.
"--- Group by key: groupBy ---"
| grouped |
grouped := #(1 2 3 4 5 6) groupBy: [ :x | x \\ 2 ].
grouped keys printNl.
(grouped at: '0') printNl.
(grouped at: '1') printNl.
"--- Zip two arrays: zip ---"
(#(1 2 3) zip: #('a' 'b' 'c')) printNl.
"--- Split into chunks: chunks ---"
(#(1 2 3 4 5) chunks: 2) printNl.
"--- Iterate with separator: do:separatedBy ---"
#(1 2 3) do: [ :x | x print ] separatedBy: [ ', ' print ].
'' printNl.
"--- ifEmpty: / ifNotEmpty: ---"
#() ifEmpty: [ 'Empty array' printNl ].
#(1 2 3) ifNotEmpty: [ :arr | ('Size: ' , arr size asString) printNl ].
"Returns self if condition not met"
| result |
result := #(1 2 3) ifEmpty: [ 'was empty' ].
result printNl. "=> #(1 2 3)"
"--- count: ---"
(#(1 2 3 4 5) count: [ :x | x > 2 ]) printNl. "=> 3"
"--- String isBlank / ifBlank: / ifNotBlank: ---"
'' isBlank printNl. "=> true"
' ' isBlank printNl. "=> true"
'hello' isBlank printNl. "=> false"
| name |
name := ''.
name ifBlank: [ 'Using default name' printNl ].
name := 'Alice'.
name ifNotBlank: [ :n | ('Hello, ' , n) printNl ].
'=== Done! ===' printNl.
03_control_flow.st
"
Lambda Smalltalk - Control Flow
Smalltalk is SVO: Subject Verb Object
(x > 0) ifTrue: [ ... ]
S V O
5 timesRepeat: [ ... ]
S V O
Just tell WHO to do WHAT.
"
"--- If true ---"
(3 > 0) ifTrue: [ 'positive' printNl ].
"--- If false ---"
(3 < 0) ifFalse: [ 'not negative' printNl ].
"--- If-then-else ---"
| x |
x := 10.
(x > 5)
ifTrue: [ 'big' printNl ]
ifFalse: [ 'small' printNl ].
"--- Equality ---"
(5 = 5) printNl.
(5 ~= 3) printNl.
"--- Comparison ---"
(3 < 5) printNl.
(5 > 3) printNl.
(3 <= 3) printNl.
(5 >= 5) printNl.
"--- Logical AND / OR / NOT ---"
(true & true) printNl.
(true | false) printNl.
true not printNl.
"--- Repeat N times ---"
| count |
count := 0.
5 timesRepeat: [ count := count + 1 ].
count printNl.
"--- For loop: to:do ---"
| sum |
sum := 0.
1 to: 10 do: [ :i | sum := sum + i ].
sum printNl.
"--- For loop with step: to:by:do ---"
| evens |
evens := 0.
2 to: 10 by: 2 do: [ :i | evens := evens + i ].
evens printNl.
"--- While true ---"
| n |
n := 1.
[ n < 100 ] whileTrue: [ n := n * 2 ].
n printNl.
"--- While false ---"
| m |
m := 10.
[ m = 0 ] whileFalse: [ m := m - 1 ].
m printNl.
"--- If nil ---"
| val |
val := nil.
val ifNil: [ 'was nil' printNl ].
"--- If not nil ---"
val := 42.
val ifNotNil: [ 'not nil' printNl ].
"--- Nested if-else ---"
| score grade |
score := 85.
grade := (score >= 90)
ifTrue: [ 'A' ]
ifFalse: [
(score >= 80)
ifTrue: [ 'B' ]
ifFalse: [ 'C' ]
].
grade printNl.
'=== Done! ===' printNl.
04_blocks.st
"
Lambda Smalltalk - Blocks and Closures
Blocks are Smalltalk's lambdas/closures.
They are first-class objects that hold code.
block value - Block, execute yourself
block value: 5 - Block, execute with argument 5
array collect: block - Array, transform using this block
Just tell WHO to do WHAT.
"
"--- Create and execute a block ---"
| b |
b := [ 'Hello from block' printNl ].
b value.
"--- Block with one argument ---"
| add1 |
add1 := [ :x | x + 1 ].
(add1 value: 5) printNl.
"--- Block with two arguments ---"
| add |
add := [ :a :b | a + b ].
(add value: 3 value: 4) printNl.
"--- Closure: captures outer variable ---"
| counter block |
counter := 0.
block := [ counter := counter + 1. counter ].
(block value) printNl.
(block value) printNl.
(block value) printNl.
"--- Block as function ---"
| square |
square := [ :n | n * n ].
(square value: 7) printNl.
"--- Block as callback ---"
| nums doubled |
nums := #(1 2 3 4 5).
doubled := nums collect: [ :x | x * 2 ].
doubled printNl.
"--- Nested blocks ---"
| outer |
outer := [
| inner |
inner := [ 'inner' ].
inner value
].
(outer value) printNl.
"--- Higher-order: block takes block ---"
| twice result |
twice := [ :f :x | f value: (f value: x) ].
result := twice value: [ :n | n + 1 ] value: 5.
result printNl.
'=== Done! ===' printNl.
05_classes.st
"
Lambda Smalltalk - Classes
Smalltalk is SVO: Subject Verb Object
Object subclass: #Counter ... - Object, create a subclass named Counter
Counter new - Counter, create a new instance
counter inc - Counter instance, increment yourself
Just tell WHO to do WHAT.
"
"--- Define a class ---"
Object subclass: #Counter instanceVariableNames: 'value'.
"--- Define methods ---"
Counter >> initialize
value := 0.
!
Counter >> inc
value := value + 1.
^ value
!
Counter >> value
^ value
!
"--- Create and use instance ---"
| c |
c := Counter new.
c inc printNl.
c inc printNl.
c inc printNl.
c value printNl.
"--- Built-in: Point ---"
| p |
p := 3 @ 4.
p x printNl.
p y printNl.
p printNl.
'=== Done! ===' printNl.
06_file_io.st
"
Lambda Smalltalk - File I/O
Smalltalk is SVO: Subject Verb Object
File read: 'config.txt' - File, read this path (returns string)
File write: 'out.txt' content: x - File, write x to this path
File exists: 'config.txt' - File, does this path exist?
FileStream openRead: path do: [:stream|..] - FileStream, open and auto-close (safe)
Just tell WHO to do WHAT.
"
"--- Read file ---"
| content |
content := File read: 'examples/06_file_io.st'.
(content size) printNl.
"--- Write file ---"
File write: 'examples/temp.txt' content: 'Hello, File!'.
(File read: 'examples/temp.txt') printNl.
"--- Check file exists ---"
(File exists: 'examples/temp.txt') printNl.
(File exists: 'examples/no_such_file.xyz') printNl.
"--- Glob pattern ---"
| files |
files := File glob: 'examples/*.st'.
files size printNl.
"--- Delete file ---"
(File delete: 'examples/temp.txt') printNl.
(File exists: 'examples/temp.txt') printNl.
"--- Safe file reading with openRead:do: ---"
"Auto-closes file even on error - no ensure: needed"
| lineCount |
lineCount := 0.
FileStream openRead: 'examples/06_file_io.st' do: [:stream |
[stream atEnd] whileFalse: [
stream nextLine.
lineCount := lineCount + 1.
]
].
('Lines in this file: ' , lineCount asString) printNl.
'=== Done! ===' printNl.
07_file_in.st
"=== Lambda Smalltalk: FileStream fileIn: ==="
'=== Load library ===' printNl.
FileStream fileIn: 'examples/lib/math.st'.
'=== Use loaded class ===' printNl.
| calc |
calc := Calculator new.
calc setValue: 7.
calc square printNl.
calc value printNl.
'=== Done! ===' printNl.
08_plugins.st
"=== Lambda Smalltalk: Plugin System (FFI) ==="
"Load and call native plugins written in Rust/C (.dll/.so/.dylib)"
"=== Load plugin ==="
'Loading math plugin...' printNl.
| pluginName |
pluginName := Plugin load: 'examples/plugins/math_plugin/target/release/math_plugin.dll'.
'Loaded: ' print. pluginName printNl.
"=== List plugins and functions ==="
'Loaded plugins: ' print. (Plugin list) printNl.
'Available functions: ' print. (Plugin functions: 'math') printNl.
"=== Call plugin functions ==="
| r |
'factorial(5) = ' print.
r := Plugin call: 'math' function: 'factorial' args: #(5).
r printNl.
'factorial(10) = ' print.
r := Plugin call: 'math' function: 'factorial' args: #(10).
r printNl.
'fibonacci(10) = ' print.
r := Plugin call: 'math' function: 'fibonacci' args: #(10).
r printNl.
'gcd(48, 18) = ' print.
r := Plugin call: 'math' function: 'gcd' args: #(48 18).
r printNl.
'is_prime(17) = ' print.
r := Plugin call: 'math' function: 'is_prime' args: #(17).
r printNl.
'is_prime(15) = ' print.
r := Plugin call: 'math' function: 'is_prime' args: #(15).
r printNl.
'=== Done! ===' printNl.
09_modules.st
"=== Module System Example ==="
"Lambda Smalltalk supports a module system for namespace management."
"--- Basic Usage (without explicit modules) ---"
"When no module is declared, all classes are in the 'Core' module."
"This maintains backward compatibility with existing code."
Object subclass: #SimplePoint instanceVariableNames: 'x y'.
SimplePoint >> x
^x
!
SimplePoint >> y
^y
!
SimplePoint >> x: aValue
x := aValue
!
SimplePoint >> y: aValue
y := aValue
!
SimplePoint >> initialize
x := 0. y := 0
!
|p|
p := SimplePoint new.
p x: 10.
p y: 20.
'SimplePoint x:' printNl.
p x printNl.
'SimplePoint y:' printNl.
p y printNl.
"--- Module Import ---"
"Import modules from lib/{ModuleName}/{ModuleName}.st"
"The module is auto-loaded on first import."
Module import: 'CodeGen'.
"Now we can use String extensions defined in CodeGen module"
'camelToSnake test:' printNl.
('myVariableName' camelToSnake) printNl.
'snakeToCamel test:' printNl.
('my_variable_name' snakeToCamel) printNl.
"--- Module Definition ---"
"In a module file (e.g., lib/MyLib/MyLib.st):"
"
Module name: 'MyLib'.
Module export: #(PublicClass1 PublicClass2).
Object subclass: #PublicClass1 instanceVariableNames: ''.
Object subclass: #PrivateHelper instanceVariableNames: ''.
"
'=== Module example done ===' printNl.
10_stream_fusion.st
"
Lambda Smalltalk - Streaming I/O Examples
Demonstrates efficient file processing using linesDo: with inline transformation.
This approach uses constant memory regardless of file size.
"
'=== Streaming I/O Examples ===' printNl.
'' printNl.
" ============================================ "
" Example 1: Basic linesDo: with transformation "
" ============================================ "
'--- Example 1: Filter and transform lines ---' printNl.
" Create test file "
File write: 'test_stream.txt' content: 'hello
world
lambda
smalltalk'.
" Process with inline transformation "
'Streaming (filter + uppercase):' printNl.
'test_stream.txt' linesDo: [:line |
(line size > 4) ifTrue: [
(' ' , line asUppercase) printNl.
].
].
'' printNl.
" ============================================ "
" Example 2: Counting lines "
" ============================================ "
'--- Example 2: Count lines ---' printNl.
| count |
count := 0.
'test_stream.txt' linesDo: [:line |
count := count + 1.
].
('Total lines: ' , count asString) printNl.
'' printNl.
" ============================================ "
" Example 3: Accumulating results "
" ============================================ "
'--- Example 3: Sum line lengths ---' printNl.
| totalLength |
totalLength := 0.
'test_stream.txt' linesDo: [:line |
totalLength := totalLength + line size.
].
('Total characters: ' , totalLength asString) printNl.
'' printNl.
" ============================================ "
" Example 4: Manual stream control "
" ============================================ "
'--- Example 4: Manual iteration ---' printNl.
File write: 'mixed.txt' content: 'apple
banana
cherry
date
elderberry
fig
grape'.
| stream line |
stream := FileStream openRead: 'mixed.txt'.
'Lines longer than 4 characters (uppercase):' printNl.
[ stream atEnd ] whileFalse: [
line := stream nextLine.
(line size > 4) ifTrue: [
(' ' , line asUppercase) printNl.
].
].
stream close.
'' printNl.
" ============================================ "
" Example 5: Comparison with eager loading "
" ============================================ "
'--- Example 5: Eager vs Streaming ---' printNl.
'Eager (loads entire file into memory):' printNl.
| lines |
lines := (File read: 'mixed.txt') lines.
lines := lines select: [:line | line size > 4].
lines := lines collect: [:line | line asUppercase].
lines do: [:line | (' ' , line) printNl.].
'' printNl.
'Streaming (constant memory):' printNl.
'mixed.txt' linesDo: [:line |
(line size > 4) ifTrue: [
(' ' , line asUppercase) printNl.
].
].
'' printNl.
'=== Streaming examples completed! ===' printNl.
'Use linesDo: with inline transformation for memory-efficient file processing.' printNl.
11_manual_gc.st
"======================================
Manual Garbage Collection Examples
======================================"
'=== GC Basics ===' printNl.
"Test 1: Create objects without GC"
'Creating 1000 objects...' printNl.
1 to: 1000 do: [:i |
arr := Array new: 10.
arr at: 1 put: i.
].
'Done.' printNl.
'' printNl.
"Test 2: Check heap size"
'=== Heap Size ===' printNl.
'Current heap size: Still need System class methods' printNl.
'' printNl.
"Test 3: GC with live objects"
'=== GC Test ===' printNl.
'Creating some objects that stay alive...' printNl.
liveData := OrderedCollection new.
1 to: 100 do: [:i |
liveData add: (Array new: 5).
].
'Creating temporary objects...' printNl.
1 to: 1000 do: [:i |
temp := Array new: 10.
].
'Live objects: ' print. liveData size printNl.
'' printNl.
"Test 4: Memory usage pattern"
'=== Memory Pattern ===' printNl.
'This test creates and discards objects in a loop' printNl.
1 to: 10 do: [:round |
('Round ' , round asString) printNl.
1 to: 100 do: [:i |
temp := Array new: 20.
temp at: 1 put: i.
].
].
'Done with 10 rounds (1000 temp objects created)' printNl.
'' printNl.
'=== All Tests Complete ===' printNl.
12_utilities.st
"============================================
12_utilities.st - Utility Classes Demo
============================================
Demonstrates: Json, Yaml, Toml, Csv, Env, Random, DateTime, Path, Sha2, Hmac, Base64,
Directory, System, Http, Regex
"
'=== Json ===' printNl.
"Parse JSON string to Dictionary"
| json data |
json := '{"name": "Alice", "age": 30}'.
data := Json parse: json.
('Parsed: ' , (data at: 'name') , ', age=' , (data at: 'age') asString) printNl.
"Generate JSON from Dictionary"
| dict output |
dict := Dict new.
dict at: 'city' put: 'Tokyo'.
dict at: 'population' put: 14000000.
output := Json generate: dict.
('Generated: ' , output) printNl.
'=== Yaml ===' printNl.
"Parse YAML string to Dictionary"
| yaml yamlData |
yaml := 'name: Bob
age: 25
city: Osaka'.
yamlData := Yaml parse: yaml.
('Parsed YAML: name=' , (yamlData at: 'name') , ', age=' , (yamlData at: 'age') asString) printNl.
'=== Toml ===' printNl.
"Parse TOML string to Dictionary"
| toml tomlData |
toml := 'title = "Lambda Smalltalk"
version = "0.1.0"
[author]
name = "Developer"'.
tomlData := Toml parse: toml.
('Parsed TOML: title=' , (tomlData at: 'title')) printNl.
'=== Csv ===' printNl.
"Parse CSV string - returns array of dictionaries (header row becomes keys)"
| csv rows row |
csv := 'name,age,city
Alice,30,Tokyo
Bob,25,Osaka
Charlie,35,Kyoto'.
rows := Csv parse: csv.
('CSV data rows: ' , rows size asString) printNl.
"Each row is a Dictionary with header keys"
row := rows at: 1.
('Row 1: name=' , (row at: 'name') , ', age=' , (row at: 'age') asString , ', city=' , (row at: 'city')) printNl.
row := rows at: 2.
('Row 2: name=' , (row at: 'name') , ', age=' , (row at: 'age') asString , ', city=' , (row at: 'city')) printNl.
"Streaming CSV - memory efficient for large files"
| reader names |
reader := Csv reader: 'product,price
Apple,100
Banana,80
Orange,120'.
names := OrderedCollection new.
[reader atEnd] whileFalse: [
| r |
r := reader next.
r ifNotNil: [names add: (r at: 'product')]
].
('Streamed products: ' , (names join: ', ')) printNl.
'=== Env (Environment Variables) ===' printNl.
"Get environment variable"
| path |
path := Env at: 'PATH'.
(path isNil)
ifTrue: [ 'PATH not set' printNl ]
ifFalse: [ ('PATH length: ' , path size asString) printNl ].
"Set and get environment variable"
Env at: 'LAMBDA_ST_TEST' put: 'hello'.
('LAMBDA_ST_TEST = ' , (Env at: 'LAMBDA_ST_TEST')) printNl.
"List all environment variable names"
| keys |
keys := Env keys.
('Total env vars: ' , keys size asString) printNl.
'=== Random ===' printNl.
"Generate random float [0.0, 1.0)"
| r |
r := Random next.
('Random float: ' , r asString) printNl.
"Generate random integer [0, max)"
| n |
n := Random nextInt: 100.
('Random int (0-99): ' , n asString) printNl.
"Generate 5 random numbers"
5 timesRepeat: [
(Random nextInt: 10) print. ' ' print.
].
'' printNl.
'=== DateTime ===' printNl.
"Get current timestamp"
| now |
now := DateTime now.
('Now (epoch): ' , now asString) printNl.
"Format timestamp"
| formatted |
formatted := now format: '%Y-%m-%d %H:%M:%S'.
('Formatted: ' , formatted) printNl.
"Parse date string (RFC3339 format)"
| parsed |
parsed := DateTime parse: '2025-12-25T10:30:00+00:00'.
(parsed isNil)
ifTrue: [ 'Failed to parse' printNl ]
ifFalse: [ ('Parsed timestamp: ' , parsed asString) printNl ].
'=== Path ===' printNl.
"Extract basename"
| basename |
basename := Path basename: '/home/user/documents/report.pdf'.
('Basename: ' , basename) printNl.
"Extract dirname"
| dirname |
dirname := Path dirname: '/home/user/documents/report.pdf'.
('Dirname: ' , dirname) printNl.
"Extract extension"
| ext |
ext := Path extension: '/home/user/documents/report.pdf'.
('Extension: ' , ext) printNl.
"Join paths"
| joined |
joined := Path join: '/home/user' with: 'documents'.
('Joined: ' , joined) printNl.
"Get absolute path"
| abs |
abs := Path absolute: 'examples'.
('Absolute: ' , abs) printNl.
"Check if path exists"
| exists |
exists := Path exists: '.'.
('Current dir exists: ' , exists asString) printNl.
exists := Path exists: '/nonexistent/path/that/does/not/exist'.
('Nonexistent path exists: ' , exists asString) printNl.
"Check if path is directory"
| isDir |
isDir := Path isDirectory: '.'.
('Current dir is directory: ' , isDir asString) printNl.
isDir := Path isDirectory: 'examples/11_utilities.st'.
('This file is directory: ' , isDir asString) printNl.
'=== Sha2 (Hashing) ===' printNl.
"SHA256 hash"
| hash |
hash := Sha2 sha256: 'hello world'.
('SHA256: ' , hash) printNl.
'=== Hmac (Message Authentication) ===' printNl.
"HMAC-SHA256 for API signatures and webhook verification"
| signature |
signature := Hmac sha256: 'message to sign' key: 'secret-key'.
('HMAC-SHA256: ' , signature) printNl.
"AWS-style signature (simplified example)"
| awsSecret kDate |
awsSecret := 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY'.
kDate := Hmac sha256: '20260110' key: ('AWS4' , awsSecret).
('AWS kDate: ' , kDate) printNl.
'=== Base64 ===' printNl.
"Encode to Base64"
| encoded decoded |
encoded := Base64 encode: 'Hello, Lambda Smalltalk!'.
('Encoded: ' , encoded) printNl.
"Decode from Base64"
decoded := Base64 decode: encoded.
('Decoded: ' , decoded) printNl.
'=== Directory ===' printNl.
"List directory entries"
| entries |
entries := Directory entries: 'examples'.
('Entries in examples/: ' , entries size asString , ' files') printNl.
entries do: [:entry | (' - ' , entry) printNl ].
'=== System ===' printNl.
"Dynamic class lookup (DI pattern)"
| cls obj |
cls := System classNamed: 'OrderedCollection'.
cls printNl. "=> OrderedCollection class"
obj := cls new.
obj add: 'dynamic'.
obj add: 'instantiation'.
('Created via classNamed: ' , obj asArray asString) printNl.
"Non-existent class returns nil"
(System classNamed: 'NonExistent') isNil ifTrue: [
'NonExistent class not found (as expected)' printNl
].
"Platform detection"
('Platform: ' , System platform) printNl.
'=== Regex (String match:) ===' printNl.
"String match: uses regex patterns"
('abc123' match: '\d+') printNl. "=> true (contains digits)"
('abc' match: '\d+') printNl. "=> false (no digits)"
"Email validation"
| email |
email := 'test@example.com'.
(email match: '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$')
ifTrue: [ (email , ' is valid email') printNl ]
ifFalse: [ (email , ' is invalid email') printNl ].
"Pattern matching examples"
('hello123world' match: '[0-9]+') printNl. "=> true"
('no-numbers' match: '[0-9]+') printNl. "=> false"
'=== Http (commented - requires network) ===' printNl.
"HTTP examples are commented out since they require network access.
Uncomment to test with actual endpoints.
--- Basic GET ---
| response |
response := Http get: 'https://httpbin.org/get'.
response printNl.
--- POST with body ---
| postResponse |
postResponse := Http post: 'https://httpbin.org/post' body: jsonBody.
postResponse printNl.
--- GET with custom headers ---
| headers authResponse |
headers := Dict new.
headers at: 'Authorization' put: 'Bearer your-token-here'.
headers at: 'User-Agent' put: 'Lambda-Smalltalk/1.0'.
authResponse := Http get: 'https://api.example.com/data' headers: headers.
authResponse printNl.
--- PUT and DELETE ---
Http put: url body: data headers: headers.
Http delete: url headers: headers.
"
'(Http examples are commented - uncomment to test with network)' printNl.
'=== Done! ===' printNl.
13_transformer.st
"
Transformer Example - Lark-style Source Code Surgery
This example demonstrates how to use the Transformer class for
source code manipulation with automatic gap preservation.
"
"Load the Transformer library"
Module import: 'Transform'.
'=== Transformer Example ===' printNl.
'' printNl.
"--- Example 1: Simple function renaming with Transformer ---"
'Example 1: Rename print() to console_log()' printNl.
| g t source result |
g := Grammar from: '
call: FUNC "(" ARGS ")"
FUNC: /[a-zA-Z_][a-zA-Z0-9_]*/
ARGS: /[^)]*/
%ignore /\s+/
'.
t := Transformer new grammar: g.
"Rule for call: items = [FUNC, '(', ARGS, ')']"
t rule: 'call' do: [:items |
| func args |
func := items at: 1. "FUNC text"
args := items at: 3. "ARGS text (index 2 is '(')"
(func = 'print')
ifTrue: [ 'console_log(' , args , ')' ]
ifFalse: [ func , '(' , args , ')' ]
].
source := 'x = print(hello); y = other(world); z = print(foo)'.
result := t transform: source.
(' Input: ' , source) printNl.
(' Output: ' , result) printNl.
'' printNl.
"--- Example 2: Using Grammar replace:in:with: ---"
'Example 2: Using Grammar replace:in:with:' printNl.
| g2 source2 result2 |
g2 := Grammar from: '
dotcall: RECV "." METHOD "()"
RECV: /[a-z]+/
METHOD: /[a-z]+/
%ignore /./
'.
source2 := '/* comment */ obj.fetch() and client.send() /* end */'.
result2 := Grammar replace: g2 in: source2 with: [:m |
| text |
text := m at: 'text'.
'await ' , text
].
(' Input: ' , source2) printNl.
(' Output: ' , result2) printNl.
'' printNl.
"--- Example 3: Nested transformation ---"
'Example 3: Inspect tree structure' printNl.
| g3 matches |
g3 := Grammar from: '
expr: IDENT "(" IDENT ")"
IDENT: /[a-z]+/
%ignore /\s+/
'.
matches := Grammar findAll: g3 in: 'foo(bar)'.
matches do: [:m |
| tree |
(' text: ' , (m at: 'text')) printNl.
tree := m at: 'tree'.
tree isNil ifFalse: [
(' tree.name: ' , (tree at: 'name')) printNl.
(' tree.children count: ' , (tree at: 'children') size asString) printNl.
].
].
'' printNl.
'=== Done ===' printNl.
14_streaming_io.st
"
Lambda Smalltalk - Streaming I/O Examples
This file demonstrates memory-efficient file processing using FileStream.
Unlike File read: which loads entire files into memory, streaming APIs
process files line-by-line for better performance with large files.
"
'=== Streaming File I/O Examples ===' printNl.
'' printNl.
" ============================================ "
" Example 1: linesDo: - Simple line iteration "
" ============================================ "
'--- Example 1: linesDo: basic usage ---' printNl.
" Create a sample file "
File write: 'sample.txt' content: 'Apple
Banana
Cherry
Date
Elderberry'.
" Process each line without loading entire file "
'sample.txt' linesDo: [:line |
(' * ' , line) printNl.
].
'' printNl.
" ==================================================== "
" Example 2: Manual stream control for complex logic "
" ==================================================== "
'--- Example 2: Manual stream control ---' printNl.
| stream line count |
stream := FileStream openRead: 'sample.txt'.
count := 0.
" Read lines manually with custom logic "
[ stream atEnd ] whileFalse: [
line := stream nextLine.
line ifNotNil: [
count := count + 1.
('Line ' , count asString , ': ' , line) printNl.
].
].
stream close.
('Total lines: ' , count asString) printNl.
'' printNl.
" ============================================== "
" Example 3: Filter lines while streaming "
" ============================================== "
'--- Example 3: Filter long lines ---' printNl.
" Create file with mixed line lengths "
File write: 'mixed.txt' content: 'Short
This is a longer line
Tiny
Another very long line here
OK'.
" Process only lines longer than 10 characters "
'mixed.txt' linesDo: [:line |
(line size > 10) ifTrue: [
(' Long: ' , line) printNl.
].
].
'' printNl.
" ============================================== "
" Example 4: Count matching lines efficiently "
" ============================================== "
'--- Example 4: Count lines containing letter ---' printNl.
| matchCount |
matchCount := 0.
'sample.txt' linesDo: [:line |
" Count lines containing 'e' "
(line includes: 'e') ifTrue: [
matchCount := matchCount + 1.
].
].
('Lines containing "e": ' , matchCount asString) printNl.
'' printNl.
" ============================================== "
" Example 5: Early exit with manual stream "
" ============================================== "
'--- Example 5: Find first match and stop ---' printNl.
stream := FileStream openRead: 'sample.txt'.
| found |
found := false.
[ stream atEnd not and: [ found not ] ] whileTrue: [
line := stream nextLine.
line ifNotNil: [
(line startsWith: 'C') ifTrue: [
('Found line starting with C: ' , line) printNl.
found := true.
].
].
].
stream close.
'' printNl.
" ============================================== "
" Example 6: Compare memory efficiency "
" ============================================== "
'--- Example 6: Memory efficiency comparison ---' printNl.
" Create a larger file "
| content i |
content := ''.
i := 1.
[ i <= 100 ] whileTrue: [
content := content , 'Line ' , i asString , '
'.
i := i + 1.
].
File write: 'large.txt' content: content.
'Rich-man programming (loads entire file):' printNl.
| lines |
lines := (File read: 'large.txt') lines.
(' Loaded ' , lines size asString , ' lines into memory') printNl.
'Streaming approach (processes line-by-line):' printNl.
count := 0.
'large.txt' linesDo: [:ln | count := count + 1. ].
(' Processed ' , count asString , ' lines without loading all') printNl.
'' printNl.
" ============================================== "
" Example 7: Stream with error handling "
" ============================================== "
'--- Example 7: Safe stream usage ---' printNl.
| safeStream |
safeStream := nil.
[
safeStream := FileStream openRead: 'sample.txt'.
" Process file "
safeStream nextLine printNl.
safeStream nextLine printNl.
] ensure: [
" Always close stream even if error occurs "
safeStream ifNotNil: [ safeStream close. ].
'Stream closed safely' printNl.
].
'' printNl.
" ============================================== "
" Cleanup: Remove temporary files "
" ============================================== "
File delete: 'sample.txt'.
File delete: 'mixed.txt'.
File delete: 'large.txt'.
'=== All streaming examples completed! ===' printNl.
15_argparser.st
"
ArgParser - command-line argument parsing
Build CLI tools with flags, options, and positional arguments.
"
Module import: 'CLI'.
| parser result |
"--- Create parser ---"
parser := ArgParser new.
"--- Set program name ---"
parser name: 'demo-tool'.
"--- Set description ---"
parser description: 'A demonstration CLI tool'.
"--- Add boolean flag (--verbose or -v) ---"
parser flag: 'verbose' short: 'v' description: 'Enable verbose output'.
"--- Add option with value (--output FILE or -o FILE) ---"
parser option: 'output' short: 'o' description: 'Output file path'.
"--- Add another option ---"
parser option: 'count' short: 'n' description: 'Number of iterations'.
"--- Add positional argument ---"
parser positional: 'input' description: 'Input file to process'.
"--- Parse command line args ---"
result := parser parse: System args.
"--- Check parse success ---"
result isSuccess ifTrue: [
'=== Parsed Arguments ===' printNl.
"--- Get positional value ---"
'Input: ' print.
((result positional: 'input') ifNil: ['(not set)']) printNl.
"--- Get option value ---"
'Output: ' print.
((result option: 'output') ifNil: ['(not set)']) printNl.
"--- Get flag value (boolean) ---"
'Verbose: ' print.
(result flag: 'verbose') printNl.
'Count: ' print.
((result option: 'count') ifNil: ['(not set)']) printNl.
"--- Get extra arguments ---"
(result extras size > 0) ifTrue: [
'Extra args: ' print.
result extras printNl.
].
] ifFalse: [
"--- Handle parse error ---"
'Error: ' print.
result errorMessage printNl.
"--- Print help ---"
parser printHelp.
].
'=== Done! ===' printNl.
16_parallel_process.st
"========================================
Parallel Process Execution
DevOps-style parallel command execution
========================================"
"Helper to get shell command based on OS"
| shell shellArg isWindows child exitCode pingCmd pollCount processes codes running maxConcurrency items results echoCmd exitCmd args |
isWindows := System platform = 'windows'.
shell := isWindows ifTrue: ['cmd'] ifFalse: ['sh'].
shellArg := isWindows ifTrue: ['/c'] ifFalse: ['-c'].
'=== 1. Basic ChildProcess ===' printNl.
"Spawn a process and wait for it"
args := Array new: 2.
args at: 1 put: shellArg.
args at: 2 put: 'echo Hello from child process'.
child := ChildProcess spawn: shell args: args.
'Spawned process: ' print. child printNl.
"Wait for completion (blocking)"
exitCode := child exitCode.
'Exit code: ' print. exitCode printNl.
'' printNl.
'=== 2. Non-blocking check ===' printNl.
"Spawn a longer-running process"
pingCmd := isWindows
ifTrue: ['ping -n 1 127.0.0.1']
ifFalse: ['ping -c 1 127.0.0.1'].
args := Array new: 2.
args at: 1 put: shellArg.
args at: 2 put: pingCmd.
child := ChildProcess spawn: shell args: args.
'Process spawned, polling...' printNl.
"Poll until finished"
pollCount := 0.
[child isFinished] whileFalse: [
pollCount := pollCount + 1.
(pollCount \\ 50000) = 0 ifTrue: ['..' print].
].
'' printNl.
'Finished after polling ' print. pollCount printNl.
'Exit code: ' print. child exitCode printNl.
'' printNl.
'=== 3. Multiple processes in sequence ===' printNl.
"Run multiple processes and collect results"
processes := OrderedCollection new.
args := Array new: 2. args at: 1 put: shellArg. args at: 2 put: 'echo Job 1'.
processes add: (ChildProcess spawn: shell args: args).
args := Array new: 2. args at: 1 put: shellArg. args at: 2 put: 'echo Job 2'.
processes add: (ChildProcess spawn: shell args: args).
args := Array new: 2. args at: 1 put: shellArg. args at: 2 put: 'echo Job 3'.
processes add: (ChildProcess spawn: shell args: args).
"Wait for all to complete"
codes := processes collect: [:p | p exitCode].
'All jobs completed. Exit codes: ' print. codes printNl.
'' printNl.
'=== 4. Parallel execution with manual pool ===' printNl.
"Run 4 jobs with max 2 concurrent"
maxConcurrency := 2.
running := OrderedCollection new.
results := OrderedCollection new.
items := #('A' 'B' 'C' 'D').
items do: [:item |
"Wait if at max"
[running size >= maxConcurrency] whileTrue: [
running do: [:p |
p isFinished ifTrue: [
results add: p exitCode.
].
].
running := running select: [:p | p isFinished not].
1 to: 5000 do: [:i | ]. "brief busy wait"
].
"Spawn new"
echoCmd := 'echo ', item.
args := Array new: 2. args at: 1 put: shellArg. args at: 2 put: echoCmd.
running add: (ChildProcess spawn: shell args: args).
].
"Wait for remaining"
[running isEmpty not] whileTrue: [
running do: [:p |
p isFinished ifTrue: [results add: p exitCode].
].
running := running select: [:p | p isFinished not].
1 to: 5000 do: [:i | ].
].
'Parallel jobs (max 2 concurrent) completed. Exit codes: ' print. results asArray printNl.
'' printNl.
'=== 5. Error handling ===' printNl.
"Process that fails"
exitCmd := isWindows ifTrue: ['exit 42'] ifFalse: ['exit 42'].
args := Array new: 2. args at: 1 put: shellArg. args at: 2 put: exitCmd.
child := ChildProcess spawn: shell args: args.
exitCode := child exitCode.
'Process with exit 42, got: ' print. exitCode printNl.
'' printNl.
'=== All parallel process tests complete! ===' printNl.
16_tableprinter.st
"
TablePrinter Example - East Asian Width Support
Demonstrates TablePrinter with Japanese text.
Full-width characters (Japanese) are properly aligned.
"
'=== TablePrinter Example ===' printNl.
'' printNl.
"Import the Text module"
Module import: 'Text'.
"--- Example 1: Basic displayWidth test ---"
'Example 1: displayWidth test' printNl.
(' ''hello'' displayWidth = ', 'hello' displayWidth asString) printNl.
(' ''world'' displayWidth = ', 'world' displayWidth asString) printNl.
(' ''Running'' displayWidth = ', 'Running' displayWidth asString) printNl.
'' printNl.
"--- Example 2: Server status table (English only) ---"
'Example 2: English table' printNl.
| table |
table := TablePrinter new.
table headers: #('ID' 'Server Name' 'Status').
table addRow: #(1 'web-01' 'Running').
table addRow: #(2 'db-primary' 'Maintenance').
table addRow: #(105 'api-gateway' 'Error').
table printTable.
'' printNl.
"--- Example 3: Mixed table with Japanese ---"
'Example 3: Japanese table' printNl.
| table2 |
table2 := TablePrinter new.
table2 headers: #('ID' 'Server Name' 'Status' 'Memo').
table2 addRow: #(1 'web-01' 'Running' 'OK').
table2 addRow: #(2 'db-primary' 'Maintenance' 'Backup').
table2 addRow: #(105 'api-gateway' 'Error' 'Check').
table2 printTable.
'' printNl.
"--- Example 4: padRightDisplay test ---"
'Example 4: padRightDisplay test' printNl.
| s1 s2 s3 |
s1 := 'ABC'.
s2 := 'XYZ'.
s3 := 'Hello'.
('[', (s1 padRightDisplay: 10), ']') printNl.
('[', (s2 padRightDisplay: 10), ']') printNl.
('[', (s3 padRightDisplay: 10), ']') printNl.
'' printNl.
'=== Done ===' printNl.
16_mysql.st
"=== Lambda Smalltalk: MySQL Plugin Example ==="
"Demonstrates MySQL database connection and queries"
"NOTE: This example requires a running MySQL server."
"Adjust the connection string as needed."
"=== Load the MySQL plugin ==="
'Loading MySQL plugin...' printNl.
| pluginName |
pluginName := Plugin load: 'examples/plugins/mysql_plugin/target/release/mysql_plugin.dll'.
'Loaded: ' print. pluginName printNl.
'Available functions: ' print. (Plugin functions: 'mysql') printNl.
"=== Connect to database ==="
"Connection string format: mysql://user:password@host:port/database"
| db |
db := Plugin call: 'mysql' function: 'connect' args: #('mysql://root:password@localhost:3306/testdb').
db ifNil: [
'Failed to connect to MySQL. Make sure the server is running.' printNl.
] ifNotNil: [
'Connected! Handle: ' print. db printNl.
"=== Create a test table ==="
| result |
result := Plugin call: 'mysql' function: 'execute' args: { db.
'CREATE TABLE IF NOT EXISTS users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
age INT,
email VARCHAR(100)
)' }.
'Create table: ' print. result printNl.
"=== Insert data with parameters ==="
result := Plugin call: 'mysql' function: 'execute_params'
args: { db. 'INSERT INTO users (name, age, email) VALUES (?, ?, ?)'. #('Alice' 30 'alice@example.com') }.
'Insert Alice: ' print. result printNl.
result := Plugin call: 'mysql' function: 'execute_params'
args: { db. 'INSERT INTO users (name, age, email) VALUES (?, ?, ?)'. #('Bob' 25 'bob@example.com') }.
'Insert Bob: ' print. result printNl.
result := Plugin call: 'mysql' function: 'execute_params'
args: { db. 'INSERT INTO users (name, age, email) VALUES (?, ?, ?)'. #('Charlie' 35 'charlie@example.com') }.
'Insert Charlie: ' print. result printNl.
"=== Query all users ==="
'All users:' printNl.
| rows |
rows := Plugin call: 'mysql' function: 'query' args: { db. 'SELECT * FROM users' }.
rows do: [:row |
' ' print. row printNl.
].
"=== Query with parameters ==="
'Users older than 28:' printNl.
rows := Plugin call: 'mysql' function: 'query_params'
args: { db. 'SELECT name, age FROM users WHERE age > ?'. #(28) }.
rows do: [:row |
' ' print. (row at: 'name') print. ' is ' print. (row at: 'age') print. ' years old' printNl.
].
"=== Update data ==="
result := Plugin call: 'mysql' function: 'execute_params'
args: { db. 'UPDATE users SET age = ? WHERE name = ?'. #(31 'Alice') }.
'Update Alice age: ' print. result printNl.
"=== Delete data ==="
result := Plugin call: 'mysql' function: 'execute_params'
args: { db. 'DELETE FROM users WHERE name = ?'. #('Charlie') }.
'Delete Charlie: ' print. result printNl.
"=== Final state ==="
'Final users:' printNl.
rows := Plugin call: 'mysql' function: 'query' args: { db. 'SELECT * FROM users' }.
rows do: [:row |
' ' print. row printNl.
].
"=== Cleanup ==="
result := Plugin call: 'mysql' function: 'execute' args: { db. 'DROP TABLE users' }.
'Drop table: ' print. result printNl.
"=== Close connection ==="
result := Plugin call: 'mysql' function: 'close' args: { db }.
'Connection closed: ' print. result printNl.
].
'=== Done! ===' printNl.
16_tcp.st
"
Lambda Smalltalk - TCP Networking Example
Demonstrates TCP client and server operations.
"
'=== TCP Client Example ===' printNl.
"Note: This example requires an actual server to connect to.
For testing, you can use: nc -l 12345 (netcat) or similar.
Basic usage:
sock := Tcp connect: 'localhost' port: 12345.
sock send: 'Hello, server!'.
response := sock recvLine.
response printNl.
sock close.
"
'--- TCP API Overview ---' printNl.
' Tcp connect: host port: port - Connect to server' printNl.
' Tcp connect: host port: port timeout: ms - Connect with timeout' printNl.
' stream send: data - Send string or ByteArray' printNl.
' stream recv: maxBytes - Receive up to maxBytes' printNl.
' stream recv - Receive with default buffer' printNl.
' stream recvLine - Receive a line (up to \n)' printNl.
' stream close - Close the connection' printNl.
'' printNl.
' TcpListener listen: port - Start listening on port' printNl.
' listener accept - Accept incoming connection' printNl.
' listener close - Stop listening' printNl.
'' printNl.
"
=== Simple HTTP Client Example ===
This demonstrates making a raw HTTP request over TCP.
"
'--- Minimal HTTP Client ---' printNl.
"
sock := Tcp connect: 'httpbin.org' port: 80.
sock ifNotNil: [
sock send: 'GET /get HTTP/1.1\r\nHost: httpbin.org\r\nConnection: close\r\n\r\n'.
response := sock recv: 4096.
response ifNotNil: [
(response asString) printNl.
].
sock close.
'HTTP request complete.' printNl.
] ifNil: [
'Connection failed.' printNl.
].
"
'--- TCP Server Example (pseudocode) ---' printNl.
"
server := TcpListener listen: 8080.
server ifNotNil: [
'Listening on port 8080...' printNl.
client := server accept.
client ifNotNil: [
request := client recvLine.
'Received: ' print. request printNl.
client send: 'Hello from Lambda Smalltalk!'.
client close.
].
server close.
].
"
'=== Redis Client Example (pseudocode) ===' printNl.
"
Redis uses a simple text protocol (RESP).
With TCP support, you can build a Redis client in pure Smalltalk.
"
"
Object subclass: #Redis instanceVariableNames: 'sock'.
Redis class >> connect: host port: port
| r |
r := self new.
r sock: (Tcp connect: host port: port).
^ r
!
Redis >> ping
sock send: '*1\r\n$4\r\nPING\r\n'.
^ sock recvLine ''Should return +PONG''
!
Redis >> set: key value: value
| keyLen valLen |
keyLen := key size.
valLen := value size.
sock send: '*3\r\n$3\r\nSET\r\n$', keyLen asString, '\r\n', key, '\r\n$', valLen asString, '\r\n', value, '\r\n'.
^ sock recvLine
!
Redis >> get: key
| keyLen |
keyLen := key size.
sock send: '*2\r\n$3\r\nGET\r\n$', keyLen asString, '\r\n', key, '\r\n'.
^ sock recvLine
!
''Usage:''
redis := Redis connect: 'localhost' port: 6379.
redis ping printNl. ''-> +PONG''
redis set: 'mykey' value: 'myvalue'.
redis get: 'mykey' printNl. ''-> myvalue''
"
'TCP examples loaded.' printNl.
17_excel.st
"
Lambda Smalltalk - Excel Plugin Example
Demonstrates: Plugin loading, Excel read/write, multi-sheet support
Requires: excel_plugin (built automatically)
"
FileStream fileIn: 'examples/lib/excel.st'.
| excel rows sheets testFile |
testFile := '_test_excel_example.xlsx'.
"Build plugin if needed"
'--- Building Excel Plugin ---' printNl.
(Process run: 'cargo' args: #('build' '--release' '--manifest-path' 'examples/plugins/excel_plugin/Cargo.toml')) = 0
ifFalse: [ self error: 'Build failed' ].
"Create Excel file with multiple sheets"
'--- Creating Excel File ---' printNl.
excel := Excel load.
excel newWorkbook.
"Sheet 1: Report"
excel addWorksheet: 'Report'.
excel writeString: 'Date' row: 0 col: 0 sheet: 'Report'.
excel writeString: 'Value' row: 0 col: 1 sheet: 'Report'.
excel writeString: '2026-01-10' row: 1 col: 0 sheet: 'Report'.
excel writeNumber: 123.45 row: 1 col: 1 sheet: 'Report'.
excel writeString: '2026-01-11' row: 2 col: 0 sheet: 'Report'.
excel writeNumber: 678.90 row: 2 col: 1 sheet: 'Report'.
"Sheet 2: Summary"
excel addWorksheet: 'Summary'.
excel writeString: 'Total' row: 0 col: 0 sheet: 'Summary'.
excel writeNumber: 802.35 row: 0 col: 1 sheet: 'Summary'.
('Saving to ' , testFile , '...') printNl.
excel save: testFile.
"Read back: sheet names"
'--- Reading Sheet Names ---' printNl.
excel := Excel load.
sheets := excel sheetNames: testFile.
'Sheets: ' print. sheets printNl.
"Read back: specific sheet"
'--- Reading Report Sheet ---' printNl.
rows := excel readSheet: 'Report' from: testFile.
rows do: [:row |
row do: [:cell | cell print. ' ' print].
'' printNl.
].
"Read back: using read: (first sheet as dicts)"
'--- Reading as Dicts ---' printNl.
rows := excel read: testFile.
rows do: [:row |
'Date: ' print. (row at: 'Date') print.
', Value: ' print. (row at: 'Value') printNl.
].
"Cleanup"
File delete: testFile.
('Cleaned up: ' , testFile) printNl.
'Done.' printNl.
18_postgres.st
"
Lambda Smalltalk - PostgreSQL Plugin Example
Requires: postgres_plugin.dll and a running PostgreSQL server
NOTE: This example requires a PostgreSQL server.
If you don't have one, install PostgreSQL or skip this example.
Connection string format:
'host=localhost user=postgres password=yourpass dbname=testdb'
"
| db rows |
'--- Building PostgreSQL Plugin ---' printNl.
(Process run: 'cargo' args: #('build' '--release' '--manifest-path' 'examples/plugins/postgres_plugin/Cargo.toml')) = 0
ifFalse: [ 'Build failed' printNl. ^ self ].
'--- Loading PostgreSQL Library ---' printNl.
FileStream fileIn: 'examples/lib/postgres.st'.
'--- Connecting to PostgreSQL ---' printNl.
"Change this connection string to match your PostgreSQL setup"
db := Postgres connect: 'host=localhost user=postgres password=postgres dbname=postgres'.
db = nil ifTrue: [
'ERROR: Could not connect to PostgreSQL' printNl.
'Make sure PostgreSQL is running and connection string is correct' printNl.
^ self
].
'Connected successfully' printNl.
'--- Creating Test Table ---' printNl.
(db execute: 'DROP TABLE IF EXISTS test_users') ifFalse: [
'Failed to drop table' printNl. ^ self
].
(db execute: 'CREATE TABLE test_users (id SERIAL PRIMARY KEY, name VARCHAR(100), age INTEGER)') ifFalse: [
'Failed to create table' printNl. ^ self
].
'Table created' printNl.
'--- Inserting Data ---' printNl.
(db execute: 'INSERT INTO test_users (name, age) VALUES (''Alice'', 30)') ifFalse: [
'Failed to insert Alice' printNl. ^ self
].
(db execute: 'INSERT INTO test_users (name, age) VALUES (''Bob'', 25)') ifFalse: [
'Failed to insert Bob' printNl. ^ self
].
'Data inserted' printNl.
'--- Inserting with Parameters ---' printNl.
(db execute: 'INSERT INTO test_users (name, age) VALUES ($1, $2)' params: #('Charlie' 35)) ifFalse: [
'Failed to insert Charlie' printNl. ^ self
].
'Parameterized insert successful' printNl.
'--- Querying All Rows ---' printNl.
rows := db query: 'SELECT id, name, age FROM test_users ORDER BY id'.
rows = nil ifTrue: [
'Query failed' printNl. ^ self
].
'Query results:' printNl.
rows do: [:row |
"PostgreSQL plugin now returns proper Dicts!"
'ID: ' print. (row at: 'id') print.
', Name: ' print. (row at: 'name') print.
', Age: ' print. (row at: 'age') printNl.
].
'--- Querying with Parameters ---' printNl.
rows := db queryWith: 'SELECT name, age FROM test_users WHERE age > $1' params: #(28).
rows = nil ifTrue: [
'Parameterized query failed' printNl. ^ self
].
'Users older than 28:' printNl.
rows do: [:row |
(row at: 'name') print. ' (age: ' print. (row at: 'age') print. ')' printNl.
].
'--- Cleanup ---' printNl.
(db execute: 'DROP TABLE test_users') ifFalse: [
'Failed to drop table' printNl. ^ self
].
'Table dropped' printNl.
'--- PostgreSQL Plugin Test Complete ---' printNl.
19_template.st
"============================================
19_template.st - Mustache Template Demo
============================================
Demonstrates: Template rendering with data substitution
"
'=== Basic Template ===' printNl.
"Simple variable substitution"
| tmpl data result |
tmpl := 'Hello, {{name}}!'.
data := Dict new.
data at: 'name' put: 'Alice'.
result := Template render: tmpl with: data.
result printNl.
'=== Template with Multiple Variables ===' printNl.
"Multiple variables"
tmpl := 'Name: {{name}}, Age: {{age}}, City: {{city}}'.
data := Dict new.
data at: 'name' put: 'Bob'.
data at: 'age' put: 30.
data at: 'city' put: 'Tokyo'.
result := Template render: tmpl with: data.
result printNl.
'=== Template with Lists ===' printNl.
"Iterate over array items"
tmpl := 'Items:
{{#items}}
- {{name}}: ${{price}}
{{/items}}'.
data := Dict new.
| items |
items := Array new: 3.
| item1 item2 item3 |
item1 := Dict new.
item1 at: 'name' put: 'Apple'.
item1 at: 'price' put: 100.
item2 := Dict new.
item2 at: 'name' put: 'Banana'.
item2 at: 'price' put: 80.
item3 := Dict new.
item3 at: 'name' put: 'Orange'.
item3 at: 'price' put: 120.
items at: 1 put: item1.
items at: 2 put: item2.
items at: 3 put: item3.
data at: 'items' put: items.
result := Template render: tmpl with: data.
result printNl.
'=== Template with Conditionals ===' printNl.
"Show/hide sections based on data"
tmpl := 'Hello{{#premium}}, Premium User{{/premium}}{{^premium}}, Guest{{/premium}}!'.
| data1 data2 |
data1 := Dict new.
data1 at: 'premium' put: true.
('Premium user: ' , (Template render: tmpl with: data1)) printNl.
data2 := Dict new.
data2 at: 'premium' put: false.
('Regular user: ' , (Template render: tmpl with: data2)) printNl.
'=== HTML Template ===' printNl.
"Generate HTML report"
tmpl := '<html>
<head><title>{{title}}</title></head>
<body>
<h1>{{title}}</h1>
<ul>
{{#users}}
<li>{{name}} - {{email}}</li>
{{/users}}
</ul>
</body>
</html>'.
data := Dict new.
data at: 'title' put: 'User List'.
| users |
users := Array new: 2.
| user1 user2 |
user1 := Dict new.
user1 at: 'name' put: 'Alice'.
user1 at: 'email' put: 'alice@example.com'.
user2 := Dict new.
user2 at: 'name' put: 'Bob'.
user2 at: 'email' put: 'bob@example.com'.
users at: 1 put: user1.
users at: 2 put: user2.
data at: 'users' put: users.
result := Template render: tmpl with: data.
result printNl.
'=== Done! ===' printNl.