The Builtin Module

Table of Content: [Hide]


The builtin module contains facilities that are potentially useful to all users. It occupies the builtin: namespace. You rarely have to explicitly specify the namespace though, since it is one of the namespaces consulted when resolving unqualified names.

Usage Notation

The usage of a builtin command is described by giving an example usage, using variables as arguments. For instance, The repeat command takes two arguments and are described as:

repeat $n $v

Optional arguments are represented with a trailing ?, while variadic arguments with a trailing .... For instance, the count command takes an optional list:

count $input-list?

While the put command takes an arbitrary number of arguments:

put $values...

Options are given along with their default values. For instance, the echo command takes an sep option and arbitrary arguments:

echo &sep=' ' $value...

(When you calling functions, options are always optional.)

Supplying Input

Some builtin functions, e.g. count and each, can take their input in one of two ways:

  1. From pipe:

    ~> put lorem ipsum | count # count number of inputs
    ~> put 10 100 | each [x]{ + 1 $x } # apply function to each input
    ▶ 11
    ▶ 101

    Byte pipes are also possible; one line becomes one input:

    ~> echo "a\nb\nc" | count # count number of lines
    ▶ 3
  2. From an argument – an iterable value:

    ~> count [lorem ipsum] # count number of elements in argument
    ~> each [x]{ + 1 $x } [10 100] # apply to each element in argument
    ▶ 11
    ▶ 101

    Strings, and in future, other sequence types are also possible:

    ~> count lorem
    ▶ 5

When documenting such commands, the optional argument is always written as $input-list?. On the other hand, a trailing $input-list? always indicates that a command can take its input in one of two ways above: this fact is not repeated below.

Note: You should prefer the first form, unless using it requires explicit put commands. Avoid count [(some-command)] or each some-func [(some-command)]; they are, most of the time, equivalent to some-command | count or some-command | each some-func.

Rationale: An alternative way to design this is to make (say) count take an arbitrary number of arguments, and count its arguments; when there is 0 argument, count inputs. However, this leads to problems in code like count *; the intention is clearly to count the number of files in the current directory, but when the current directory is empty, count will wait for inputs. Hence it is required to put the input in a list: count [*] unambiguously supplies input in the argument, even if there is no file.

Numerical Commands

Commands that operate on numbers are quite flexible about the format of the numbers. Integers can be specified as decimals (e.g. 233) or hexadecimals (e.g. 0xE9) and floating-point numbers can be specified using the scientific notation (e.g. 2.33e2). These are different strings, but equal when considered as commands.

Elvish has no special syntax or data type for numbers. Instead, they are just strings. For this reason, builtin commands for strings and numbers are completely separate. For instance, the numerical equality command is ==, while the string equality command is ==s. Another example is the + builtin, which only operates on numbers and does not function as a string concatenation commands.


Predicates are functions that write exactly one output that is either $true or $false. They are described like “Determine …” or “Test …”. See is for one example.

Builtin Functions

+ - * /

+ $summand...
- $minuend $subtrahend...
* $factor...
/ $dividend $divisor...

Basic arithmetic operations of adding, substraction, multiplication and division respectively.

All of them can take multiple arguments:

~> + 2 5 7 # 2 + 5 + 7
▶ 14
~> - 2 5 7 # 2 - 5 - 7
▶ -10
~> * 2 5 7 # 2 * 5 * 7
▶ 70
~> / 2 5 7 # 2 / 5 / 7
▶ 0.05714285714285715

When given one element, they all output their sole argument (given that it is a valid number). When given no argument,

  • + outputs 0, and * outputs 1. You can think that they both have a “hidden” argument of 0 or 1, which does not alter their behaviors (in mathematical terms, 0 and 1 are identity elements of addition and multiplication, respectively).

  • - throws an exception.

  • / becomes a synonym for cd /, due to the implicit cd feature. (The implicit cd feature will probably change to avoid this oddity).


% $dividend $divisor

Output the remainder after dividing $dividend by $divisor. Both must be integers. Example:

~> % 23 7
▶ 2


^ $base $exponent

Output the result of raising $base to the power of $exponent. Examples:

~> ^ 2 10
▶ 1024
~> ^ 2 0.5
▶ 1.4142135623730951

< <= == != > >=

<  $number... # less
<= $number... # less or equal
== $number... # equal
!= $number... # not equal
> $number... # greater
>= $number... # greater or equal

Number comparisons. All of them accept an arbitrary number of arguments:

  1. When given fewer than two arguments, all output $true.

  2. When given two arguments, output whether the two arguments satisfy the named relationship.

  3. When given more than two arguments, output whether every adjacent pair of numbers satisfy the named relationship.


~> == 3 3.0
▶ $true
~> < 3 4
▶ $true
~> < 3 4 10
▶ $true
~> < 6 9 1
▶ $false

As a consequence of rule 3, the != command outputs $true as long as any adjacent pair of numbers are not equal, even if some numbers that are not adjacent are equal:

~> != 5 5 4
▶ $false
~> != 5 6 5
▶ $true

<s <=s ==s !=s >s >=s

<s  $string... # less
<=s $string... # less or equal
==s $string... # equal
!=s $string... # not equal
>s $string... # greater
>=s $string... # greater or equal

String comparisons. They behave similarly to their number counterparts when given multiple arguments. Examples:

~> >s lorem ipsum
▶ $true
~> ==s 1 1.0
▶ $false
~> >s 8 12
▶ $true


assoc $container $k $v

Output a slighly modified version of $container, such that its value at $k is $v. Currently only applies to lists, but will apply to maps as well.

When $container is a list, $k may be a negative index. However, slice is not yet supported.

~> assoc [foo bar quux] 0 lorem
▶ [lorem bar quux]
~> assoc [foo bar quux] -1 ipsum
▶ [foo bar ipsum]

Etymology: Clojure.


bool $value

Convert a value to boolean. In Elvish, only $false and errors are booleanly false. Everything else, including 0, empty strings and empty lists, is booleanly true:

~> bool $true
▶ $true
~> bool $false
▶ $false
~> bool $ok
▶ $true
~> bool ?(fail haha)
▶ $false
~> bool ''
▶ $true
~> bool []
▶ $true
~> bool abc
▶ $true

See also not.


cd $dirname

Change directory.

Note that Elvish’s cd does not support cd -.


constantly $value...

Output a function that takes no arguments and outputs $values when called. Examples:

~> f=(constantly lorem ipsum)
~> $f
▶ lorem
▶ ipsum

The above example is actually equivalent to simply f = []{ put lorem ipsum }; it is most useful when the argument is not a literal value, e.g.

~> f = (constantly (uname))
~> $f
▶ Darwin
~> $f
▶ Darwin

The above code only calls uname once, while if you do f = []{ put (uname) }, every time you invoke $f, uname will be called.

Etymology: Clojure.


count $input-list?

Count the number of inputs.


~> count lorem # count bytes in a string
▶ 5
~> count [lorem ipsum]
▶ 2
~> range 100 | count
▶ 100
~> seq 100 | count
▶ 100


each $f $input-list?

Call $f on all inputs. Examples:

~> range 5 8 | each [x]{ ^ $x 2 }
▶ 25
▶ 36
▶ 49
~> each [x]{ put $x[:3] } [lorem ipsum]
▶ lor
▶ ips

See also peach.

Etymology: Various languages, as for each. Happens to have the same name as the iteration construct of Factor.


eawk $f $input-list?

For each input, call $f with the input followed by all its fields.

It should behave the same as the following functions:

fn eawk [f @rest]{
each [line]{
@fields = (re:split '[ \t]+'
(re:replace '^[ \t]+|[ \t]+$' '' $line))
$f $line [email protected]
} [email protected]

This command allows you to write code very similar to awk scripts using anonymous functions. Example:

~> echo ' lorem ipsum
1 2'
| awk '{ print $1 }'
~> echo ' lorem ipsum
1 2'
| eawk [line a b]{ put $a }
▶ lorem
▶ 1


echo &sep=' ' $value...

Print all arguments, joined by the sep option, and followed by a newline.


~> echo Hello   elvish
Hello elvish
~> echo "Hello elvish"
Hello elvish
~> echo &sep=, lorem ipsum

Notes: The echo builtin does not treat -e or -n specially. For instance, echo -n just prints -n. Use double-quoted strings to print special characters, and print to suppress the trailing newline.

See also print.

Etymology: Bourne sh.


eq $values...

Determine whether all $values are structurally equivalent. Writes $true when given no or one argument.

~> eq a a
▶ $true
~> eq [a] [a]
▶ $true
~> eq [&k=v] [&k=v]
▶ $true
~> eq a [b]
▶ $false

See also is.

Etymology: Perl.


exec $command?

Replace the Elvish process with an external $command, defaulting to elvish.


exit $status?

Exit the Elvish process with $status (defaulting to 0).


explode $iterable

Put all elements of $iterable on the structured stdout. Like flatten in functional languages. Equivalent to [li]{ put [email protected] }.


~> explode [a b [x]]
▶ a
▶ b
▶ [x]

Etymology: PHP. PHP’s explode is actually equivalent to Elvish’s splits, but the author liked the name too much to not use it.


fail $message

Throw an exception.

~> fail bad
Exception: bad
[interactive], line 1:
fail bad
~> put ?(fail bad)
▶ ?(fail bad)

Note: Exceptions are now only allowed to carry string messages. You cannot do fail [&cause=xxx] (this will, ironically, throw a different exception complaining that you cannot throw a map). This is subject to change. Builtins will likely also throw structured exceptions in future.



Takes bytes stdin, parses it as JSON and puts the result on structured stdout. The input can contain multiple JSONs, which can, but do not have to, be separated with whitespaces.


~> echo '"a"' | from-json
▶ a
~> echo '["lorem", "ipsum"]' | from-json
▶ [lorem ipsum]
~> echo '{"lorem": "ipsum"}' | from-json
▶ [&lorem=ipsum]
~> # multiple JSONs running together
echo '"a""b"["x"]' | from-json
▶ a
▶ b
▶ [x]
~> # multiple JSONs separated by newlines
echo '"a"
{"k": "v"}'
| from-json
▶ a
▶ [&k=v]

See also to-json.


has-external $command

Test whether $command names a valid external command. Examples (your output might differ):

~> has-external cat
▶ $true
~> has-external lalala
▶ $false

See also search-external.


has-prefix $string $prefix

Determine whether $prefix is a prefix of $string. Examples:

~> has-prefix lorem,ipsum lor
▶ $true
~> has-prefix lorem,ipsum foo
▶ $false


has-suffix $string $suffix

Determine whether $suffix is a suffix of $string. Examples:

~> has-suffix a.html .txt
▶ $false
~> has-suffix a.html .html
▶ $true


is $values...

Determine whether all $values have the same identity. Writes $true when given no or one argument.

The definition of identity is subject to change. Do not rely on its behavior.

~> is a a
▶ $true
~> is a b
▶ $false
~> is [] []
▶ $true
~> is [a] [a]
▶ $false

See also eq.

Etymology: Python.


joins $sep $input-list?

Join inputs with $sep. Examples:

~> put lorem ipsum | joins ,
▶ lorem,ipsum
~> joins , [lorem ipsum]
▶ lorem,ipsum

The suffix “s” means “string” and also serves to avoid colliding with the well-known join utility.

Etymology: Various languages as join, in particular Python.

See also splits.


keys $map

Put all keys of $map on the structured stdout.


~> keys [&a=foo &b=bar &c=baz]
▶ a
▶ c
▶ b

Note that there is no guaranteed order for the keys of a map.


kind-of $value...

Output the kinds of $values. Example:

~> kind-of lorem [] [&]
▶ string
▶ list
▶ map

The terminology and definition of “kind” is subject to change.


nop &any-opt= $value...

Accepts arbitrary arguments and options and does exactly nothing.


~> nop
~> nop a b c
~> nop &k=v

Etymology: Various languages, in particular NOP in assembly languages.


not $value

Boolean negation. Examples:

~> not $true
▶ $false
~> not $false
▶ $true
~> not $ok
▶ $false
~> not ?(fail error)
▶ $true

NOTE: and and or are implemented as special commands.

See also bool.


ord $string

Output value of each codepoint in $string, in hexadecimal. Examples:

~> ord aA
▶ 0x61
▶ 0x41
~> ord 你好
▶ 0x4f60
▶ 0x597d

The output format is subject to change.

Etymology: Python.


path-abs $path
path-base $path
path-clean $path
path-dir $path
path-ext $path

See godoc of path/filepath. Go errors are turned into exceptions.


peach $f $input-list?

Call $f on all inputs, possibly in parallel.

Example (your output will differ):

~> range 1 7 | peach [x]{ + $x 10 }
▶ 12
▶ 11
▶ 13
▶ 16
▶ 15
▶ 14

See also each.


put $value...

Takes arbitrary arguments and write them to the structured stdout.


~> put a
▶ a
~> put lorem ipsum [a b] { ls }
▶ lorem
▶ ipsum
▶ [a b]
▶ <closure 0xc4202607e0>

Etymology: Various languages, in particular C and Ruby as puts.


pprint $value...

Pretty-print representations of Elvish values. Examples:

~> pprint [foo bar]
~> pprint [&k1=v1 &k2=v2]

The output format is subject to change.

See also repr.


print &sep=' ' $value...

Like echo, just without the newline.

See also echo.

Etymology: Various languages, in particular Perl and zsh, whose prints do not print a trailing newline.


range &step=1 $low? $high

Output $low, $low + $step, …, proceeding as long as smaller than $high. If not given, $low defaults to 0.


~> range 4
▶ 0
▶ 1
▶ 2
▶ 3
~> range 1 6 &step=2
▶ 1
▶ 3
▶ 5

Beware floating point oddities:

~> range 0 0.8 &step=.1
▶ 0
▶ 0.1
▶ 0.2
▶ 0.30000000000000004
▶ 0.4
▶ 0.5
▶ 0.6
▶ 0.7
▶ 0.7999999999999999

Etymology: Python.



Output a pseudo-random number in the interval [0, 1). Example:

~> rand
▶ 0.17843564133528436


randint $low $high

Output a pseudo-random integer in the interval [$low, $high). Example:

~> # Emulate dice
randint 1 7
▶ 6


repeat $n $value

Output $value for $n times. Example:

~> repeat 0 lorem
~> repeat 4 NAN

Etymology: Clojure.


replaces &max=-1 $old $repl $source

Replace all occurrences of $old with $repl in $source. If $max is non-negative, it determines the max number of substitutions.

Note: replaces does not support searching by regular expressions, $old is always interpreted as a plain string. Use re:replace if you need to search by regex.


repr $value...

Writes representation of $values, separated by space and followed by a newline. Example:

~> repr [foo 'lorem ipsum'] "aha\n"
[foo 'lorem ipsum'] "aha\n"

See also pprint.

Etymology: Python.


resolve $command

Resolve $command. Command resolution is described in the language reference. (TODO: actually describe it there.)


~> resolve echo
▶ <builtin echo>
~> fn f { }
~> resolve f
▶ <closure 0xc4201c24d0>
~> resolve cat
▶ <external cat>


search-external $command

Output the full path of the external $command. Throws an exception when not found. Example (your output might vary):

~> search-external cat
▶ /bin/cat

See also has-external.



Reads bytes input into a single string, and put this string on structured stdout.


~> echo "a\nb" | slurp
▶ "a\nb\n"

Etymology: Perl, as File::Slurp.


splits $sep $string

Split $string by $sep. If $sep is an empty string, split it into codepoints.

~> splits , lorem,ipsum
▶ lorem
▶ ipsum
~> splits '' 你好
▶ 你
▶ 好

Note: splits does not support splitting by regular expressions, $sep is always interpreted as a plain string. Use re:split if you need to split by regex.

Etymology: Various languages as split, in particular Python.

See also joins.


take $n $input-list?

Return the first $n elements of the inputs. Examples:

~> take 3 [a b c d e]
▶ a
▶ b
▶ c

~> splits ' ' 'how are you?' | take 1
▶ how

If $n is larger than the number of elements in the input, the entire input is returned.



Takes structured stdin, convert it to JSON and puts the result on bytes stdout.

~> put a | to-json
~> put [lorem ipsum] | to-json
~> put [&lorem=ipsum] | to-json

See also from-json.


wcswidth $string

Output the width of $string when displayed on the terminal. Examples:

~> wcswidth a
▶ 1
~> wcswidth lorem
▶ 5
~> wcswidth 你好,世界
▶ 10

Builtin Variables


A blackhole variable. It can only be assigned, and values to assigned to it will be discard. Trying to use its value will cause an exception.


The boolean false value.


The special value used by ?() to signal absence of exceptions.


A list of search paths, kept in sync with $E:PATH. It is easier to use than $E:PATH.


The process ID of the current Elvish process.


The present working directory. Setting this variable has the same effect as cd. This variable is most useful in temporary assignment.


## Updates all git repositories
for x [*/] {
pwd=$x {
if ?(test -d .git) {
git pull

Etymology: the pwd command.


The boolean true value.