More about Unions in Vala

In a previous post I speculated about adding tagged unions to Vala. Let’s do that again.

In order to support the C usecase, Vala would need to include 2 types of tagged unions, a legacy one, and an idiomatic one. The legacy should look like the C version of a tagged union:

struct tagged {
    short tag;
    union variants {
        string text;
        int num;
} tagged;

This is needed to bind the C libs out there. The type of the tag should be something that can be easily compared IMO (numeric datatypes, C enums, and string). The binding would then look like this:

[CCode (cname = "tagged", union_tag_field = "tag" union_tag_type = "short" union_field = "variants")]
union Tagged {
    [CCode (cname = "text", union_tag_id = "1")]
    [CCode (cname = "num", union_tag_id = "2")]

The idiomatic ones, however, would actually look like a Rust struct, so if we declare:

public union OrderStatus {
	CANCELLED {string reason, string cancelled_by},
	REJECTED {string reason},
	COMPLETED {DateTime completed_at},
	ON_HOLD {string reason, Datetime until}

We should get:

enum OrderStatusTag {
} OrderStatusTag

union order_status {
    struct accepted {OrderStatusTag tag};
    struct cancelled {OrderStatusTag tag; string reason, string cancelled_by};
    struct rejected {OrderStatusTag tag; string reason};
    struct completed {OrderStatusTag tag; GDateTime completed_at};
    struct on_hold {OrderStatusTag tag; string reason; GDatetime until};
} OrderStatus;

Fun things to support: GVariant variant types (unboxing, serialization, etc.), GValue, JSON representations.


Unions in Vala

I’ve started to use Kotlin professionally, and keeping an eye on Rust. Both offer a lot of niceties that I wish we could adapt for Vala, but there’s one that keeps popping up my mind everytime: pattern matching.

The simplest pattern matching we have is C unions, and a lot of c-libs use them. Unfortunately, the current handling of unions in Vala is a disgrace, and there’s no alternative for it. But I believe we can import some syntax from both Kotlin and Rust. Here is my proposal of how should unions work in Vala:

//Opening a bracket defines an "anonymous struct"
public union OrderStatus {
	CANCELLED {string reason, string cancelled_by},
	REJECTED {string reason},
	COMPLETED {DateTime completed_at}
	ON_HOLD {string reason, Datetime until}

match (order.status) {
	ACCEPTED -> info("Cool!");
	CANCELLED -> debug(@"Not okay, it was cancelled because of $(it.reason) by $(it.cancelled_by)");
	REJECTED as that -> info (@"Rejected: $that.reason");
	default -> error("What is this?? There's no implicit \"it\" here because it's a catch-all!")

public union NestedUnion {
	union COMPLEX {
		HARD{string reason}

//The additional field belongs to the wrapping struct

public union ComplexUnion {
	THIRD {string reason};
	//parent field, children cannot have a field with the same name
	uint32 timestamp;

//Maybe this is not a good idea

public union VeryComplex {
		override void run() {
		override void run() {
		override void run() {
		override void do() {
			debug ("Yay!");
	//They are all required to implement it!
	abstract void run();
	//Optionally overriden
	virtual void do() {
	//Can't touch this
	public void execute() {

//In this case, they reuse existing datatypes

public union ExternalUnion {

public void method () {
	var order = new Order(OrderStatus.ON_HOLD("reason",;
	var other_order = new Order(OrderStatus.CANCELLED(cancelled_by = "desiderantes", reason = "who knows!")); 
	var nested = NestedUnion.COMPLEX.HARD(reason = "no reason at all");
	//'match' can return a value, but all branches should return the same type
	//this 'match' in particular is exhaustive, so no default needed, but if you return a value from 'match', you have to either
	//cover all cases or have a default branch
	NestedUnion another_nested = get_from_network();
	var reason = match (another_nested) {
		SIMPLE -> "Just because";
		COMPLEX -> match (it) {
			SOFT -> "Really easy";
			//if not renamed, then you'll lose access to the it from outer context, as it'll be shadowed
			HARD as that -> that.reason;
	//This errors
	var complex = ComplexUnion(123456789);
	var complex = ComplexUnion();
	var complex = ComplexUnion.FIRST();

	//This should work
	var complex = ComplexUnion.THIRD(123456789, "I can");
	var complex = ComplexUnion.THIRD(reason = "Just because", timestamp = 321654987);
	match (complex) {
		//properties from the parent are only accessible from the parent reference, no implicit parent var
		FIRST -> debug(@"$(complex.timestamp)");
		SECOND -> debug ("Oops");
		THIRD -> debug @("$(complex.timestamp) by $(it.reason)");
	var external = ExternalUnion.STRING("this string is required");

The internal structure (C-wise) of my proposed tagged union is not anything new, it has been done a lot before in C land (here is an explanation from the Rust viewpoint)

Tip: Emitting the notify signal in Vala

I needed a way to emit the notify signal of one of my objects from another place, and Vala didn’t show me a straightforward way to do it. If you need it for some reason, here’s a code snippet showing you how:

using GLib;

public class TestClass : GLib.Object {
	public string test1 {get;set;default = "test1";}
	//Ths one won't emit on assignment
	[CCode (notify = false)]
	public string test2 {get;set;default = "test2";}

	public static void main (string[] args) {
		var test = new TestClass ();
		test.notify["test1"].connect (() => GLib.print ("test1 notification\n"));
		test.notify["test2"].connect (() => GLib.print ("test2 notification\n"));
		test.test1 = "Ahoy";
		test.test2 = "Újale";
		test.test2 = "Ajúa";
		ParamSpec pspec = ((ObjectClass) typeof (TestClass).class_ref ()).find_property ("test2");
		GLib.print ("First try, will not work %s\n",;
		GLib.print ("second one, this is how it works");
		test.notify["test2"] (pspec);

Abandoned Vala Projects

There was a time when Vala was really popular, and a plethora of Vala apps spawned. A lot of them are dead right now, so since i don’t have time to revive any of them, i’ll publish this list of interesting projects in case someone is interested in bringing back one of them:

On Vala and Composite Templates

If you want to use the GTK+ composite templates in Vala, please remember : you have to use a GResource. The syntax is not exactly hard, here’s an example:

<?xml version="1.0" encoding="UTF-8"?>
<gresource prefix="/org/gtk/Example">
<file compressed="true">window.ui</file>

Which is pretty simple. Let’s say you called that file project.gresource.xml, so to include it, you do (at compile time)

valac --target-glib=2.38 --gresources project.gresource.xml --pkg your_package1 --pkg you_package2 ...

Of course, it can’t be that simple, so first you have to _compile_ that xml file (crazy, isn’t it?), doing

glib-compile-resources project.gresource.xml

and then include the generated C file. As this won’t scale, and you probably aren’t compiling that way, the documentation suggest to include a make rule for this. So, our make rule should look like this:

project-gresource.c: project.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --generate-dependencies project.gresource.xml)

and we can include the generated C file in our valac call:

valac --target-glib=2.38 --gresources project.gresource.xml --pkg your_package1 --pkg you_package2 file1.vala file2.vala project-gresource.c ...

Please don’t forget to read the announcement here for more info.