Abs Versions Save

Home of the ABS programming language: the joy of shell scripting.

1.11.0

4 years ago

A new minor release of ABS: always be shipping! :ship:

Named functions

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)}

Decorators

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

Accessing a function's arguments

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 a function with an array of arguments

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

1.10.1

4 years ago

This patch release fixes 2 issues with backports from the 1.11.x development branch.

The issues fixed are:

  • hash property / array index assignment did not support ending with a semicolon, such as x.key = val; (#315)
  • you couldn't return "early" from for / for-in loops (for x in 1..10 { return x }) (#303)

1.10.0

4 years ago

A new minor release of ABS: always be shipping! :ship:

New features

  • you can now reverse strings with str.reverse() (#310)
  • arrays' join method glue argument now defaults to an empty character: [1,2,3].join() # 123 (#310)
  • strings' split method separator argument now defaults to a space: "a b c".split() # ["a", "b", "c"] (#310)

Misc

  • the ABS package installer will now remove archives downloaded from github after extracting them (#292)

Thank yous!

A big thank you to @mingwho and @sysread for their contributions!

1.9.0

4 years ago

A new minor release of ABS: always be shipping! :ship:

Optional chaining

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.

env() improvements

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!

Installed modules don't have the -master suffix anymore

Earlier, modules were saved under /vendor/github.com/$REPO-master directory. Now they are saved under /vendor/github.com/$REPO directory.

Thanks @mingwho!

1.8.3

4 years ago

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"]).

1.8.2

4 years ago

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) # ""

1.8.1

4 years ago

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()

1.8.0

4 years ago

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!

The ABS module installer

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:

asciicast

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.

Negative indexes

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

array.tsv()

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).

Bash-style interpolation in strings

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

Misc

ABS is now built using Go 1.13, which was released at the beginning of the month.

1.7.0

4 years ago

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!

Reverse search in the REPL

You can now use ctrl+r to look for previously ran commands in the REPL (#265), have a look at this video:

asciicast

Number abbreviations

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.

Output an exit message when terminating a script

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.

Improvements to str.replace(...)

We have made a couple of changes to improve the str.replace() function:

  • you do not have to specify the number of replacements anymore, as the default value is "all replacements": "abcabc".replace("a", "x") # "xbcxbc" (#268)
  • you can replace a list of characters now: "121".replace(["1", "2"], "x") # "xxx" (#267)

The ABS playground

This is not really specific to this version, but we launched a playground for you to test ABS code directly on the website:

image

1.6.2

4 years ago

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).