Bern Logo

A functionally inspired language focused on expressiveness.

iex (irm https://bern-lang.github.io/Bern/install/install_bern.ps1)

Install with PowerShell using the command above.
Alternatively, install with Bash using curl -fsSL https://bern-lang.github.io/Bern/install/install_bern.sh | bash

🔋

Batteries Included

The standard library offers a rich set of functions for data manipulation, I/O, and more, so you can get started quickly.

1
2
3
4
5
6
7
8
import core
import random
import strings

-- This is actually a 'random' function that wraps a C binding!
text = random_choice(['apple', 'banana', 'cherry'])

map(text, \c -> char_to_upper(c))
🎯

Pattern Matching

Define functions with multiple clauses that match on patterns, making your code clear and maintainable.

1
2
3
4
5
def sign(0) -> "zero"
def sign(n) -> "positive"

def greet("Alice") -> "Hi, Alice!"
def greet(_) -> "Hello, someone else!"
📦

Algebraic Data Types

Create custom types with multiple constructors for type-safe data modeling. ADTs combine naturally with pattern matching.

1
2
3
4
5
6
7
8
9
adt Shape = Circle Double | Rectangle Double Double

def area(Circle(r)) -> 3.14159 * r * r
def area(Rectangle(w, h)) -> w * h

c = Circle(5.0)
r = Rectangle(3.0, 4.0)

area(c)  // Calculates circle area
🔄

Unified Loop Syntax

Use the loop keyword for all loop types, inspired by Odin. Clean syntax for repeating, conditional, and iteration loops. (for still works as an alias.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Repeat loop
loop 3 do
    "Hello!"
end

// Conditional loop
loop counter > 0 do
    counter = counter - 1
end

// Loop-in loop
loop char : "Bern" do
    char
end
λ

First-Class Functions

Functions are values that can be passed around, returned, and composed. Lambda expressions make inline functions natural.

1
2
3
4
5
6
7
8
import core

// Higher-order function usage
map([1, 2, 3, 4, 5], \x -> x * 2)

// Lambda expressions
inc = \x -> x + 1
applyTwice(\n -> n * 2, 5)
➡️

Pipe Operator

The )| operator threads a value into a function as its first argument, so data transformations read left to right.

1
2
3
4
5
import core

// x )| f  is the same as  f(x)
[1, 2, 3, 4] )| filter(\x -> x % 2 == 0) )| map(\x -> x * 10)
// [20, 40]
📝

Readable Word Operators

New to programming? You don't have to memorize cryptic symbols. Every operator has a plain-English name, so you can write what you mean and read your code out loud. Once you're comfortable, the symbols work too, and you can mix and match freely.

1
2
3
4
3 is-greater 2 and 5 is-less-or-equal 5  // true
[1, 2] concat [3, 4]                 // [1, 2, 3, 4]
total be 10 plus 5                      // assignment with words
17 modulo 5                           // 2

🌟 Also Featuring

Examples

A quick taste below. For a guided, thoroughly explained walkthrough of every feature, head to the in-depth Examples page →

Basics

In Bern, literals are interpreted and printed automatically. Variables are defined with simple assignment.

integer = 2 double = 3.14 helloworld = "Hello, World!"

Conditionals

Use if-then-else statements and else-if chains for conditional logic.

age = 18 if age >= 18 then "You are an adult." else "You are a minor." end

Lists

Lists are homogeneous collections with range syntax and various operations.

numbers = [1, 2, 3, 4, 5] range = [5..10] [1, 2] + 2 // Maps: [3, 4] [1, 2] <> [3, 4, 5] // Concatenation [1, 2, 3] <| [3, 4, 5] // Union (no duplicates)

Sets

Sets automatically handle uniqueness and support set theory operations.

{1, 2} + 3 // Add element {1, 2, 3} |> {2, 3, 4} // Intersection {1, 2, 3} {2, 3, 4} // Difference

Objects (Hashmaps)

Objects use #{...}# notation for key-value pairs.

obj = #{ key: "value", hello: "world" }# obj["key"] = "new_value" obj["new_key"] = "added_value"

Functions with Block Bodies

Use do...end blocks with return for more complex functions.

def sumList(xs) do total = 0 loop n : xs do total = total + n end return total end sumList([1, 2, 3, 4]) // Returns 10

Imports

Extend functionality by importing libraries like core.

import core map([1, 2, 3, 4, 5], \x -> x + 2) def isEven(x) -> x % 2 == 0 filter([1, 2, 3, 4, 5, 6], isEven)

Pipe Operator

The )| operator passes a value as the first argument to a function, letting pipelines read left to right.

import core [3, 1, 2] )| reverse // [2, 1, 3] [1, 2, 3, 4] )| filter(\x -> x > 2) // [3, 4]

User Input

Capture user input with the input() function.

name = input("Type your name: ") import core age_text = input("Type your age: ") age = to_int(age_text)