# Builtin function
There are many builtin functions in ABS.
Take type
, for example:
type(1) # NUMBER
type([]) # ARRAY
We'll reveal to you a secret now: all string, array, number & hash functions are actually "generic", but the syntax you see makes you think those are specific to the string, number, etc object.
The trick is very simple; whenever the ABS' interpreter finds a method call
such as object.func(arg)
it will actually translate it to func(object, arg)
.
Don't believe us? Try with these examples:
map(["1"], int) # [1]
sort([3, 2, 1]) # [1, 2, 3]
len("abc") # 3
At the same time, there are some builtin functions that doesn't really
make sense to call with the method notation, so we've kept them in a
"special" location in the documentation. exit(99)
, for example, exits
the program with the status code 99
, but it would definitely look
strange to see something such as 99.exit()
.
# Generic builtin functions
# arg(n)
Returns the n
th argument to the current script:
arg(0) # /usr/bin/abs
# args()
Returns the list of arguments to the current script (including the current script itself)
$ abs --flag1 --flag2 arg1 arg2
Hello user, welcome to the ABS programming language!
Type 'quit' when you're done, 'help' if you get lost!
⧐ args()
["abs", "--flag1", "--flag2", "arg1", "arg2"]
⧐ args().len()
5
# cd() or cd(path)
Sets the current working directory to homeDir
or the given path
in both Linux and Windows.
Note that the path may have a '~/'
prefix which will be replaced
with 'homeDir/'
. Also, in Windows, any '/'
path separator will be
replaced with '\'
and path names are not case-sensitive.
Returns the '/fully/expanded/path'
to the new current working directory and path.ok
.
If path.ok
is false
, that means there was an error changing directory:
path = cd()
path.ok # true
path # /home/user or C:\Users\user
here = pwd()
path = cd("/path/to/nowhere")
path.ok # false
path # 'chdir /path/to/nowhere: no such file or directory'
here == pwd() # true
cd("~/git/abs") # /home/user/git/abs or C:\Users\user\git\abs
cd("..") # /home/user/git or C:\Users\user\git
cd("/usr/local/bin") # /usr/local/bin
dirs = cd() && `ls /`.lines()
len(dirs) # number of directories in homeDir
# echo(var)
Prints the given variable:
echo("hello world")
You can use use placeholders in your strings:
echo("hello %s", "world")
To know more about how the placeholders work, please have a look at the documentation for string.fmt()
# env(str)
Returns the str
environment variable:
env("PATH") # "/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
# eval(str)
Evaluates the str
as ABS code:
eval("1 + 1") # 2
eval('object = {"x": 10}; object.x') # 10
# exit(code [, message])
Exits the script with status code
:
exit(99)
You can specify a message that's going to be outputted right before exiting:
⧐ exit(99, "Got problems...")
Got problems...
# flag(str)
Returns the value of a command-line flag. Both the --flag
and -flag
form are accepted, and you can specify values with --flag=x
as well as --flag x
:
$ abs --test --test2 2 --test3=3 --test4 -test5
Hello user, welcome to the ABS programming language!
Type 'quit' when you're done, 'help' if you get lost!
⧐ flag("test")
true
⧐ flag("test2")
2
⧐ flag("test3")
3
⧐ flag("test4")
true
⧐ flag("test5")
true
⧐ flag("test6")
⧐
If a flag value is not set, it will default to true
.
The value of a flag that does not exist is NULL
.
In all other cases flag(...)
returns the literal string
value of the flag:
$ abs --number 10
Hello user, welcome to the ABS programming language!
Type 'quit' when you're done, 'help' if you get lost!
⧐ n = flag("number")
⧐ n
10
⧐ type(n)
STRING
# pwd()
Returns the path to the current working directory -- equivalent
to env("PWD")
.
If executed from a script this will initially be the directory containing the script.
To change the working directory, see cd()
.
pwd() # /go/src/github.com/abs-lang/abs
# rand(max)
Returns a random integer number between 0 and max
:
rand(10) # 7
# require(path_to_file.abs)
Evaluates the script at path_to_file.abs
, and makes
its return value available to the caller.
For example, suppose we have a module.abs
file:
adder = f(a, b) { a + b }
multiplier = f(a, b) { a * b }
return {"adder": adder, "multiplier": multiplier}
and a main.abs
such as:
mod = require("module.abs")
echo(mod.adder(1, 2)) # 3
This is mostly useful to create external library functions, like NPM modules or PIP packages, that do not have access to the global environment. Any variable set outside of the module will not be available inside it, and vice-versa. The only variable available to the caller (the script requiring the module) is the module's return value.
Note that require
uses paths that are relative to
the current script. Say that you have 2 files (a.abs
and b.abs
)
in the /tmp
folder, a.abs
can require("./b.abs")
without having to specify the full path (eg. require("/tmp/b.abs")
).
# sleep(ms)
Halts the process for as many ms
you specified:
sleep(1000) # sleeps for 1 second
# source(path_to_file.abs)
Evaluates the script at path_to_file.abs
in the context of the
ABS global environment. The results of any expressions in the file
become available to other commands in the REPL command line or to other
scripts in the current script execution chain.
This is very similar to require
, but allows the module to access
and edit the global environment. Any variable set inside the module
will also be available outside of it.
This is most useful for creating library functions in a startup script,
or variables that can be used by many other scripts. Often these library functions
are loaded via the ABS Init File ~/.absrc
(see ABS Init File).
For example:
$ cat ~/abs/lib/library.abs
# Useful function library ~/abs/lib/library.abs
adder = f(n, i) { n + i }
$ cat ~/.absrc
# ABS init file ~/.absrc
source("~/abs/lib/library.abs")
$ abs
Hello user, welcome to the ABS programming language!
Type 'quit' when you are done, 'help' if you get lost!
⧐ adder(1, 2)
3
⧐
In addition to source file inclusion in scripts, you can also use
source()
in the interactive REPL to load a script being
debugged. When the loaded script completes, the REPL command line
will have access to all variables and functions evaluated in the
script.
For example:
⧐ source("~/git/abs/tests/test-strings.abs")
...
=====================
>>> Testing split and join strings with expanded LFs:
s = split("a\nb\nc", "\n")
echo(s)
[a, b, c]
...
⧐ s
[a, b, c]
⧐
Note well that nested source files must not create a circular
inclusion condition. You can configure the intended source file
inclusion depth using the ABS_SOURCE_DEPTH
OS or ABS environment
variables. The default is ABS_SOURCE_DEPTH=10
. This will prevent
a panic in the ABS interpreter if there is an unintended circular
source inclusion.
For example an ABS Init File may contain:
ABS_SOURCE_DEPTH = 15
source("~/path/to/abs/lib")
This will limit the source inclusion depth to 15 levels for this
source()
statement and will also apply to future source()
statements until changed.
# stdin()
Reads from the stdin
:
echo("What do you like?")
echo("Oh, you like %s!", stdin()) # This line will block until user enters some text
Worth to note that you can read
the stdin
indefinitely with:
# Will read all input to the
# stdin and output it back
for input in stdin {
echo(input)
}
# Or from the REPL:
⧐ for input in stdin { echo((input.int() / 2).str() + "...try again:") }
10
5...try again:
5
2.5...try again:
...
# type(var)
Returns the type if the given variable:
type("") # "STRING"
type({}) # "HASH"
# unix_ms()
Returns the current unix epoch time, in milliseconds:
unix_ms() # 1594049453157