HelloValaIntroduction
Hello Vala: An Introduction to the Vala Language - Instructors: Lethalman, juergbi
Logs for this session will be available at http://irclogs.ubuntu.com/2011/09/07/%23ubuntu-classroom.html following the conclusion of the session. alright :) hi all, I'm Luca Bruno and I contribute to the Vala project juergbi is the project leader vala is a new programming language with C#-like syntax that compiles to C and targets the GObject type system I'm going to introduce the basics and the features of the vala language the homepage can be found at https://live.gnome.org/Vala you can get the vala compiler with "apt-get install valac", this is likely going to install at least vala 0.12 on an up-to-date system so what's good with vala... :) vala has syntax support for most of GLib/GObject features like classes/interfaces, properties, RTTI, virtual methods, signals, GValue and GVariant boxing/unboxing, error handling and optionally GIO features like GAsync and GDBus it also provides generics, closures, delegates, contract programming, duck typing and some other cool stuff without any additional run-time! https://live.gnome.org/Vala/Documentation#Projects_Developed_in_Vala these are some applications written in vala so, let's start by taking a look at the hello world: http://paste.debian.net/127646/ you can compile it with "valac hello.vala" then run it with "./hello" args is the well known array of strings passed to the command line string[] denotes an array of strings, while "print" refers to "GLib.print" which is static method mapped to g_print() in vala you can have namespaces, and GLib is the default namespace for reference, the online documentation for GLib can be found here: http://valadoc.org/glib-2.0/GLib.html the main() static method is the entry point for applications, it will be executed first at the very basics you might want to see what happens behind the scenes... if you want to see the generated C code, compile with "valac -C hello.vala" then read "hello.c" vala has most of the basic glib types like int, bool, int16, uint16, float, double, string, structs, enums, flags, classes, interfaces and so on so let's take a look at the next example: http://paste.debian.net/127644/ we're defining the "Foo" class that extends the "Object" class then the "bar" property of type int with automatic getter and setter (you can also define custom getter and setter) we have a constructor which takes an int value and sets the bar property, "this" refers to the instance of the class in main() we create a new Foo instance and assign it to the local variable foo the "var" keyword is meant to exploit type inference, so the type of foo is Foo... useful when you're lazy at writing long types ;) you can find other examples of type inference in vala here: https://live.gnome.org/Vala/Tutorial#Type_Inference for completeness let me say that the print() method supports printf-like format (man sprintf), so that you can format the arguments to the output very easily the first important thing to notice is that we don't manually manage the foo variable lifetime in the example, instead vala does manage it vala has automatic memory management using reference counting when possible, so you don't have to manually call ref() or unref() functions for gobjects in this case, the foo variable is automatically unref()'d once it goes out of the scope for more information about the memory model see both http://developer.gnome.org/gobject/stable/gobject-memory.html#gobject-memory-refcount and https://live.gnome.org/Vala/ReferenceHandling what's special in this example is that Foo is a registered GObject class in C and bar is a regular GObject property so, if you tell valac to autogenerate the header (valac -H sample.h sample.vala), C applications can use the class directly in general, vala performs very well in the interoperability area vala can talk to C using vala bindings (.vapi files) without additional run-time that is, vala calls C functions directly without the need of any FFI in fact .vapi files are just descriptions of the API of C libraries e.g. in order to use a foreign package called gtk+-2.0.vapi that is installed in your system, just use valac --pkg gtk+-2.0 yourprogram.vala so that vala compiles your program against gtk+-2.0 and you can use the gtk symbols a .vapi file has the same syntax of a .vala file, thus easy to write manually, see json-1.0.vapi (short enough for a pastebin) for example: http://paste.debian.net/127656/ don't worry, bindings can also be autogenerated from GIR files ;) (http://live.gnome.org/GObjectIntrospection) to generate a somelib.vapi from a gir it's as simple as doing vapigen --library somelib SomeLib-1.0.gir that's a little different than python or javascript or... as it's compile-time stuff anyway, vala itself ships with many bindings, you can see the docs at http://valadoc.org/ ok some more about interoperability then we talk about some cool features :) vala is able to autogenerate well-annotated GIR files to be used from other languages like python, javascript, etc. that means higher level languages can talk to vala just immediately (just two steps without writing any GI annotation like in C) let's see for example: https://live.gnome.org/Vala/SharedLibSample#Calling_vala_functions_using_introspection what we do is first creating a test_shared.so library and tell valac to generate testShared-0.1.gir for us once you got a gir we're done, it's only a matter of generating a typelib using the GI compiler !y shazzner77 asked: weird question, but I have a microcontroller that can be programmed in C. Can I use Vala for this? that's an hard question as it highly depends on the microcontroller most of microcontroller have different C dialects but you can use the posix profile to generate non-glib code somehow, but it's mostly an experimental feature... it's usable to some sort though so, let's talk about error handling vala features error handling on top of GError, with the well known try/catch/finally syntax in other words, you can catch errors thrown by C methods... eek! that sounds weird ;) this is a simple example: http://paste.debian.net/128329/ in the example we try to read a file, if the file doesn't exist (FileError.NOENT) we keep throwing the error, for any other error we abort the program with GLib.error() errors in glib are propagated using GError, so vala autogenerates the necessary code to handle that gracefully you can define your own error types using "errordomain" like this: http://paste.debian.net/128714/ so, this is already a lot of nice features, but that's not all about it! some cool stuff about vala is the syntax support for async operations, closures and dbus client/server it is possible to define GIO-style async methods and calling other async methods very easily an async method returns immediately giving control back to the caller, and when the job is completed a callback is fired take a look at the first example here: http://live.gnome.org/Vala/AsyncSamples the "async" keyword in front of list_dir() marks it as being a GIO-style coroutine yield dir.enumerate_children_async() will pause the method, then it will be resumed once there's a result... that's amazingly simple (in the meantime, thanks to nemequ for doing a great work in -chat :P) also notice in the main() method (which is not an async method) that we used a closure to be notified when list_dir() completes its job list_dir.begin() will initiate the async operation, then when the job is complete we free the resources with list_dir.end() closures are an important feature of vala compared to raw C a closure (or lambda expression, or ...) is a method created on-the-fly that shares the scope of the parent method (main() in this case) this is very very useful for callbacks for which you need to pass user data in fact, in the example the "loop" variable is used within the closure, but it's defined outside the closure the general syntax for defining lambda expressions is (param1, param2, ...) => { ... body here ... } the types of param1, param2, ... automatically match the parameters of the target type in this case the target type is AsyncReadyCallback which is a delegate type (i.e. a type that accepts methods) here's the definition of AsyncReadyCallback: http://www.valadoc.org/gio-2.0/GLib.AsyncReadyCallback.html it takes two parameters, an Object and an AsyncResult... that's why we used (obj,res) => { ... } in the example kermit66676 asked: I noticed there is no #include directive when using a library in Vala - doesn't that make things messy in bigger applications with a lot of packages - you have to watch out not to repeat class names from some other libraries? Or use namespaces all the time... if I understood the question correctly... when you compile a project you feed to valac all the .vala files at once valac file1.vala file2.vala ... for what concerns collision with existing names, yes namespaces are used for that but applications or libraries written in vala usually have their own namespace, that's the best practice mjaga asked: is valac part of the gcc family? no it isn't, it's a self-hosted compiler on its own but valac uses the C compiler as it produces C code it's very slim and compiles fast, most of the time spent on compiling is usually due to the C compiler vala lets the underlying C compiler optimize things... so... the async stuff is very powerful when combined with dbus :) we can call dbus methods (well, a property in this case) in a such simple way: http://paste.debian.net/128341/ methods of UPower would have suspended your workstation, so :P the interface in the example is a way for vala to generate proxy calls to the dbus interface the "can_hibernate" property is mapped to the dbus property org.freedesktop.UPower.CanHibernate what we do here is starting the async upower_query() operation, which will asynchronously connect to the system bus and request a proxy for UPower afterwards we request the value of the "can_hibernate" property... bool.to_string() is an helper method defined by vala, you know what it does :) vala automatically does dbus serialization of values when doing dbus stuff (the bool property in this case), even for the most complex types this is about client code, but you can write dbus servers by just writing normal class methods take for example this server code: http://paste.debian.net/128754/ and the following client snippet to query the server: http://paste.debian.net/128756/ compile the server with "valac dbusserver.vala --pkg gio-2.0" and the client with "valac dbusclient.vala --pkg gio-2.0" so you can start the server with ./dbusserver and then invoke the client multiple times with ./dbusclient if everything goes well, on the client you should see a counter increasing on each call notice: as said in -chat not _all_ of the complex types, there might be some bug/limitation but you can use GLib.Variant manually as well in this case we assumed the client didn't know the server codebase, otherwise we could share the same interface definition and let the server class implement it server side we do some other stuff for acquiring the name, registering a callback when it's available so, this vala integration is very important as our desktops are leading toward async and dbus more and more there are several projects that massively use such advanced features of vala successfully after this low level stuff we can take a look at some GUI with GTK+: http://live.gnome.org/Vala/GTKSample reference docs for gtk3 can be found here: http://valadoc.org/gtk+-3.0/index.htm the "using Gtk;" statement on the top means that the Gtk namespace is merged in the file therefore we can use "new Window ()" instead of "new Gtk.Window ()", and so on also notice window.title = "First GTK+ Program"; window.title is a gobject property, we saw them in the first hello world example in this case vala will generate the C code for calling gtk_window_set_title (GTK_WINDOW (window), "First GTK+ Program") properly in the example we can also see the button.clicked.connect() call: it's used to connect to the "GtkButton::clicked" signal! the first argument is the callback that will be fired when the signal is emitted you can also specify a method (static method or instance method) as the signal callback, not only a closure I've written an equivalent code here without the use of a closure: http://paste.debian.net/128743/ yeah, it's more typing without closures ;) as you can see writing gui with vala is very simple, and you can take advantage of async operations for doing I/O without blocking the GUI! so now we're connecting to a signal, but in vala defining signals is as easy as putting a "signal" keyword in front of a method declaration an example of signal definition can be found here: https://live.gnome.org/Vala/Tutorial#Signals in that code we defined a full gobject signal named "sig_1" with an int parameter... like properties, signals can be used from C as well as higher level languages and emitting the signal is as simple as calling a normal method: t1.sig_1 (5) ok now let's talk a little about generics generics in vala are similar to C# or Java generics they are used to restrict the type of data that is contained in a class, both at compile-time and at run-time (no type erasure) for example let's use GList, which is a glib structure for doubly linked lists: http://paste.debian.net/128737/ the type List<string> will define a list whose elements are of type string then we append to strings to the list, and print them the foreach statement is another neat feature of vala, allowing to iterate through the elements of a collection the syntax is simple: foreach (element_type variable_name in container_expression) { ... } in this case we used "var" as element type to exploit the type inference roughly speaking, in this case vala will infer the element type from the generic type of the container which is "string" There are 10 minutes remaining in the current session. mhr3 asked: there's this nice syntax to read/write gobject properties, are there any plans to have similar support for widget style properties? well, not that I know of anyway while the properties defined in a class are known at compile-time, not necessarily style properties (or child properties...) are known at compile-time so it may lack some type checking... if you have a clear idea you can feature request it :) you can also define your own complex types using generics like the first example here: https://live.gnome.org/Vala/Tutorial#Generics glib offers several data structures already, but there's also libgee that provides a collection library that is written in vala and widely used libgee is more vala-friendly and has data structures such as TreeMap, PriorityQueue, HashSet, HashMultiMap, etc. the reference docs for libgee can be found here: http://valadoc.org/libgee-0.7/index.htm ok... we're almost done :) vala comes with libvala, which is a library for parsing and analyzing the vala code and generating code... There are 5 minutes remaining in the current session. despite the libvala API is not stable, there are many users of it like IDEs, documentation tools, code generators, etc. for generating documentation for you projects you can use valadoc: https://live.gnome.org/Valadoc there're lots of other neat features like lock statement, inheritance, virtual/abstract methods and properties, etc. that we didn't mention... or experimental features like chained expressions: foo < bar < baz < mama or regex literals like in perl: /.../ will create a GLib.Regex if you want to know more the tutorial at https://live.gnome.org/Vala/Tutorial is a good start... and the community is wide and very active ;) ok that's all, thanks everyone :) ok suggested from -chat to mention our community is on the mailing list vala-list@gnome.org and on #vala on irc.gimp.org
MeetingLogs/appdevweek1109/HelloValaIntroduction (last edited 2011-09-08 09:16:58 by dpm)