Chapter 2 of 8

Your first session: install, the REPL, and the types

Amber is one folder. There is no installer, nothing is copied anywhere, and deleting the folder uninstalls it completely.

Getting a prompt

git clone https://github.com/BonucciAndrea/amber
cd amber
./a                    # builds if needed, then drops you at the REPL

./a rebuilds whenever the sources are newer than the binary, so after a git pull the first run is a build. For the fastest build on your own machine:

AMBER_NATIVE=1 ./a     # -march=native
Do not use rlwrap

Line editing is built in: history, Ctrl-A/E, Ctrl-W/U/K, reverse search, multi-line continuation. Wrapping Amber in rlwrap fights the built-in editor and gives you a worse terminal rather than a better one.

The REPL is the documentation

Before anything else, learn these four. They will answer more questions than this website will:

commandwhat it gives you
\the help menu, every topic on one screen
\hthe one-screen cheat-sheet of every verb
\v · \fvariables and functions currently defined
\\exit

Typing \ on its own prints the menu; each topic is one keystroke from there.

Atoms and vectors

An atom is a single value. A vector is many of one type. They are different things, and the type tag tells you which:

@ 1                    / `i   -- integer atom     (lower case = atom)
@ 1 2 3                / `I   -- integer vector   (upper case = vector)
@ 1.5                  / `f   -- float atom
@ 1.5 2.5              / `F   -- float vector
@ "a"                  / `c   -- char atom
@ "abc"                / `C   -- char vector, i.e. a string
@ `sym                 / `s   -- symbol atom (interned, compares by id)
@ `a`b`c               / `S   -- symbol vector
@ (1;`a;"b")           / `A   -- generic list: mixed types
Why symbols exist

A symbol is interned once and afterwards compared as a 4-byte id, never character by character. Every column of instrument names in a tick table should be `S, never `C. This is the difference between a group-by that takes 34 ms and one that takes 587.

Nulls, infinities and the empty vector

0N                     / integer null
0n                     / float null (NaN)
0w  -0w                / positive and negative infinity
^ 1 0N 3               / 0 1 0     -- ^ tests for null
0N ^ 1 0N 3            / 1 0N 3    -- x^y fills nulls in y with x... careful:
0 ^ 1 0N 3             / 1 0 3     -- fill the nulls with 0
!0                     / an empty integer vector
0#`                    / an empty symbol vector -- 0# takes nothing

Float nulls (0n) propagate silently through arithmetic, which is usually what you want in a time series and occasionally a trap. Int nulls stay null too, as q's do (since 2.9.0): 0N+1 is 0N. The q-named sum, avg, min and max skip nulls the way q does, though (since 2.4). ^x is how you check.

Assignment and functions

a: 42                  / local assignment
a:: 42                 / global assignment (from inside a function)
f: {x + y}             / a lambda; x, y, z are the implicit arguments
f[1; 2]                / 3        -- bracket call, semicolon separated
g: {[price;size] price * size}    / or name them explicitly
g[10.5; 100]           / 1050.0
Two-argument functions work infix

As in q, a named function of two arguments can sit between them: sz wavg px is wavg[sz;px], and your own work the same way (g:{[a;b] a*b}; 3 g 4). A lambda written in place doesn't: {x+y}[3;4], not 3 {x+y} 4.