| id | guided-examples |
|---|---|
| title | Guided Examples |
| slug | /examples/guided-examples |
This chapter is example-first: each section includes complete code you can copy into a .fss file and run directly.
| Start here when you want to… | Example |
|---|---|
| Read inputs and produce a result | Hello with script arguments |
| Learn branching without ceremony | FizzBuzz with for + match |
| Transform real data | Collections and pattern matching |
| Model recursive domain data | Recursive records and traversal |
| Split a script into modules | Imports + exports |
| Call a script from an application | An embedded pricing rule |
| Explore typed FFI with graphics and opaque resources | A rotating teapot |
This first example introduces:
- reading CLI arguments through
Env.Arguments, - pattern matching on lists,
- string interpolation.
let name =
match Env.Arguments with
| head :: _ -> head
| _ -> "Unknown"
Console.writeLine $"Hello {name} !"Run it:
fscript hello.fss -- AdaAPI references used here:
This example introduces:
- helper functions,
- modulo checks,
- tuple matching in
match.
let fizz n = n % 3 = 0
let buzz n = n % 5 = 0
for n in [0..20] do
match (fizz n, buzz n) with
| (true, true) -> Console.writeLine "Fizz Buzz"
| (true, _) -> Console.writeLine "Fizz"
| (_, true) -> Console.writeLine "Buzz"
| _ -> Console.writeLine $"{n}"This example introduces:
List.filter,List.map,List.fold,List.tryHeadand option matching,- head/tail list patterns,
- map-pattern removal with
{ [key] = _; ..rest }.
let values = [1;2;3;4;5;6]
let evens = values |> List.filter (fun n -> n % 2 = 0)
let doubled = evens |> List.map (fun n -> n * 2)
let total = doubled |> List.fold (fun acc -> fun n -> acc + n) 0
Console.writeLine $"evens={evens}"
Console.writeLine $"doubled={doubled}"
Console.writeLine $"total={total}"
let firstEven = evens |> List.tryHead
match firstEven with
| Some x -> Console.writeLine $"first even: {x}"
| None -> Console.writeLine "no even value"
match doubled with
| head :: tail -> Console.writeLine $"head={head} tail={tail}"
| [] -> Console.writeLine "empty"
let scores = { ["a"] = 1; ["b"] = 2 }
let remove k m =
match m with
| { [key] = _; ..rest } when key = k -> rest
| _ -> m
let removedB = remove "b" scores
Console.writeLine $"scores without b = {removedB}"This example introduces:
- recursive record types (
type rec), - optional child nodes,
- recursive tree traversal.
type rec Node =
{ Value: int
Left: Node option
Right: Node option }
let leaf1 = { Value = 4; Left = None; Right = None }
let leaf2 = { Value = 5; Left = None; Right = None }
let leaf3 = { Value = 6; Left = None; Right = None }
let leaf4 = { Value = 7; Left = None; Right = None }
let n2 = { Value = 2; Left = Some leaf1; Right = Some leaf2 }
let n3 = { Value = 3; Left = Some leaf3; Right = Some leaf4 }
let root = { Value = 1; Left = Some n2; Right = Some n3 }
let rec explore visit (node: Node) =
visit node
let exploreChild child =
match child with
| Some n -> explore visit n
| _ -> ()
exploreChild node.Left
exploreChild node.Right
let displayNode (node: Node) =
Console.writeLine $"{node.Value}"
explore displayNode rootThis example introduces:
import "..." as Alias,- top-level
export letbindings, - using imported record types in exported functions.
type ProjectInfo = { Name: string; Language: string }
let describe_project project =
$"{project.Name} ({project.Language})"
let describe_command cmd =
$"step={cmd}"
let join_with_comma items =
String.concat ", " itemsimport "includes/common.fss" as Common
export let extension_name = "demo"
export let summary (project: Common.ProjectInfo) =
let steps = [ "build"; "test"; "publish" ] |> List.map Common.describe_command
$"{Common.describe_project project}: {Common.join_with_comma steps}"
let main =
let project = { Name = "Terrabuild"; Language = "F#" }
Console.writeLine (summary project)
Console.writeLine $"Extension: {extension_name}"
mainThis example shows the full product-facing loop: keep a business rule in FScript, export one intentional entry point, and invoke it from a JavaScript host.
type Customer =
{ Plan: string
Seats: int }
export let quote (customer: Customer) =
let pricePerSeat =
match customer.Plan with
| "scale" -> 29
| "team" -> 19
| _ -> 9
pricePerSeat * customer.Seatsimport { readFile } from "node:fs/promises";
import { load, invoke } from "@magnusopera/fscript";
const source = await readFile(new URL("./pricing.fss", import.meta.url), "utf8");
const script = load(source);
const result = invoke(script, "quote", [{ Plan: "scale", Seats: 12 }]);
console.log(result.value); // 348nInstall the package and run the host:
npm install @magnusopera/fscript
node pricing.mjsThe script owns the changeable rule. The host owns loading, input, output, and every external capability. For typed extern functions and production concerns, continue with the Fable and JavaScript host guide.
- Run example 1 and 2 to get comfortable with flow and syntax.
- Run example 3 to practice pattern matching on real data.
- Run example 4 to practice recursion with typed data.
- Run example 5 when you are ready for multi-file scripts and host-facing exports.
- Run example 6 when you are ready to cross the script/host boundary.
- Run the BASIC sample under
samples/basic/when you want to see FScript host a second language withPRINT,INPUT, jumps, and loops.
Continue with FFI Graphics — A Rotating Teapot to generate a 3D model in FScript and send geometry, camera, and lighting through a typed .NET provider.
The task-sharing analysis samples contrast unsafe shared state, hidden function state, ordered access, and a non-pure but thread-safe counter. They use a small provider with no graphics or native dependencies.