Hi all, so, I’ve been asking variations of this in Vala-specific channels, but I’m also very interested in feedback from people who don’t use Vala for their apps.
If you’re using Vala, what improvements would you like to see? What would make Vala so much better for you?
If you’re not using Vala, presumably you found that a different language suits your use case better. Why is that? How could we improve Vala so it’s also very suitable for your use case? What is Vala missing to be your go-to language, for GNOME app / library development and beyond?
The following are fictional examples of the kind of responses I’m looking for:
“Memory safety is really important to me. If Vala provided some hardening against memory issues, that would make it so much more viable for me.”
“I’d totally use Vala for my GNOME-unrelated project if the POSIX profile was more complete. But as things stand, the mandatory dependency on GLib is not feasible for my project.”
“The type system is not advanced enough. I’m used to higher-kinded zygomorphic proto-meta-paramorphism, and I’m sorely missing it when trying to write Vala.”
“There is not enough documentation, guidance, examples, and tutorials about Vala. It might be good for all I know, but there is no way to learn it.”
“The overall design is good enough, and no big thing is missing. However, various small issues here and there accumulate, and it’s a death by a thousand paper cuts. In particular I’ve hit the following issues, all of which I reported on GitLab: link1, link2, link3, link4.”
“For my project, I have to use the aws-sdk-dynamodb Rust crate, there’s no way around it. If Vala provided some native interop with Rust, being able to transparently call into Rust and back, that would be so great, I’d write my UI in Vala, and my backend in Rust.”
“The tooling around Vala is not good enough. The LSP is hard to set up, and is frequently crashing. The formatter cannot seem to decide how it wants function parameters to be aligned. And expecting us to debug the generated C code with GDB, dude, are you for real?”
“I’m actually using Vala for my app, but missing LINQ from C#. LINQ is such a great invention, why didn’t you copy it into Vala?”
I of course cannot promise that every request would be fulfilled But it would be nice to, at least, understand what you all would actually like to see, and what we should focus on.
I already use Vala, but one friction point that springs to mind is always having to spell out long type specifications in full, e.g.
internal HashTable<string, Value> data
= new HashTable<string, Value>(str_hash, str_equal);
I know there’s a way to create type aliases of sorts through inheritance, but it’s verbose and the docs left me unclear on the details. An equivalent of typedef or using would help a lot.
more frequently up to date bindings for projects like GTK that don’t have vapis upstream, incl. in stable releases. E.g. it took a fairly long time to get GTK 4.22 stuff into GNOME 50 runtime
up-to-date docs on valadoc as well. For example libadwaita is at 1.4, this is a release from 5.5 cycles ago, that had been EOLed a while ago too. And libadwaita is pretty much the best case from vala’s pov too because we ship our own bindings, so the only thing that needs to be maintained is bumping the version on valadoc - so I’d imagine other libraries are even more out of date.
It would be awesome if Vala could output safe Rust code, or modern C++ (like Michael wrote about in a previous thread). To have a more familiar and simpler syntax for Rust, with still first-class support for GLib/GObject.
It would be a long-term project, but there is the possibility to create a variant language (to break backward-compatibility), either with compiler flags, or just giving the new language another name (Vrust?).
Also, what some new library projects do is to write the implementation in Rust, and the API in C/GObject, to benefit from the language bindings. What about writing the API in Vala instead? So, focusing on the API aspect. The “Vrust” could also output C/GObject for the API.
There can also be hybrid approaches for having as a result a C/GObject API. Write the API in Vala, and do the bridge with the implementation with manual work, but less manual work than writing the whole API in C/GObject by hand. Some kind of code generation tool, but provide nice places where to put the additional code.
What advantages would that bring, how would that make Vala better? What do you care, as long as the generated C is just an implementation detail, one of the several internal compiler representations?
Perhaps what you’re after is not what code it generates, but being able to interop with Rust just as easily as Vala today interoperates with C (due to compiling to C)?
If you’re using Vala, what improvements would you like to see? What would make Vala so much better for you?
A small macro language: I’m very fond of Crystal’s and it’d make repetitive code such as this one (actions) more maintainable.
Expand and modernize stdlib, outside of glib. E.g. some stuff from libgee should be built-in. Plus the built-in arrays are very minimal in features.
Expanding on Alice’s valadoc comment, I’d also add, just getting rid of the server and moving to a static platform with client-side searching. There was a period in time when valadoc would go down often and I had a demo prototype of exactly that somewhere. Updating binding docs would be a lot faster.
union types
if strict non-null makes it in, I’d rather it takes a smarter approach than (!). From Crystal again, to avoid telling the compiler that something nullable is explicitly non-null, we do this
if !(not_nullable = nullable).nil?
# `not_nullable` is no longer nullable
end
vs nullable.not_nil! which will raise a runtime exception if it ends up being null
I don’t think GNOME developers are going to care about the POSIX profile, but that’s probably essential for the language to be more broadly successful. Targeting GNOME developers only has drastically limited the size of Vala’s user base and has clearly not been a successful strategy.
It doesn’t have to be perfect, but it should at minimum protect against both out of bounds accesses (probably easy to do) and lifetime issues (probably hard to do). The benefit is elimination or at least drastic reduction of memory safety vulnerabilities.
I’m probably one of few people to have maintained a public C API that’s actually written in Vala (libgnome-games-support). It’s absolutely doable. I don’t recommend it, though. You have to be willing to inspect the generated C header file to look for ABI breakage, because the ABI implications of changes to your Vala source code are sometimes not obvious. A library’s API is the one part that really ought to be done in C. (Of course, implement it using whichever language you prefer.)
Suppose we added “libvalastd”, how would that improve upon the current situation of there being libgee?
On arrays, yes, I agree. It would be great to fix the various issues surrounding them (.move () leaking overwritten items…) and add .pop (), so arrays are usable as stacks. Maybe add a few more things, ones that you would actually do with a plain array in C. Then maybe there’d be less incentive to reach out for Gee.ArrayList — indeed, in plain C you would not use a GeeArrayList, you’d make do with an array.
I’m entirely unfamiliar with valadoc internals, but yeah, if it’s not static, then sounds that making it static would indeed be an improvement.
Care to expand? Tagged unions? Untagged unions like in C? What would they correspond in C, and is there an example API in the platform where they’re used?
Yes, also very much agree here. I’m fond of Kotlin’s smart casts, which are basically the same thing. We should have that in Vala in order to complete the strict non-null mode.
Vala already implements a very limited form of this under the name “type narrowing”. We should build up on that.
Can you provide an example where a C API/ABI change stemming from a Vala change wasn’t obvious to you? What could we improve on the Vala side to make it more obvious?
Perhaps better tooling would help, one that would yell at you if you change your C API?
I’d say introduce similar structures to the native arrays. I’m trying to avoid libgee for new projects, so e.g. hashmaps become Glib.HashTables etc. but maybe there could exist something like the following:
string[string] map = {"language" => "vala", "toolkit" => "gtk"}; // dk what the type would look like
map["language"]; #=> "vala"
map["foo"] = "bar";
// ...
for the most part it is, but the search and tooltips require a server and a mysql instance.
I’d say tagged, but I don’t know what the C output would be or give you an example, but I’d use them in situations such as:
void do_something_with_url (GLib.Uri | string url) {
string final_url = url is typeof(GLib.Uri) ? url.to_string () : url; // type narrowing would be cool here too
// ...
}
though to be honest, I’ve gotten quite used to creating helper functions at this point, e.g.
This is going to be a possibly outdated anecdote about my experience with vala (it’s been 5 or 6 years). Most of my programming experience is with Rust, Ruby, and JavaScript, so Vala and other java-y looking languages are a bit foreign to me, and I can always trust my programs to uphold memory safety. I was working on a GTK configuration UI for a custom stream deck I had built, and I was trying to make use of async code in Vala. Despite not using multithreading (just single-threaded async), I was somehow managing to segfault in the standard library (libgee?) hashmap code. My opinion at the time, and my opinion still now, is that shouldn’t be able to happen. After being unable to figure out that particular problem I switched to writing the configuration UI in Rust where I could trust my async + hashmap code not to segfault.
All this to say: memory safety is very important to me because it means I don’t need to worry about any of the related problems.
tooling mostly, i think. vala compiler errors aren’t great and the c warnings are not useful and get in the way. it’d be nice if the language server wasn’t slow and crashy as well, and if there was an easy to use formatter. having to use a debugger on the generated c code doesn’t sound awesome either but i’ve not had to do that yet.
another concern for me is bindings support, though i haven’t run into any bindings issues yet other than the documentation being out of date on valadoc.org. that site also looks kinda outdated and not particularly inviting
overall documentation on docs.vala.dev is fine.
this is not necessary but there is a language feature that i think would be nice: i’d like to use _ to explicitly ignore function return values and lambda parameters, like this:
The issue there is that native arrays require practically no run-time code to implement (it’s just a pointer and a size), hence we can have them in the language. Hash tables on the other hand need a lot of run-time logic, so even if the syntax was built in, the run-time implementation has to be in some sort of libcoolhash.so, somewhere. That’s currently either libglib-2.0.so or libgee-0.8.so.
Agree, I also generally try to avoid libgee. But maybe we could have something like that as a syntax for the existing GLib has tables? Here’s your example rewritten:
// Calls g_hash_table_new_full, followed by a sequence of g_hash_table_insert-s
var map = new HashTable<string, string> {
"language": "vala",
"toolkit": "gtk",
};
map["language"] // Calls g_hash_table_lookup
map["foo"] = "bar" // Calls g_hash_table_replace
This is a social issue — do you have any thoughts on how we should approach it?
GTK maintainers don’t want to ship gtk4.vapi upstream, which is understandable, indeed they don’t have to ship bindings for other languages.
Shipping gtk4.vapi with Vala, as it’s done currently, is clearly wrong, if only because Vala moves much more slowly compared to GTK.
GNOME SDK packagers, I imagine, don’t feel that it’s their responsibility to harmonize the version of GTK they ship and the gtk4.vapi they ship.
How could we make it work?
One idea that was discussed is for Vala project to only ship Gtk-4.0.metadata & Gtk-4.0-custom.vala, and telling people to produce the vapi from those & the GTK GIR files on their own machines. This is also the approach that peel takes, we ship the API tweaks file, and tell people to generate actual C++ bindings at their project’s build time.
What this is doing is: As seen from Vala, there are two virtual methods named light_map and light_map_broken, all the callers use the former. But as seen from C, there are two methods, gee_future_light_map_fixed and gee_future_light_map, and two corresponding vfuncs light_map_fixed and light_map, all the callers and implementors (written in C, or in Vala and not recompiled) keep using the old (broken) one.
This of course reminds me of ELF symbol versioning championed by glibc, where recompiled callers get the new/fixed version of a symbol, but old ones keep the one they were compiled against.
Not anyone has to go to this length, but a tool to check if your Vala-level changes are introducing unintended C ABI changes might be helpful.
I don’t think this is clearly wrong per-se, it just doesn’t work with the current release schedule. Perhaps changing it to be closely aligned with the GNOME one (perhaps a week after the API freeze) would be a good approach.