Skip to the content.

About 0.14.0

I’m excited to announce that the 0.14.0 version is out with a lot of interesting new features. And since I didn’t posted a thing about “older” versions since 0.8, I’ll mention some features that shipped with them, too:

Custom types

Custom types are our way of doing what I’ll call “PUOHT” (programming using objects here and there) and now it’s easier to make them behave almost like native objects. The following methods are now available:

This way you have much more freedom to implement your objects without relying on ugly shortcuts like sum $myobject 10 or print [to_string $myobject] or worse.

Scopes and context managers

A feature whose implementation feels very natural after you have custom types is context managers. I drew inspiration from Python and now you can write this kind of thing in Til:


type logger {
    proc init (name) {
        print "logger for `$name` was instantiated."
        return $name
    }
    proc open (name) {
        print "$name: starting..."
    }
    proc close (name) {
        print "$name: closed."
    }
}

scope "test the logger" {
    with l [logger "teste"]
    print "sleeping..."
    sleep 1
}

The result would be:

logger for `teste` was instantiated.
teste: starting...
sleeping...
teste: closed.

The scope command is going to help me implement better test suites (when an assert fails it can also display the scope name, for instance) and work this way:

Now the with command acts almost like set, in the sense that it creates a new variable in the scope, but it also immediately calls the open method, while the close method is called when the scope ends.

This combination of scope and with solves a problem I discussed some months ago with dumblob: nested context managers. In Python they are kind of a pain in the ass, since you easily ends with too much indentation or some horrible giant lines. In Til, the number of managers for a context has “vertical influence” only: it’s not going to act in the horizontal axis of your code – and you can even instantiate them outside of the scope if you feel the need to.

(And all this is going to make my life much easier when I start working with the file system and sockets.)

Strings

Now we have regexes.

Of course, in a very early stage, but at least you don’t have to rely so heavily on exec.

See (and run) examples/regex.til.

Also, one can iterate over each character of a string, now, using the range method, and insert some special characters, like \n or \t.

I still want the code for Til to be very easy to read, so I’m always trying to keep it small. Special characters in strings (and strings in general) have this tendency to need a lot of code, so I’m not planning on expanding too much on this special characters list, but simply allowing the insertion of chars by hexadecimal or “\u” notation.

Environment variables and command line arguments

Your program now has access to $env (containing the process environment variables) and $args (containing the command line arguments).

Skip!

There’s both ExitCode.Skip and the command skip, so that your ranges (or transform) can ask for whoever is consuming it to skip this iteration because there’s nothing really interesting to “yield”.

Ranges

The range method for SimpleLists now has a sibling, range.enumerate, that acts like the enumerate function from Python, returning both the index and the item on each iteration.

There’s also the zip command to “zip” multiple ranges together.

NO MORE AUTOMATIC PRECEDENCE!!!

That was a hard decision to make, but that still makes some sense: math and logic operations don’t apply precedence automatically anymore. I’m well aware of the potential to put off a lot of people, but this has two advantages:

  1. It makes the math code so much easier to understand;
  2. If the user can overwrite operate, maybe the precedence is not aways a good thing.

So, now that you can implement different behaviors for + and * in your custom type, maybe forcing * to happen always before + is not an interesting behavior…

I was thinking about implementing automatic precedence in math, but I believe it would be very confusing to see it working in some places (math calls) and not working in others (if calls, for example).

But, notice, && and || precedence still apply for logic evaluations!

Anyway, precedence is crazy. If you look how we do it in the real world you clearly can see it would never fit a computerized operation much easily, right?