UStackUStack
Franz icon

Franz

Franz is a functional, prototype-oriented language with terse syntax, lexical scoping, and native compilation via LLVM IR for effect control and predictable closures.

Franz

What is Franz?

Franz is a high-level, functional, interpreted, dynamically typed, general-purpose programming language with a terse syntax and a verbose standard library. Its core purpose is to support functional programming patterns while providing tools for managing effects and predictable execution.

The project is presented as a prototype-oriented language with capability-safe effects and deterministic replay, including “strictly no side effects” (with an explicit exception noted for IO). It also includes a path from source to native executables via LLVM IR.

Key Features

  • Functional core with prototype-oriented objects: Uses a small functional foundation plus prototype-oriented objects to model behavior while keeping the language centered on functional constructs.
  • Capability-safe effects with deterministic replay: Designed to help localize and control effects from imported Franz files.
  • Strictly no side effects (with IO table exception): The language model is described as avoiding side effects except for an explicitly mentioned IO mechanism.
  • Native compilation via LLVM IR: Supports direct compilation to native executables using LLVM IR.
  • List literals and LLVM list operations: Includes list literal syntax like [1, "hello", 3.14] and nested lists, plus operations such as head, tail, cons, empty?, length, nth, and is_list.
  • Comparison and math primitives compiled for common types: Provides equality/ordering operators (is, less_than, greater_than) for integers, floats, and strings, plus math functions such as remainder, power, random, floor, ceil, round, abs, min, max, and sqrt.
  • Control flow and pattern-like conditionals: Offers if/when/unless constructs and “cond chains” for pattern-matching-style multi-way branching.
  • Lexical scoping with snapshot-based closures: Implements lexical scoping where closures capture variables from their definition-time environment; supports arbitrary-depth nested closures.
  • Capability-based sandboxing for imported code: Uses sandboxed execution patterns via use_with() and effect localization via use_as() and dot notation (as described in the repository text).

How to Use Franz

  1. Clone or open the Franz repository and inspect the included README.md and example files (for example, examples/mult-table.franz and examples/game-of-life.franz).
  2. Review the standard library modules referenced in the documentation (String, Math, List, Func) to see available built-in functions and list/list-combinator operations.
  3. Follow the lexical scoping and closure patterns shown in the repository text to verify how closures capture variables and how nested closures behave.
  4. Run the repository’s provided scripts to exercise the implementation and smoke tests (the repository mentions bash scripts such as scripts/run-comparison.sh and automated smoke tests).

Use Cases

  • Building data transformation code with functional list processing: Use list literals and list operations (e.g., map-style patterns shown in the repository text, plus head/tail/nth and other list helpers) to manipulate structured data.
  • Implementing multi-branch logic with conditional chains: Use cond chains for pattern-like branching when you need to route logic based on integer/float/string comparisons or guards.
  • Writing higher-order code with closures: Use the “Func module” combinators (such as compose2, apply, and apply_twice) together with snapshot-based closures to build reusable functional components.
  • Demonstrating predictable scoping in small programs: Use lexical scoping and arbitrary-depth nested closures to build programs where captured variables should remain stable across calls.
  • Prototyping language behavior with native compilation: Compile Franz code through the LLVM IR pipeline to produce native executables, including code paths that exercise list operations, math, comparisons, and control flow.

FAQ

  • Is Franz side-effect-free? The repository text says “Strictly no side effects,” with an explicit exception noted for an IO table.

  • Does Franz compile to native executables? Yes. The project description states “Direct compilation to native executables via LLVM IR.”

  • What typing model does Franz use? Franz is described as dynamically typed and garbage collected.

  • How does closure capturing work in Franz? The documentation describes lexical scoping where closures capture variables from their definition-time environment (snapshot-based closures), and it supports arbitrary-depth nested closures.

  • What tooling is included in the repository? The repository includes examples under examples/, tests (including “smoke tests”), and scripts for running comparisons and checks (as referenced in the page content).

Alternatives

  • Functional programming languages with strong type systems (e.g., ML-family languages): If you primarily want a functional syntax with predictable scoping and closures but don’t need LLVM-based native compilation as a stated focus.
  • Prototype-based languages (e.g., JavaScript with functional patterns): Useful when your interest is prototype-oriented object modeling, though the workflow and effect model described for Franz differ.
  • General-purpose compiled languages with functional features (e.g., languages that compile through LLVM): If you want LLVM IR compilation and functional constructs, but you prefer an ecosystem with different syntax and runtime conventions.
  • Scripting languages used for prototyping with sandboxing approaches: If your priority is experimenting quickly with controlled execution (the repository discusses capability-based security patterns), you may choose a different runtime that offers its own sandbox mechanisms.