Beginner

Hello World in Vale

Your first Vale program - the classic Hello World example with Docker setup

Every programming journey starts with Hello World. Let’s write our first Vale program.

The Code

Create a file named hello.vale:

import stdlib.*;

exported func main() {
  println("Hello, World!");
}

Understanding the Code

  • import stdlib.*; - Imports the Vale standard library, which provides println and other utility functions
  • exported func main() - Declares the program entry point; exported means the function can be called by the operating system or other languages (like C)
  • println("Hello, World!"); - Prints the string followed by a newline to standard output

Running with Docker

Since there is no official Vale Docker image on Docker Hub, we provide a custom image built from the Vale 0.2 release. The image includes the Vale compiler (valec), a JDK (required by the Scala-based frontend), and clang (required for linking the final executable). See our GitHub repository for the Dockerfile:

1
2
# Compile and run the program
docker run --rm -v $(pwd):/app -w /app codearchaeology/vale:0.2 bash -c '/opt/vale/valec build mymod=hello.vale --output_dir build && ./build/main'

Note: The Vale compiler outputs verbose build progress to stdout (showing the frontend, backend, and linker stages). The final line of output will be your program’s result. You may also see compiler warnings from Vale’s built-in C support files — these are harmless.

Running Locally

If you have Vale installed (download from vale.dev/download):

1
2
3
4
5
# Compile and build
valec build mymod=hello.vale --output_dir build

# Run the compiled binary
./build/main

Vale requires a JDK and clang to be installed on your system in addition to the Vale compiler itself.

Expected Output

Hello, World!

Key Concepts

  1. Vale is compiled - Source code (.vale) is compiled through LLVM to native machine code
  2. Single ownership - Each mutable object has exactly one owning reference; when it goes out of scope, the object is destroyed
  3. Generational references - Vale’s novel memory safety mechanism uses runtime generation checks instead of a garbage collector or borrow checker
  4. exported keyword - Required on main so the operating system can call it; also used when exposing functions to C via FFI

The exported Keyword

The exported keyword on main serves a similar purpose to pub in Rust or export in Hare — it makes the function visible outside the current module. For the entry point, this is required so the operating system can invoke it:

import stdlib.*;

// Helper function - not exported, only visible within this module
func greet() {
  println("Hello, World!");
}

// Entry point - must be exported
exported func main() {
  greet();
}

File Extension

Vale source files use the .vale extension. The valec compiler handles parsing (via the Scala frontend), code generation (via the C++/LLVM backend), and linking (via clang) to produce a native binary.

Running Today

All examples can be run using Docker:

docker pull codearchaeology/vale:0.2
Last updated: