Quick Start

This guide walks you through BioLang's core concepts in five minutes. By the end, you will have run your first program, used the pipe operator, and worked with a DNA literal.

Hello, BioLang!

Create a file called hello.bl with the following content:

print("Hello, BioLang!")

Run it from your terminal:

bl run hello.bl
# Hello, BioLang!

The bl run command executes a BioLang source file. You can also pass inline expressions with -e:

bl -e 'print("Hello from the command line!")'

Your First Pipe

The pipe operator |> is BioLang's signature feature. It passes the result of the left-hand expression as the first argument to the right-hand function, enabling clean, readable data transformation chains.

# Transform a list with pipes
[1, 2, 3, 4, 5]
  |> map(|x| x * 2)
  |> filter(|x| x > 4)
  |> print()
# [6, 8, 10]

Without pipes, the equivalent code would nest function calls:

# Same logic without pipes — harder to read
print(filter(map([1, 2, 3, 4, 5], |x| x * 2), |x| x > 4))

Pipes work with any function. The left-hand value becomes the first argument, and any additional arguments follow inside the parentheses:

"hello world"
  |> split(" ")
  |> map(|s| upper(s))
  |> join(", ")
  |> print()
# HELLO, WORLD

DNA Literals

BioLang has first-class support for biological sequences. DNA, RNA, and protein literals are built into the language with the dna"...", rna"...", and aa"..." prefixes.

# Create a DNA sequence
let seq = dna"ATCGATCGATCG"

# GC content is a built-in function
gc_content(seq) |> print()
# 0.5

# Reverse complement
reverse_complement(seq) |> print()
# CGATCGATCGAT

# Sequence length
len(seq) |> print()
# 12

Sequence literals are validated at parse time. Invalid bases produce a compile error, not a runtime crash:

# This is a compile error — 'X' is not a valid DNA base
let bad = dna"ATCXGATCG"
# Error: invalid DNA base 'X' at position 4

Variables and Types

BioLang uses let to declare variables. Variables can be reassigned freely (without let). Types are inferred.

let name = "BioLang"          # String
let version = 0.1              # Float
let bases = ["A", "T", "C", "G"]  # List
let gc = true                  # Bool

# Reassignment
let count = 0
count = count + 1

let threshold = 30.0

Working with Collections

Lists and maps are the primary collection types. Both work seamlessly with pipes.

# Lists
let scores = [38.5, 40.2, 35.1, 42.0, 37.8]
scores
  |> filter(|q| q >= 38.0)
  |> mean()
  |> print()
# 40.233...

# Maps (key-value dictionaries)
let sample = {
  "id": "SAMPLE_001",
  "reads": 1_500_000,
  "organism": "Homo sapiens"
}
print(sample["id"])
# SAMPLE_001

# Map over a list of maps
let samples = [
  { "id": "S1", "reads": 1_000_000 },
  { "id": "S2", "reads": 2_500_000 },
  { "id": "S3", "reads": 800_000 }
]
samples
  |> filter(|s| s["reads"] >= 1_000_000)
  |> map(|s| s["id"])
  |> print()
# ["S1", "S2"]

Running from the REPL

The BioLang REPL is an interactive environment for experimenting. Launch it with:

bl repl

The REPL provides syntax highlighting, tab completion, and multi-line input. Try pasting any of the examples above:

bl> dna"GATTACA" |> reverse_complement()
TGTAATC

bl> [10, 20, 30] |> sum()
60

bl> :type dna"ATCG"
Dna

Type :help to see all available REPL commands, or :quit to exit. See the REPL Tour for a full walkthrough.

Running Scripts

BioLang scripts use the .bl extension. You can run any script with bl run:

# Run a script
bl run analysis.bl

# Run with arguments
bl run analysis.bl -- --input reads.fastq --threshold 30

# Check syntax without running
bl check analysis.bl

# Format a script
bl fmt analysis.bl

Sample Data

BioLang ships with sample data files in examples/sample-data/ so you can run file-based examples immediately. The directory includes FASTA, FASTQ, VCF, BED, GFF, CSV, TSV, and SAM files with realistic bioinformatics content.

# Run the quickstart script that exercises all sample data
bl run examples/quickstart.bl

When documentation examples reference a bare filename like read_fasta("contigs.fa"), substitute the sample data path: read_fasta("examples/sample-data/contigs.fa").

What's Next

You now know the basics: running code, pipes, DNA literals, variables, and collections. Continue to the First Script guide for a full walkthrough of a realistic bioinformatics script.