:foo-bar |
"baz" |
The standard library is the set of modules that come with Bass.
The ground module is inherited by all modules. It provides basic language constructs and the standard toolkit for running thunks.
$ |
constructs a thunk with args |
* |
multiplies numbers |
+ |
sums numbers |
- |
subtracts ys from x |
-> |
passes a value through a series of function calls |
< |
returns true if the numbers are in ascending order |
<= |
returns true if the numbers are in ascending or equal order |
= |
returns true if the values are all equal |
> |
returns true if the numbers are in descending order |
>= |
returns true if the numbers are in descending or equal order |
across |
returns a pipe source that yields a list of values across all the given sources |
addr |
returns an address for a port provided by the thunk |
always |
returns a function that returns x for any value |
and |
returns a truthy value if none of the conds return a falsy value |
append |
joins all given lists into one listdeprecated |
applicative? |
returns true if the value is an applicative |
apply |
call an applicative's underlying operative with a list of arguments |
assert |
evaluates the form and raises an error if it's not true |
assoc |
assoc(iate) keys with values in a clone of a scope |
bind |
attempts to bind values in the scope |
binds? |
returns true if the scope has a value bound to the given symbol |
boolean? |
returns true if the value is true or false |
cache-dir |
returns a cache directory corresponding to the string identifier |
case |
evaluates the branch that successfully binds the given value |
cd |
chain a sequence of thunks with a given working directory |
collect |
returns (f value) for every value read from the source |
combiner? |
returns true if the value is a combiner |
concat |
joins all given lists into one list |
cond |
if-then-else, but with many clauses |
conj |
conjoins values onto the end of a list |
cons |
construct a pair from the given values |
current-scope |
returns the scope of the caller |
curryfn |
returns a fn which accepts args one value at a time |
def |
bind symbols to values in the current scope |
defn |
construct a function and bind it to a symbol |
defop |
construct an operative and bind it to a symbol |
do |
evaluate a sequence, returning the last value |
doc |
print docs for symbols |
dump |
encodes a value as JSON to stderr |
each |
calls f for every value read from the source |
emit |
emits a value to a sink |
empty? |
returns true if the value is an empty list, a zero-length string, an empty scope, or null |
error |
errors with the given message |
eval |
evaluate a value in a scope |
filter |
returns only values from xs which satisfy the predicate |
first |
return the first value in a pair |
fn |
construct a function |
foldl |
reduces xs, leftmost values first, with initial value z |
foldr |
reduces xs, rightmost values first, with initial value z |
for |
loops over values from sources |
from |
chain a sequence of thunks starting from an initial image |
id |
identity function; returns its argument |
if |
if then else (branching logic) |
ignore? |
returns true if the value is _ ("ignore") |
import |
binds symbols in the current scope to their values from the source scope |
insecure! |
sets the :insecure field of the thunk to true |
json |
returns a string containing val encoded as JSON |
keys |
collects the bindings from a scope |
last |
returns the last value from the source |
length |
return the length of the given list |
let |
binds values in a child scope |
linux |
a path root for resolving Linux images |
list |
construct a list from a sequence of values |
list* |
prepend a sequence of values to a list given as the final argument |
list->scope |
constructs an object from a list of flat keyword/value pairs |
list->source |
creates a pipe source from a list of values in chronological order |
list? |
returns true if the value is a linked list |
load |
load a thunk as a module |
log |
logs a string message or arbitrary value to stderr |
make-scope |
construct a scope with the given parents |
map |
returns a list containing the result of applying f to each member of xs |
map-pairs |
calls a function with alternating pairs in a flat list (i.e. with pairs ungrouped) |
mask |
shrouds a string in secrecy |
max |
returns the largest number |
memo |
memo(ize)s a function |
merge |
returns a scope containing the union of the given scopes |
meta |
returns the meta attached to the value |
min |
returns the smallest number |
mkfile |
returns an in-memory file with the given content |
mkfs |
returns a dir path backed by an in-memory filesystem |
module |
returns a scope with only the specified bindings from a child scope |
next |
receive the next value from a source |
not |
negates the given bool-ish value |
now |
returns the current UTC time truncated to the given seconds |
null? |
returns true if the value is null |
number? |
returns true if the value is a number |
op |
construct an operative |
operative? |
returns true if the value is an operative |
or |
returns the first truthy value returned by evaluating conds |
pair? |
returns true if the value is a pair |
path-base |
returns the path-name converted into a file path |
path-name |
returns the base name of the path |
path-stem |
returns the base name of the path, without any extension |
path? |
returns true if the value is a path |
provide |
provide bindings to the current scope from a nested scope |
read |
returns a stream producing values read from a thunk's output or a file's content |
recall-memo |
fetches the result of a memoized function call |
reduce-kv |
reduces a scope |
resolve |
resolve an image reference to its most exact form |
rest |
return the second value in a pair, i.e. the rest of a linked list |
run |
runs a thunk |
scope->list |
returns a flat list alternating a scope's keys and values |
scope? |
returns true if the value is a scope |
second |
return the second member of a linked list |
sink? |
returns true if the value is a sink |
source? |
returns true if the value is a source |
start |
starts running a thunk asynchronously |
store-memo |
stores the result of a memoized function call |
str |
returns the concatenation of all given strings or values |
string->cmd-path |
converts a string to a command or file path |
string->dir |
converts a string to a directory path |
string->fs-path |
parses a string value into a file or directory path |
string->symbol |
convert a string to a symbol |
string? |
returns true if the value is a string |
subpath |
extend path with another path |
substring |
returns a portion of a string |
succeeds? |
returns true if the thunk successfully runs (i.e. exit code 0) |
symbol->string |
convert a symbol to a string |
symbol? |
returns true if the value is a symbol |
take |
reads the next n values from the source into a list |
take-all |
reads all values from the source into a list |
third |
return third member of a linked list |
thunk-args |
returns the thunk's args |
thunk-cmd |
returns the thunk's command |
thunk? |
returns true if the value is a valid thunk |
trim |
removes whitespace from both ends of a string |
unwrap |
returns an applicative's underlying combiner |
use |
loads each thunk and binds it as the name from the thunk's command path |
vals |
collects the values from a scope |
wait |
waits for all started thunks to finish |
when |
evaluates the body if test returns true |
with-args |
returns thunk with args set to args |
with-cmd |
returns thunk with cmd set to cmd |
with-dir |
returns thunk with the working directory set to dir |
with-env |
returns thunk with env set to the given env |
with-image |
returns thunk with the base image set to image |
with-insecure |
returns thunk with the insecure flag set to bool |
with-label |
returns thunk with the label set to val |
with-meta |
returns val with the given scope as its metadata |
with-mount |
returns thunk with a mount from source to the target path |
with-port |
returns thunk with a named port appended to its ports |
with-stdin |
returns thunk with stdin set to vals |
with-tls |
returns thunk with paths to a TLS certificate and key to generate |
wrap |
construct an applicative from a combiner (typically an operative) |
wrap-cmd |
prepend a command + args to a thunk's command + args |
(mkfs & file-content-kv)
applicative? combiner?
returns a dir path backed by an in-memory filesystem
Takes alternating file paths and their content, which must be a text string, and returns the root directory of an in-memory filesystem containing the specified files.
All embedded files have 0644 Unix file permissions and a zero (Unix epoch) mtime.
=> docker-image://docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 [0.01s]=> resolve image config for docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 [0.02s]=> mkfile /file CACHED [0.00s]=> cat <fs>/file [0.24s]=> exporting to client directory [0.00s]-> copying files 29B [0.00s]
"hey"
(log val & fields)
applicative? combiner?
(error msg & fields)
applicative? combiner?
errors with the given message
Accepts key-value fields for structured error data.
(error "oh no!")
error! call trace (oldest first):┆ <fs>/literate-4:1:0..1:161 │ (error "oh no!")^^^^^^^^^^^^^^^^oh no!
(error "oh no!" :exit-code 2)
error! call trace (oldest first):┆ <fs>/literate-4:1:0..1:291 │ (error "oh no!" :exit-code 2)^^^^^^^^^^^^^^^^^^^^^^^^^^^^^oh no!:exit-code 2
(wrap comb)
applicative? combiner?
(make-scope & parents)
applicative? combiner?
construct a scope with the given parents
(make-scope {:a 1} {:b 2})
{
{
} |
|||
{
} |
}
(eval [+ :a :b] (make-scope {:a 1} {:b 2}))
3
(bind scope formals val)
applicative? combiner?
attempts to bind values in the scope
Returns true if the binding succeeded, otherwise false.
(if (bind (current-scope) :abc 123) abc :mismatch)
123
(if (bind (current-scope) [] 123) _ :mismatch)
mismatch
(doc & symbols)
operative? combiner?
(applicative? val)
applicative? combiner?
(operative? val)
applicative? combiner?
returns true if the value is an operative
An operative is a combiner that is given the caller's scope.
An operative may decide whether and how to evaluate its arguments. They are typically used to define new syntactic constructs.
false
(operative? op)
true
(list->source list)
applicative? combiner?
creates a pipe source from a list of values in chronological order
(list->source [1 2 3])
<source: 1 2 3>
(across & sources)
applicative? combiner?
returns a pipe source that yields a list of values across all the given sources
Each list has the last value for each source. Values from each source are never skipped, but not every combination will be produced.
(def evens (list->source [0 2 4]))
evens
(def odds (list->source [1 3 5]))
odds
(next src & default)
applicative? combiner?
receive the next value from a source
If the source has ended, no value will be available. A default value may be provided, otherwise an error is raised.
(next (list->source [1]) :eof)
1
(next *stdin* :eof)
eof
(reduce-kv f init kv)
applicative? combiner?
(symbol->string sym)
applicative? combiner?
convert a symbol to a string
(symbol->string :hello!)
"hello!"
(string->symbol str)
applicative? combiner?
convert a string to a symbol
(string->symbol "hello!")
hello!
(scope->list obj)
applicative? combiner?
returns a flat list alternating a scope's keys and values
(scope->list {:a 1 :b 2 :c 3})
(
a
1
b
2
c
3
)
(apply assoc (cons {:d 4} (scope->list {:a 1 :b 2 :c 3})))
{
:d |
4 |
:a |
1 |
:b |
2 |
:c |
3 |
}
(string->fs-path str)
applicative? combiner?
parses a string value into a file or directory path
(string->fs-path "./file")
./file
(string->fs-path "file")
./file
(string->fs-path "dir/")
./dir/
(string->cmd-path str)
applicative? combiner?
converts a string to a command or file path
If the value contains a /, it is converted into a file path.
Otherwise, the given value is converted into a command path.
(string->cmd-path "scripts/foo")
./scripts/foo
(string->cmd-path "bash")
.bash
(string->dir str)
applicative? combiner?
converts a string to a directory path
A trailing slash is not required; the path is always assumed to be a directory.
(string->dir "dir")
./dir/
(string->dir "dir/")
./dir/
(path-name path)
applicative? combiner?
returns the base name of the path
For a command path, this returns the command name.
For a file or dir path, it returns the file or dir name.
For a file path, it returns the file name.
For a thunk, it returns the thunk's hash.
(path-name .bash)
"bash"
(path-name ./some/file)
"file"
(path-name ./some/dir/)
"dir"
(path-name (.tests))
"GQBK30H7BF254"
(with-image thunk image)
applicative? combiner?
returns thunk with the base image set to image
Image is either a thunk? or an image ref.
Recurses when thunk's image is another thunk, setting the deepest ref or unset image.
(with-image ($ go test ./...) (linux/golang))
{
:image |
{
} |
||||||||||
:cmd |
.go |
||||||||||
:args |
(
) |
}
(with-dir thunk dir)
applicative? combiner?
returns thunk with the working directory set to dir
Unlike cd
, the value of with-dir
is resolved at runtime, meaning it can use container-local paths.
If the thunk needs to write to its output directory, the output path passed to the command must be relative to the given dir. Thunk paths and other mounts will always be 1 level deep in the output directory, so use ../ to refer to back to the output directory, repeated for each additional level of depth. If the depth is unknown, you should use cd
instead.
(with-dir (.tests) ./src/)
{
:cmd |
.tests |
:dir |
./src/ |
}
(with-stdin thunk vals)
applicative? combiner?
returns thunk with stdin set to vals
(with-stdin ($ jq ".a") [{:a 1} {:a 2}])
{
:cmd |
.jq |
||||
:args |
(
) |
||||
:stdin |
(
) |
}
(with-insecure thunk bool)
applicative? combiner?
returns thunk with the insecure flag set to bool
The insecure flag determines whether the thunk runs with elevated privileges, and is named to be indicate the reduced security assumptions.
(with-insecure (.boom) true)
{
:insecure |
true |
:cmd |
.boom |
}
(= (.boom) (with-insecure (.boom) false))
true
(with-label thunk name val)
applicative? combiner?
returns thunk with the label set to val
Labels are typically used to control caching. Two thunks that differ only in labels will evaluate separately and produce independent results.
(with-label ($ sleep 10) :at (now 10))
{
:cmd |
.sleep |
||
:args |
(
) |
||
:labels |
{
} |
}
(with-mount thunk source target)
applicative? combiner?
returns thunk with a mount from source to the target path
(with-mount ($ find ./inputs/) *dir*/inputs/ ./inputs/)
{
:cmd |
.find |
||||
:args |
(
) |
||||
:mounts |
(
) |
}
(thunk-args thunk)
applicative? combiner?
returns the thunk's args
(thunk-args ($ foo abc))
(
"abc"
)
(thunk-args ($ foo))
(
)
(resolve platform ref)
applicative? combiner?
resolve an image reference to its most exact form
(resolve {:platform {:os "linux"} :repository "golang" :tag "latest"})
=> resolve image config for docker.io/library/golang:latest [0.16s]
{
:repository |
"golang" |
||
:platform |
{
} |
||
:tag |
"latest" |
||
:digest |
"sha256:dc76ef03e54c34a00dcdca81e55c242d24b34d231637776c4bb5c1a8e8514253" |
}
(start thunk handler)
applicative? combiner?
starts running a thunk asynchronously
If the thunk errors or exits nonzero the handler is called with a combiner that raises the error when called.
If the thunk runs succeeds the handler is called with null.
=> docker-image://docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 [0.01s]=> resolve image config for docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 [0.01s]=> banana ERROR [0.23s]▕ start: exec: "banana": executable file not found in $PATH!!! banana6: [0.17s] start: exec: "banana": executable file not found in $PATH
false
=> docker-image://docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 [0.01s]=> resolve image config for docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 [0.01s]=> echo [0.22s]▕
true
=> docker-image://docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 [0.01s]=> resolve image config for docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 [0.01s]=> banana ERROR [0.21s]▕ start: exec: "banana": executable file not found in $PATH!!! banana6: [0.15s] start: exec: "banana": executable file not found in $PATHerror! call trace (oldest first):┆ <fs>/literate-9:1:0..1:491 │ ((start (from (linux/alpine) ($ banana)) raiser))^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^build failed: exit code: 1run summary:=> docker-image://docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4=> resolve image config for docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 [0.01s]=> banana [0.21s]start: exec: "banana": executable file not found in $PATHERROR: exit code: 1for more information, refer to the full output above
=> docker-image://docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 [0.01s]=> resolve image config for docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 [0.01s]=> echo [0.21s]▕
null
(read thunk-or-file protocol)
applicative? combiner?
returns a stream producing values read from a thunk's output or a file's content
=> docker-image://docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 [0.01s]=> resolve image config for docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 [0.02s]=> echo 42 [0.22s]=> exporting to client directory [0.00s]-> copying files 29B [0.00s]
42
=> docker-image://docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 [0.01s]=> resolve image config for docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 [0.01s]=> sh -c "echo 42 > file" [0.21s]=> exporting to client tarball [0.00s]-> sending tarball [0.00s]
42
(binds? scope sym)
applicative? combiner?
returns true if the scope has a value bound to the given symbol
(binds? {:x 1} :x)
true
(binds? {} :x)
false
(binds? (current-scope) :binds?)
true
(mask secret name)
applicative? combiner?
shrouds a string in secrecy
Prevents the string from being revealed when the value is displayed.
Prevents the string from being revealed in a serialized thunk or thunk path.
Does NOT currently prevent the string's value from being displayed in log output; you still have to be careful there.
(mask "super secret" :github-token)
<secret: github-token (12 bytes)>
(defop name formals eformal & body)
operative? combiner?
(defn name formals & body)
operative? combiner?
construct a function and bind it to a symbol
Returns the bound symbol. Write a comment before or after to provide documentation.
(times-7 6)
42
(doc times-7)
--------------------------------------------------times-7 applicative? combiner?args: [x]multiplies by 7
null
(current-scope)
operative? combiner?
returns the scope of the caller
{
:*memos* |
<host: bass.lock> |
||||||||||||
{
} |
}
(eval [current-scope] {:a 1})
{
:a |
1 |
}
(map-pairs f ps)
applicative? combiner?
(let bindings & body)
operative? combiner?
(list->scope kwargs)
applicative? combiner?
constructs an object from a list of flat keyword/value pairs
(list->scope [:a 1 :b 2 :c 3])
{
:a |
1 |
:b |
2 |
:c |
3 |
}
(cond & clauses)
operative? combiner?
if-then-else, but with many clauses
Takes a flat pair sequence alternating tests to evaluate and an expression to evaluate if the test returns a truthy value.
Returns the result of the evaluated branch, or null if no tests were true.
By convention, :else is used as the final catch-all test, though any truthy value works.
(cond false :a false :b :else :c)
c
(cond true :a false :b :else :c)
a
(apply appv arg & opt)
applicative? combiner?
call an applicative's underlying operative with a list of arguments
A scope may be provided as the third argument. If not specified, the operative will be called in a new empty scope.
Used to call an applicative with pre-evaluated arguments, skipping the normal evaluation the applicative would perform prior to calling the underlying operative.
(-> x f & fs)
operative? combiner?
passes a value through a series of function calls
Given an input value and a series of functions, calls the first function with the input value, passing the output to the second function, and so on, returning the final value. Typically used to flatten a deeply nested function call to make it easier to read.
Functions are either a single form (i.e. a symbol) or a pair. A single form is called with the input value as the only argument. A pair is called with the input value prepended to the rest of the pair, i.e. inserted as the first argument.
(memo memos thunk binding)
applicative? combiner?
memo(ize)s a function
Returns a function equivalent to the binding from the load
ed thunk which caches its results to/from memos, a path to a file on the host (read-write) or from a thunk (read-only).
This is a utility for caching dependency version resolution, such as image tags and git refs. It is technically the only way to perform writes against the host filesystem.
The intended practice is to commit memos into source control to facilitate reproducible builds.
(def memos *dir*/bass.lock)
memos
(upper-cache "hello")
"HELLO"
=> docker-image://docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 [0.01s]=> resolve image config for docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 [0.01s]=> local:///tmp/nix-shell.fUJHAA/bass-scope2951821946 [0.01s]-> transferring /tmp/nix-shell.fUJHAA/bass-scope2951821946: 417B [0.00s]=> copy /bass.lock /bass.lock CACHED [0.00s]=> cat <host: /tmp/nix-shell.fUJHAA/bass-scope2951821946/bass.lock> [0.26s]▕ memos: {▕ module: {▕ cmd: {▕ command: {▕ name: "strings"▕ }▕ }▕ }▕ calls: {▕ binding: "upper-case"▕ results: {▕ input: {▕ array: {▕ values: {▕ string: {▕ value: "hello"▕ }▕ }▕ }▕ }▕ output: {▕ string: {▕ value: "HELLO"▕ }▕ }▕ }▕ }▕ }
null
(succeeds? thunk)
applicative? combiner?
returns true if the thunk successfully runs (i.e. exit code 0)
returns false if it fails (i.e. exit code nonzero)
Used for running a thunk as a conditional instead of erroring when it fails.
=> docker-image://docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 [0.01s]=> resolve image config for docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 [0.01s]=> false ERROR [0.23s]!!! false
false
=> docker-image://docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 [0.01s]=> resolve image config for docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 [0.01s]=> true [0.23s]
true
(run thunk)
applicative? combiner?
runs a thunk
Raises an error if the thunk's command fails (i.e. exit code 0)
Returns null.
=> docker-image://docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 [0.01s]=> resolve image config for docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 [0.02s]=> echo "Hello, world!" [0.25s]▕ Hello, world!
null
(last source & default)
applicative? combiner?
returns the last value from the source
As with next
, a default may be provided to be returned when the source is empty. If not provided, an error will be raised if the source is empty.
(last (list->source [1 2 3]))
3
(each source f)
applicative? combiner?
(for bindings & body)
operative? combiner?
loops over values from sources
Takes a list alternating bindings and their sources, similar to let
. Reads values across all sources and evaluates the body for each set of values as they are read with next
.
Returns null when the source reaches its end.
(def evens (list->source [0 2 4]))
evens
(def odds (list->source [1 3 5]))
odds
(take n source)
applicative? combiner?
reads the next n values from the source into a list
(take 2 (list->source [1 2 3]))
(
1
2
)
(collect f source)
applicative? combiner?
returns (f value) for every value read from the source
(collect (fn [n] (+ n 1)) (list->source [1 2 3]))
(
2
3
4
)
(take-all source)
applicative? combiner?
reads all values from the source into a list
(take-all (list->source [1 2 3]))
(
1
2
3
)
(from image & thunks)
applicative? combiner?
chain a sequence of thunks starting from an initial image
(cd dir thunk & thunks)
applicative? combiner?
chain a sequence of thunks with a given working directory
Shorthand for using with-mount
to mount ./ on the first thunk and chaining the rest using from
. The working directory will propagate between them.
Typically used within an outer from
which sets the first thunk's image in order to join it into the chain.
{
:image |
{
} |
||||||||||
:cmd |
.find |
||||||||||
:args |
(
) |
||||||||||
:mounts |
(
) |
}
(linux & args)
operative? combiner?
a path root for resolving Linux images
Memoizes image resolution into the caller's *memos*, if set.
(linux/ubuntu)
{
:repository |
"ubuntu" |
||
:platform |
{
} |
||
:tag |
"latest" |
||
:digest |
"sha256:4b1d0c4a2d2aaf63b37111f34eb9fa89fa1bf53dd6e4ca954d47caebca4005c2" |
}
(linux/ubuntu :18.04)
=> resolve image config for docker.io/library/ubuntu:18.04 [0.47s]
{
:repository |
"ubuntu" |
||
:platform |
{
} |
||
:tag |
"18.04" |
||
:digest |
"sha256:ca70a834041dd1bf16cc38dfcd24f0888ec4fa431e09f3344f354cf8d1724499" |
}
(linux/docker.io/library/ubuntu :18.04)
=> resolve image config for docker.io/library/ubuntu:18.04 [0.09s]
{
:repository |
"docker.io/library/ubuntu" |
||
:platform |
{
} |
||
:tag |
"18.04" |
||
:digest |
"sha256:ca70a834041dd1bf16cc38dfcd24f0888ec4fa431e09f3344f354cf8d1724499" |
}
Bass modules always run as commands. Either a user runs the script with the bass
command, or another Bass module runs it as a thunk.
When a module is run as a script, the values reflect the system values available to the bass
command, and main
is called with the arguments passed to bass
.
When a module is run as a thunk, the values reflect the values set in the thunk, and main
is called with the thunk's args.
*dir* |
current working directory |
*env* |
environment variables |
*stdin* |
standard input stream |
*stdout* |
standard output sink |
main |
script entrypoint |
*env*
scope?
environment variables
System environment variables are only available to the entrypoint script. To propagate them further they must be explicitly passed to thunks using with-env
.
System environment variables are unset from the physical OS process as part of initialization to ensure they cannot be leaked.
{
:SECRET_TOKEN |
"im a spooky value" |
}
(main)
applicative? combiner?
script entrypoint
The [script:main] function is called with any provided command-line args when running a Bass script.
Scripts should define it to capture system arguments and run the script's desired effects.
Putting effects in [script:main] instead of running them at the toplevel makes the Bass language server happier.
.strings
module
Simple functions for manipulating UTF-8 encoded strings.
(load (.strings))
<scope: <thunk NFRAJLC6LDIDU: (.strings)>>
includes? |
returns true if str includes substr |
join |
joins a list of strings together with delim in between |
length |
returns the string's length |
split |
split a string on a delimiter |
upper-case |
capitalizes all letters in the string |
.git
module
Bare essentials for fetching Git repositories, using the git
CLI from an image passed on stdin
.
This module is limited to functions necessary for fetching other Bass scripts, i.e. bootstrapping.
checkout |
returns the repo checked out to the given ref |
github |
a path root for repos hosted at github.com |
ls-remote |
resolves a ref to a sha at the remote repo |
path |
returns a path root for repos at the given base URL |
(ls-remote repo ref & timestamp)
applicative? combiner?
resolves a ref to a sha at the remote repo
Does not cache. Used to resolve the ref at a point in time.
(git:ls-remote "https://github.com/vito/bass" "main")
=> resolve image config for docker.io/alpine/git@sha256:66b210a97bc07bfd4019826bcd13a488b371a6cbe2630a4b37d23275658bd3f2 [0.02s]=> docker-image://docker.io/alpine/git@sha256:66b210a97bc07bfd4019826bcd13a488b371a6cbe2630a4b37d23275658bd3f2 CACHED [0.00s]-> resolve docker.io/alpine/git@sha256:66b210a97bc07bfd4019826bcd13a488b371a6cbe2630a4b37d23275658bd3f2 [0.00s]=> git ls-remote https://github.com/vito/bass main [0.64s]=> exporting to client directory [0.00s]-> copying files 83B [0.00s]
"836efe1a4b59be0c148ae4cbc25f7eff581d9dde"
(checkout repo ref)
applicative? combiner?
returns the repo checked out to the given ref
The thunk for cloning the repo is labeled with the given ref. If the ref refers to a branch, you may want to resolve it to a sha first with [git:ls-remote] so that it's not cached forever.
Submodules are always initialized.
(git:checkout "https://github.com/vito/bass" "ea8cae6d4c871cb14448d7254843d86dbab8505f")
{
:image |
{
} |
||||||||||||||||||||||||||||
:cmd |
.git |
||||||||||||||||||||||||||||
:args |
(
) |
}
./
(path root memos)
applicative? combiner?
returns a path root for repos at the given base URL
Please omit the trailing slash. (TODO: would be nice to just strip it or somehow make it a non-issue.)
(def gh (git:path "https://github.com" null))
gh
gh/vito/bass/ref/main/
=> resolve image config for docker.io/alpine/git@sha256:66b210a97bc07bfd4019826bcd13a488b371a6cbe2630a4b37d23275658bd3f2 [0.01s]=> docker-image://docker.io/alpine/git@sha256:66b210a97bc07bfd4019826bcd13a488b371a6cbe2630a4b37d23275658bd3f2 CACHED [0.00s]-> resolve docker.io/alpine/git@sha256:66b210a97bc07bfd4019826bcd13a488b371a6cbe2630a4b37d23275658bd3f2 [0.00s]=> git ls-remote https://github.com/vito/bass main [0.52s]=> exporting to client directory [0.00s]-> copying files 83B [0.00s]
{
:image |
{
} |
||||||||||||||||||||||||||||
:cmd |
.git |
||||||||||||||||||||||||||||
:args |
(
) |
}
./
(github & args)
operative? combiner?
a path root for repos hosted at github.com
Memoizes ref resolution into the caller's *memos*, if set.
git:github/vito/bass/sha/ea8cae6d4c871cb14448d7254843d86dbab8505f/
{
:image |
{
} |
||||||||||||||||||||||||||||
:cmd |
.git |
||||||||||||||||||||||||||||
:args |
(
) |
}
./
(git:github/vito/bass/sha/ "ea8cae6d4c871cb14448d7254843d86dbab8505f")
{
:image |
{
} |
||||||||||||||||||||||||||||
:cmd |
.git |
||||||||||||||||||||||||||||
:args |
(
) |
}
./
git:github/vito/bass/ref/main/
=> resolve image config for docker.io/alpine/git@sha256:66b210a97bc07bfd4019826bcd13a488b371a6cbe2630a4b37d23275658bd3f2 [0.02s]=> docker-image://docker.io/alpine/git@sha256:66b210a97bc07bfd4019826bcd13a488b371a6cbe2630a4b37d23275658bd3f2 CACHED [0.00s]-> resolve docker.io/alpine/git@sha256:66b210a97bc07bfd4019826bcd13a488b371a6cbe2630a4b37d23275658bd3f2 [0.01s]=> git ls-remote https://github.com/vito/bass main [0.47s]=> exporting to client directory [0.00s]-> copying files 83B [0.00s]
{
:image |
{
} |
||||||||||||||||||||||||||||
:cmd |
.git |
||||||||||||||||||||||||||||
:args |
(
) |
}
./
.time
module
(load (.time))
<scope: <thunk TOCE8LOG569JE: (.time)>>
every-minute |
returns a timestamp of the current minute |
measure |
evaluates a form and and logs the time it took |
minute |
60 seconds |
monthly |
returns a timestamp of the current month |
yearly |
returns a timestamp of the current year |
(measure form)
operative? combiner?
evaluates a form and and logs the time it took
Returns the value returned by the form.
(use (.time))
(
time
)
(time:measure (sleep 1))
debug (time (sleep 1)) => null took 1.381675131s=> docker-image://docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 CACHED [0.00s]-> resolve docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 [0.01s]=> resolve image config for docker.io/library/alpine@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4 [0.02s]=> sleep 1 [1.24s]
null
.regexp
module
(load (.regexp))
<scope: <thunk 34KM6DJUQ7I80: (.regexp)>>
case |
matches a string against regexp callback pairs |
bind symbols to values in the current scope
Supports destructuring assignment.
abc
(
a
b
c
)
(
"it's easy as"
1
2
3
)