The foundational library: list operations, folds, higher-order helpers, and type conversions.
import core
Most programs start here. core is written in Bern itself, so every function below is an ordinary Bern function you could read in lib/core.brn. Functions that walk a list take the list as their first argument, which makes them a natural fit for the pipe operator )|.
Apply a function to every element, returning a new list of the results.
map([1, 2, 3], \x -> x * 2) -- Output: [2, 4, 6]
Keep only the elements for which the predicate returns true.
filter([1, 2, 3, 4, 5], \x -> x % 2 == 0) -- Output: [2, 4]
Reverse a list or a set; the type is detected automatically.
reverse([1, 2, 3])
-- Output: [3, 2, 1]
reverse({1, 2, 3})
-- Output: {3, 2, 1}
Concatenate tail onto the end of list (the same effect as <>, expressed as a function).
append([1, 2], [3, 4]) -- Output: [1, 2, 3, 4]
Build an inclusive list of integers - a function wrapper around the [start..end] syntax.
range(1, 5) -- Output: [1, 2, 3, 4, 5]
Reduce a list left-to-right. The function receives (accumulator, element).
foldl([1, 2, 3], 0, \acc, x -> acc + x) -- Output: 6
Reduce a list right-to-left. The function receives (element, accumulator), so it is the natural choice when you want to rebuild a list from the right.
foldr([1, 2, 3], [], \x, acc -> [x * 10] <> acc) -- Output: [10, 20, 30]
Add every element together.
sum([1, 2, 3, 4]) -- Output: 10
Multiply every element together.
product([1, 2, 3, 4]) -- Output: 24
The smallest element. Errors on an empty list.
min([4, 1, 7, 3]) -- Output: 1
The largest element. Errors on an empty list.
max([4, 1, 7, 3]) -- Output: 7
The first n elements (or the whole list if it is shorter).
take(2, [10, 20, 30, 40]) -- Output: [10, 20]
Everything except the first n elements.
drop(2, [10, 20, 30, 40]) -- Output: [30, 40]
The first element. Returns an error value for an empty list.
head([10, 20, 30]) -- Output: 10
Everything except the first element.
tail([10, 20, 30]) -- Output: [20, 30]
Whether the list has no elements.
isEmpty([]) -- Output: true isEmpty([1]) -- Output: false
Does at least one element satisfy the predicate?
any([1, 3, 5, 6], \x -> x % 2 == 0) -- Output: true
Do all elements satisfy the predicate?
all([2, 4, 6], \x -> x % 2 == 0) -- Output: true
The first matching element, or false when none match.
find([1, 2, 3, 4], \x -> x > 2) -- Output: 3 find([1, 2], \x -> x > 9) -- Output: false
The index of target in a list or set, or -1 if it is absent.
index_of(['a', 'b', 'c'], 'b') -- Output: 1 index_of([1, 2, 3], 9) -- Output: -1
Pair up elements by position; stops at the shorter list.
zip([1, 2, 3], ['a', 'b', 'c']) -- Output: [[1, 'a'], [2, 'b'], [3, 'c']]
Combine elements by position using a two-argument function.
zipWith([1, 2, 3], [10, 20, 30], \a, b -> a + b) -- Output: [11, 22, 33]
Apply g then f: compose(f, g, x) is f(g(x)).
compose(\x -> x + 1, \x -> x * 2, 5) -- Output: 11 (5 * 2, then + 1)
The identity function - returns its argument unchanged. Handy as a default or placeholder.
id(42) -- Output: 42
Always returns its first argument and ignores the second.
const(7, "ignored") -- Output: 7
Call a two-argument function with its arguments swapped.
flip(\a, b -> a - b, 3, 10) -- Output: 7 (10 - 3)
Parse a string of digits into an integer.
to_int("42")
-- Output: 42
Widen an integer to a double.
int_to_double(5) -- Output: 5.0
Turn a digit character into its numeric value (errors on a non-digit).
char_to_digit('7')
-- Output: 7
The type of a value as a string - a function form of the :: operator.
typeOf([1, 2, 3]) -- Output: "List"
The length of a string, list, or set - a function form of the :> operator.
length("hello")
-- Output: 5
Whether a value is a recoverable error value.
is_error([1, 2, 3][99]) -- Output: true
Explicitly print a value (literals print on their own, but print is useful under the no-eval pragma). Returns the value.
print("hello")
-- Output: "hello"
The functions compose naturally. Here several are chained with the pipe operator to turn a list of prices into the total of the discounted, in-stock ones:
import core
prices = [12, 40, 7, 25, 3, 60]
-- keep the affordable ones, apply a 10% discount, then total them
total = prices
)| filter(\p -> p <= 40)
)| map(\p -> p - (p / 10))
)| sum
total
-- Output: 76 (12+40+7+25 = 84, less 10% per item)
And a classic fold-based summary that reuses zip, foldl, and max together:
import core names = ["Ana", "Bob", "Cia"] scores = [88, 95, 73] pairs = zip(names, scores) -- [["Ana", 88], ["Bob", 95], ["Cia", 73]] best = max(scores) winner = find(pairs, \pair -> pair[1] == best) winner[0] + " won with " + best -- Output: "Bob won with 95"