Home of the ABS programming language: the joy of shell scripting.
A new minor release of ABS: always be shipping! :ship:
Functions can now be "named":
f my_func(x) {
return x**2
}
Earlier, you would have had to assign the function to a variable:
my_func = f(x) {
return x**2
}
while right now function names are first-class citizens. For example, the string representation of a function will actualy include its name (to be included in stacktraces as well):
⧐ f test() {echo(1)}
f test() {echo(1)}
A decorator is a plain-old function that
accepts 1 + N
arguments, where 1
is the
function being wrapped, and returns a new
function that wraps the original one:
f log_if_slow(original_fn, treshold_ms) {
return f() {
start = `date +%s%3N`.int()
res = original_fn(...)
end = `date +%s%3N`.int()
if end - start > treshold_ms {
echo("mmm, we were pretty slow...")
}
return res
}
}
That's as simple as that: a named function
that returns a new function that executes the
decorated one (original_fn
) and returns its
result, while logging if it takes longer than
a few milliseconds.
Now that we've declared our decorator, it's time
to use it, through the @
notation:
@log_if_slow(500)
f return_random_number_after_sleeping(seconds) {
`sleep $seconds`
return rand(1000)
}
and we can test our decorator has takn the stage:
⧐ return_random_number_after_sleeping(0)
493
⧐ return_random_number_after_sleeping(1)
mmm, we were pretty slow...
371
Functions can receive a dynamic number of arguments,
and arguments can be "packed" through the special
...
variable:
f sum_numbers() {
s = 0
for x in ... {
s += x
}
return s
}
sum_numbers(1) # 1
sum_numbers(1, 2, 3) # 6
...
is a special variables that acts
like an array, so you can loop and slice
it however you want:
f first_arg() {
if ....len() > 0 {
return ...[0]
}
return "No first arg"
}
first_arg() # "No first arg"
first_arg(1) # 1
When you pass ...
directly to a function,
it will be unpacked:
f echo_wrapper() {
echo(...)
}
echo_wrapper("hello %s", "root") # "hello root"
and you can add additional arguments as well:
f echo_wrapper() {
echo(..., "root")
}
echo_wrapper("hello %s %s", "sir") # "hello sir root"
call
calls a function "spreading" the array of arguments into the function's arguments:
multiplier = f(x, y) { x * y }
multiplier.call([10, 2]) # 20
This patch release fixes 2 issues with backports from the 1.11.x
development branch.
The issues fixed are:
x.key = val;
(#315)for x in 1..10 { return x }
) (#303)A new minor release of ABS: always be shipping! :ship:
str.reverse()
(#310)[1,2,3].join() # 123
(#310)"a b c".split() # ["a", "b", "c"]
(#310)A big thank you to @mingwho and @sysread for their contributions!
A new minor release of ABS: always be shipping! :ship:
You can now access objects' properties that don't exist safely (#297):
a?.b?.c?.d?.e()
Earlier, you needed to make sure all the properties in the chain existed, and simply using a.b.c.d.e()
could lead to an error.
We've added an optional argument to env()
that allows setting an environment variable (#305):
$ TEST=1 abs
Hello user, welcome to the ABS (1.9.0) programming language!
Type 'quit' when you're done, 'help' if you get lost!
⧐ env("TEST")
1
⧐ env("TEST", "123")
123
⧐ env("TEST")
123
⧐
Thanks @sysread!
-master
suffix anymoreEarlier, modules were saved under /vendor/github.com/$REPO-master
directory.
Now they are saved under /vendor/github.com/$REPO
directory.
Thanks @mingwho!
This release adds a new builtin function: args()
, implemented in #300. It returns a list of arguments the abs script has been called with (eg. ["abs", "script.abs", "--flag", "val"]
).
This release fixes a panic in the arg
function (#299), fixed through #302. If a negative number is passed, now arg(...)
will return an empty string.
# the command we're running is abs index.abs
arg(0) # "abs"
arg(1) # "index.abs"
arg(2) # ""
arg(-1) # ""
This is a bugfix release which fixes #284 through #294.
To call a function "attached" to an hash you can simply:
hash = {"fn": f(){}}
hash.fn()
Earlier you had to "dereference" the function "out" of the hash due to a minor bug in ABS' evaluator:
hash = {"fn": f(){}}
fn = hash.fn
fn()
A new minor release of ABS: always be shipping! :ship:
ABS 1.8.0
brings a bunch of interesting features and bugfixes, spearheaded by the module installer that lets you download ABS modules with a simple abs get github.com/user/repo
!
ABS is now bundled with a very simple module installer (#277). What the installer does is to fetch an archive from Github and place it under a vendor/
directory. You can use it by running abs get $ARCHIVE
, where archive is a github repository URL in the form github.com/user/repo
.
See it in action:
Once a module is installed, it will also be aliased in a file called packages.abs.json
:
{
"abs-sample-module": "./vendor/github.com/abs-lang/abs-sample-module-master"
}
You can then require
the module either through its full path or the alias, both will work. The alias, though, is there to make it easier for you. Please note that when you call require(path)
, a valid ABS file needs to be present at path
, or path
should be a directory containing an index.abs
file. This is very similar to NodeJS' require
mechanism.
Unfortunately, having to bundle the installer means the ABS distribution just got a little heavier, from 2 to around 5 MB. In the world of 5G, though, this shouldn't be a huge problem.
You can now specify negative (#276) indexes to access array elements! Want to grab the last element of an array without having to know its length?
⧐ list = [1,2,3,4]
⧐ list[-1]
4
We've added a very useful functionality to arrays, which is the ability to convert them into TSV/CSV output:
⧐ list = [["name", "age", "sport"], ["LeBron", "34", "basketball"], ["Virat", "30", "cricket"]]
⧐ list.tsv()
name age sport
LeBron 34 basketball
Virat 30 cricket
⧐ list.tsv(",")
name,age,sport
LeBron,34,basketball
Virat,30,cricket
You can specify a separator to be used, so CSV is supported out of the box. We rely on encoding/csv for this feature (#282).
Interpolation in strings now follows the same conventions used in commands (#280), meaning $VAR
is going to be interpolated in strings as well. This avoids context-switch when using both strings ("Hello %s".fmt("world")
) and commands (var = "world"; `hello $var`
). You can now interpolate in strings with a simple var = "world"; "hello $var"
.
⧐ name = "alex"
⧐ "hello $name"
hello alex
ABS is now built using Go 1.13, which was released at the beginning of the month.
A new minor release of ABS: always be shipping! :ship:
ABS 1.7.0
introduces some syntactical sugar as well as improvements to the REPL, so let's check these changes out!
You can now use ctrl+r
to look for previously ran commands in the REPL (#265), have a look at this video:
You can now abbreviate numbers through these letters (#269):
k
(thousand)m
(million)b
(billion)t
(trillion)1m / 2k # 500
The abbreviations are case-insensitive.
You can now output a "goodbye" message when exiting a script (#266):
exit(1, "something nasty happened")
Earlier you had to explicitly echo right before exiting:
echo("something nasty happened")
exit(1)
This message argument to exit(...)
is optional.
We have made a couple of changes to improve the str.replace()
function:
"abcabc".replace("a", "x") # "xbcxbc"
(#268)"121".replace(["1", "2"], "x") # "xxx"
(#267)This is not really specific to this version, but we launched a playground for you to test ABS code directly on the website:
This version fixes a bug introduced in 1.6.0
with index ranges that, under certain conditions, could cause a panic or return the wrong range (#270).