4.10

Vala Language 0.56.x, new LTS Released

Image
July 14, 2022: Vala 0.56.2 released. The first stable release of Vala 0.56 was on March 18, 2022. Vala 0.56.x is the newer (Long-term Support) major release of the Vala Programming Language.

Vala Programming Language 0.56 - a new LTS version

This is the new LTS branch was marked as Stable Long-term Support.


New Vala Language 0.56 LTS replaces the previous LTS 0.48.x

The Vala Development Team announces the next LTS (Long Term Support) version of Vala Programming language as 0.56.x.
This will be the base for the next-generation applications builds with Vala since the previous LTS version as 0.48.x lacks many features introduced gradually in newer Vala versions.

Vala 0.56.x compared with Vala 0.48.x - most notable new features:

  • Use defintions of public header in internal header if available and drop --use-header compiler option and enable it by default (since 0.49)
  • Add support for "with" statement (since 0.49)
  • Support non-virtual signals with default handler (since 0.49)
  • Support explicit nullable var-type declarations (since 0.53)
  • Add support for variadic delegates (since 0.53)
  • Add support for sealed classes (since 0.53)
  • Add support for null-safe access operator (since 0.53)
  • Emit external creation methods in bindings (since 0.53)
  • Introduce VALA_EXPORT for public symbols to improve portability (since 0.53)
  • Add support for partial classes (since 0.55)
  • Add support for nested methods - local functions (since 0.55)
  • Add multi-line support to Vala.Report (since 0.55)
  • Support "emit" for explicit signal emission (since 0.55)
  • Add native support to specify non default length-type for arrays (since 0.55)
  • Add support for async main and yield statements in main block (since 0.55)
  • Add foreach statement support for GLib.Array and GLib.Sequence (since 0.55)
  • Allow usage of dynamic on VarType (since 0.55)
  • Add webkit2gtk-4.1 bindings (since 0.56)
  • Add initial wayland-client binding (since 0.56)

Sample: Partial classes in Vala 0.56
If a class is huge and/or complex, it can be now split up into multiple pieces even into multiple files. All parts of the class only need the partial keyword in front of it.
public partial class Foo : Object {
    public double bar { get; set; }
}

public partial class Foo : Initable {
    public virtual bool init (Cancellable? cancellable = null) {
        stdout.printf ("hello!\n");
        this.bar = 0.56;
        return true;
    }
}

Sample: Length-type for Arrays in Vala 0.56
The length of an array is usually specified by an 32bit integer. But in some cases, especially in bindings to other libaries, sometimes the length of an array is given by a different type of integer. Vala now includes support for this situation:
string[] list = new string[10:uint8];

Sample: Nested functions in Vala 0.56
A simple but useful feature is to be able to nest functions (methods) inside of other functions (methods). These nested methods are then only visible to the code in the function that contains the nested one. But on the other way the code in the nested function (method) has access to variables in the upper method. They are only lambdas assigned to a local variable.
Use cases are to structure very complicated functions into multiple smaller ones, without exposing them publicly. In the following example the same asynchronous callback is used for two invocations, in which you otherwise would use lambdas:
void write_streams (OutputStream stream1, OutputStream stream2, uint8[] data) {
    void nested_function (Object object_source, AsyncResult result) {
        OutputStream stream = object_source as OutputStream;
        try {
            ssize_t size = stream.write_async.finish (result);
            stdout.printf (@"Written $size bytes\n");
        } catch (Error e) {
            stderr.printf ("Error writing to stream: %s", e.message);
        }
    }

    stream1.write_async (data, nested_function);
    stream2.write_async (data, nested_function);
}

Sample: Asynchronous Main Function in Vala 0.56
With the new release the main function can now be defined as async. This has multiple advantages. For example is it now possible to call asynchronous functions with yield:
async int main (string[] args) {
    string dir = args.length == 2 ? args[1] : ".";
    var file = File.new_for_commandline_arg (dir);
    try {
        FileEnumerator enumerator =
            yield file.enumerate_children_async (
                "standard::*,time::*",
                FileQueryInfoFlags.NOFOLLOW_SYMLINKS
            );
        List<FileInfo> children =
            yield enumerator.next_files_async (int.MAX);
        print ("total %lu\n", children.length ());
        foreach (var info in children) {
            // <file-type> <access-date> <size> <name>
            print ("%26s %24s %10"+int64.FORMAT+" B %s\n",
            info.get_content_type (),
            info.get_access_date_time ().to_string (),
            info.get_size (),
            info.get_name ());
        }
    } catch (Error e) {
        printerr ("failed to enumerate files - %s\n", e.message);
        return 1;
    }
    return 0;
}

Sample: Dynamic invocation of Signals in Vala 0.56
Libraries using the GObject type system are providing usually documentation about their API so other languages can use them. However sometimes some parts are missing. With the dynamic keyword an object can be treated as not having all properties or signals specified and they can be accessed dynamically without checking.
signals are now also callable with .emit (). This is necessary to differentiate between a method or a dynamic signal. But this syntax can be also used with non-dynamic variables if wanted.
dynamic Gst.Element appsink = Gst.ElementFactory.make ("appsink", "my_src");
appsink.max_buffers = 0;
appsink.eos.connect (on_eos);
Gst.Sample? res = appsink.pull_sample.emit ();