The Starlark Programming Language

Hermetic by design and syntactically close to Python, the Starlark language is being evaluated as a safe, deterministic scripting layer for build systems and embedded tools. Contributors highlight its strengths in reproducible builds, sandboxing, and ease of embedding (with Go, Java, and Rust implementations), while also noting drawbacks such as the lack of mature static typing, limited error-handling, and the tendency of large Starlark codebases to become complex and hard to navigate. Comparisons with alternatives like Lua, CUE, Dhall, and full-fledged languages (Python, Kotlin) center on trade-offs between expressiveness, Turing-completeness, performance, and long-term maintainability of build and configuration logic.

What Starlark Is and Where It’s Used

  • Python-like, intentionally restricted language originally for Bazel/Blaze build rules.
  • Now framed as a general-purpose embeddable language, with implementations in Java (original/Bazel-tied), Go (generic embedding), and Rust (used in Buck2, with extra features).
  • Also used in tools like Buck2, Tilt, internal Go-based tools, a smart display platform (Tidbyt), a Go-based internal tools platform, and GitHub automation.

Design Goals: Hermetic, Deterministic, Turing-Incomplete

  • No access to time, randomness, filesystem, network, or environment by default; host controls all side-effecting APIs.
  • Deterministic evaluation: same inputs → identical outputs; avoids nondeterminism from random seeds, hash ordering, system APIs.
  • Turing-incomplete (e.g., no recursion), which some see as a feature for config/build languages and a draw versus typical embeddable languages.

Strengths Reported

  • Familiar Python-like syntax lowers onboarding cost versus Lua/Lisp-like options.
  • Hermeticity and determinism aid reproducible, cacheable, parallel builds in very large monorepos.
  • Simpler, smaller “safe” runtime than embedding full Python or JS/WASM and trying to sandbox them.
  • Go implementation is easy to embed; performance and concurrency reported as good.
  • Works well as a controlled scripting layer or “contract/config language” for apps and infrastructure.

Pain Points and Critiques

  • Large Starlark codebases resemble messy large Python codebases: imperative, highly indirect, and hard to reason about.
  • Language minimalism: no standard exceptions, no multi-value returns for errors, limited data structures; error handling requires patterns like Result wrappers or custom host mechanisms.
  • Inconsistent behavior between implementations (Bazel vs Go vs Rust) noted.
  • Some find it one of the most complicated languages to read in practice given abstraction layers in real build rules.
  • Close resemblance to Python can mislead users expecting modern Python features (pattern matching, walrus operator, full stdlib).
  • Skepticism about maintaining yet another DSL vs using established languages (Lua, Python, Kotlin/Gradle) or pure data configs.

Types and Tooling Debate

  • Core Starlark lacks Python-style static typing; this is widely seen as a major weakness for large codebases.
  • Rust implementation for Buck2 adds type annotations and an LSP; Go/Bazel side has some autocomplete via bazel-lsp, but overall tooling is weaker than typed languages.
  • Long subthread debates what “typed/untyped/strong/weak” really mean; consensus in practice is that Starlark behaves like dynamically typed Python without mature static checking.

Alternatives and Broader Reflections

  • Other Turing-incomplete or config-focused options mentioned: CUE and Dhall, with more formal type systems.
  • Some argue build systems should embrace full, strongly typed languages (e.g., Kotlin/Gradle, Scala-based tools) rather than restricted DSLs; others prefer non–Turing-complete, declarative configs to keep builds understandable and safe from overengineering.