greeting
Strings, pure functions and an effectful entry point.
Read the greeting →Read a little. Try a little.
Start with a complete program and its result. The examples below have been checked against native alpha.13. The bundled examples match your native toolchain.
Strings, pure functions and an effectful entry point.
Read the greeting →Name a domain constraint and let the compiler check its use.
Read the example →Preserve exact values and make representability explicit.
Read the example →Use tagged values and exhaustive matching instead of hidden failure conventions.
Run the example →Work with persistent arrays, maps, sets and byte values.
Run the example →Study memoization, iteration, arithmetic and conditional branches.
Run Fibonacci →Give a task named fields and turn its state into a readable message.
Run the example →Sort names with a pure comparison function, then select a suffix.
Run the example →Create a library and an application in two neighbouring folders.
Build the example →Serve files from any chosen directory with the installed Panackelty HTTP server.
Serve files over HTTP →New in alpha.12
These complete, multi-file programs run from the alpha.13 release tree. Each can be checked and run from source, then compiled and run as saved bytecode.
Compose route, weather and budget modules into one itinerary.
Read the trip planner source →Use two distinct Reading types through explicit module aliases.
Re-export selected declarations through a small public module.
Read the public API source →New in alpha.12
Each condition is checked in order. Only the first matching body runs.
pure classify(value: Nat): Str {
if value == 0 {
"zero"
} else if value == 1 {
"one"
} else if value == 2 {
"two"
} else {
"many"
}
}
main(): Void {
print(classify(0))
print(classify(2))
print(classify(7))
}
Output
zero two many
Positive expresses a constraint on an integer. Code receiving this type can state its expectation directly.
type Positive = Int where value > 0
pure triple(n: Positive): Int {
n * 3
}
main(): Void {
answer: Positive = 14
print(triple(answer))
}
Output
42
main(): Void {
third = 1/3
print((third * 30).nat())
print((1/8).dec())
}
10 0.125
Exact fractions, exact conversions. An unrepresentable exact conversion fails instead of silently rounding.
Build on the basics
A Result carries either a value or an error. Exhaustive matching makes both paths visible.
pure safe_divide(numerator: Nat, denominator: Nat): Result[Nat,Str] {
if denominator == 0 {
Error("division by zero")
} else {
Ok(quotient(numerator, denominator))
}
}
pure describe(result: Result[Nat,Str]): Str {
match result {
Ok(value) => "value ${value}",
Error(message) => message
}
}
main(): Void {
print(describe(safe_divide(84, 2)))
print(describe(safe_divide(1, 0)))
}
Output
value 42 division by zero
Appending returns a new array. Updating a persistent map also returns a new value; assign it when you want to keep the change.
main(): Void {
original: [Nat] = [1, 2]
extended: [Nat] = original.append(3)
print(original)
print(extended)
mut scores: Map[Str,Nat] = map()
scores = scores.put("Ada", 42)
print(scores.get("Ada"))
}
Output
[1, 2] [1, 2, 3] 42
Give related values named fields, then keep presentation in a pure function.
record Task {
title: Str,
done: Bool
}
pure describe_task(task: Task): Str {
title = task.title
if task.done {
"Done: ${title}"
} else {
"To do: ${title}"
}
}
main(): Void {
task = Task("Try Panackelty", false)
print(describe_task(task))
}
Output
To do: Try Panackelty
Pass a named pure comparison function to sort_by, then use a string predicate to select matching names. This processes names; it does not read the filesystem.
import stdlib/prelude
pure name_before(left: Str, right: Str): Bool {
left < right
}
main(): Void {
files = ["z.txt", "b.panack", "a.panack"].sort_by(@name_before)
for file in files {
if file.ends_with(".panack") {
print(file)
}
}
}
Output
a.panack b.panack
Local mutation can be useful inside a pure calculation. Each iteration advances the two values in the sequence.
pure fibonacci(n: Nat): Nat {
mut previous: Nat = 0
mut current: Nat = 1
for ignored in 0..n {
next: Nat = previous + current
previous = current
current = next
}
previous
}
main(): Void {
print(fibonacci(10))
}
Output
55
See why a subtraction is safe or why a pure function cannot print. Explore panack explain →
For larger programs, explore the release-specific example folder, including Project Euler, enums, higher-order functions and native networking.
Native alpha.13 · local packages
Create a small greeting library and an application that uses it. You write four files in two neighbouring folders. After installing native alpha.13, everything in this example is local.
In a terminal, choose a directory for the example and run:
mkdir -p package-demo/greetings/src package-demo/hello/src
cd package-demo
The completed layout will be:
package-demo/
greetings/
panack.json
src/greeting.panack
hello/
panack.json
src/main.panack
Create greetings/src/greeting.panack. This pure function returns a greeting; pub makes it available to callers outside its module.
pub pure hello(name: Str): Str {
"Hello, ${name}!"
}
Create greetings/panack.json to declare the library and its public module:
{
"schema": 1,
"package": "example.greetings",
"version": "0.1.0",
"language": "modules-v1",
"toolchain": "0.1.0-alpha.13",
"source": "src",
"exports": {
"greeting": "greeting.panack"
},
"dependencies": {}
}
source names the source folder. The greeting export exposes src/greeting.panack under that logical module name. A library has no entry point. Both manifests pin alpha.13 because package toolchains must match exactly.
Create hello/panack.json. Its dependency alias greetings points to the library next door:
{
"schema": 1,
"package": "example.hello",
"version": "0.1.0",
"language": "modules-v1",
"toolchain": "0.1.0-alpha.13",
"source": "src",
"entry": "main.panack",
"exports": {},
"dependencies": {
"greetings": {
"path": "../greetings"
}
}
}
../greetings is resolved from the application manifest’s folder, not your terminal’s working directory. The application entry is src/main.panack. Its exports are empty because it does not publish library modules.
Create hello/src/main.panack:
import greetings/greeting as greeting
main(): Void {
print(greeting.hello("Ada"))
}
In greetings/greeting, the first name is the dependency alias and the second is the library’s exported module. as greeting gives that module a short name inside this file. The application calls the library’s pure function and prints its result.
From package-demo, run:
panack check --project hello/panack.json
panack run --project hello/panack.json
The check prints ok. The application prints:
Hello, Ada!
Change "Ada" in the application and run it again. Or change the greeting in the library: the application uses the updated function on its next source run.
You can move the whole package-demo folder and keep using the same commands and relative dependency. Moving just one package would break that relative path. This example needs no registry, package download or Git checkout.
Native alpha.13
The native installation includes panack-http-server, a general-purpose static HTTP server for any chosen directory. It can serve documents, generated reports, website assets and other files. This example uses a small HTML page; no source checkout is needed:
mkdir preview-demo
printf '%s\n' '<h1>Hello from Panackelty</h1>' > preview-demo/index.html
panack-http-server --root ./preview-demo --port 4173 --no-cache --noindex
Wait for Serving http://127.0.0.1:4173/, then open that address in your browser. Edit index.html and refresh to see your change. Press Ctrl-C to stop; active requests have up to one second to drain.
--root chooses the served folder. --no-cache asks the browser not to store responses, and --noindex asks search engines not to index them. The default bind address is loopback, so other devices cannot connect. Use another free port if 4173 is already occupied.
The tool serves existing files and directory indexes with confined reads. It does not list directories, rebuild generated sites, watch files or provide TLS. Complete responses must fit within its 1 MiB limit.
Keep exploring