I have two questions about Vala’s non-null mode. I’m trying to work with it, but there seem to be some major limitations that make it really hard to work with in realistic code.
As far as I can tell from the Vala tutorial, the only ways to work with nullable values are with the ??
operator and by using the (!)
cast. However, these are quite difficult to use in some cases that I’ll outline.
First, is there a way to safely check for a null value, and return if it’s null? I’m aware of the ??
operator to “unwrap” a value, but sometimes there’s no valid value to assign. Here’s my example, from the elementary Calendar app:
public ECal.Component? copy_ecal_component (ECal.Component? original) {
if (original == null) {
return null;
}
ECal.Component copy = original.clone ();
E.Source source = original.get_data<E.Source> ("source");
copy.set_data<E.Source> ("source", source);
return copy;
}
This of course won’t work in non-null mode, because Vala doesn’t know that original
isn’t null in the code block at the end. In this case, there’s really no way to continue the function if original
is null. My question is: is there a way to unwrap a nullable variable and return if it fails?
In Swift, there’s a built-in way to deal with this case. It has a guard let
operator that assigns a non-nullable variable to a value, and otherwise executes a block if the value would be null (which typically returns). I would look something like:
guard let unwrapped = original else {
return nil
}
// Use unwrapped as a non-nullable variable from now on
As it is, I’m not sure how I could possibly implement something like this in Vala, where I execute a totally different behavior like returning if I encounter a null value.
Second, how do I call a method on a nullable variable? In another case, I have the existing code
private DateTime get_page () {
Settings? state_settings = new GLib.Settings ("io.elementary.calendar.savedstate");
string? month_page = null;
if (state_settings != null) {
month_page = state_settings.get_string ("month-page");
}
}
I need to call a method of state_settings
. However, since it’s nullable, Vala won’t let me, and I can’t figure out how to get a non-nullable version of it to call from. I can’t use the ??
operator, because there’s no reasonable non-null value for state_settings
. I would prefer to avoid the (!)
cast if possible, since it seems to me like dangerous casts shouldn’t be necessary for what I expect is a common occurrence (variables that have no feasible default value). Again, Swift has a way of working with this. It has a if let
statement that only executes its body if a variable binding doesn’t evaluate to null. That’s basically equivalent to the if
block we have in the current code, but I don’t know how to do that safely in non-null Vala.
Is there a way to implement either of these behaviors in Vala? We have existing ways that are completely safe, but I’m not sure how to convince the compiler that they are.