Skip to main content
Version: 0.77.0

Guided Examples

This chapter is example-first: each section includes complete code you can copy into a .fss file and run directly.

Choose an example

Start here when you want to…Example
Read inputs and produce a resultHello with script arguments
Learn branching without ceremonyFizzBuzz with for + match
Transform real dataCollections and pattern matching
Model recursive domain dataRecursive records and traversal
Split a script into modulesImports + exports
Call a script from an applicationAn embedded pricing rule

1) Hello with script arguments

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 -- Ada

API references used here:

2) FizzBuzz with for + match

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}"

3) Collections and pattern matching

This example introduces:

  • List.filter, List.map, List.fold,
  • List.tryHead and 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}"

4) Recursive records and traversal

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 root

5) Imports + exports (multi-file)

This example introduces:

  • import "..." as Alias,
  • top-level [<export>] bindings,
  • using imported record types in exported functions.

File: includes/common.fss

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 ", " items

File: imports-and-exports.fss

import "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}"

main

6) An embedded pricing rule

This 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.

File: pricing.fss

type Customer =
{ Plan: string
Seats: int }

[<export>] let quote (customer: Customer) =
let pricePerSeat =
match customer.Plan with
| "scale" -> 29
| "team" -> 19
| _ -> 9

pricePerSeat * customer.Seats

File: pricing.mjs

import { 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); // 348n

Install the package and run the host:

npm install @magnusopera/fscript
node pricing.mjs

The 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.

Suggested order

  1. Run example 1 and 2 to get comfortable with flow and syntax.
  2. Run example 3 to practice pattern matching on real data.
  3. Run example 4 to practice recursion with typed data.
  4. Run example 5 when you are ready for multi-file scripts and host-facing exports.
  5. Run example 6 when you are ready to cross the script/host boundary.
  6. Run the BASIC sample under samples/basic/ when you want to see FScript host a second language with PRINT, INPUT, jumps, and loops.