A začneme hezky zostra, ať to má trochu šťávy. Nejjednodušší a nejznámější aplikace hello world, tedy ahoj světe by mohla vypadat třeba takto:
void main(){
stdout.printf("Hello world!\n");
}
To by byla ale docela nuda, a přeci jen, funkce main by měla odpovídat nějakým standardům, tedy rozšíříme:
int main(string[] args) {
stdout.printf("Hello world!\n");
stdout.printf("You have %d args:\n", args.length);
foreach (string arg in args) {
stdout.printf(@"\targ: $arg\n"); // varianta 1
stdout.printf("\targ: %s\n", arg); // varianta 2
}
return 0;
}
Tento jednoduchý příklad nám ukazuje hned několik typických přístupů. Hlavní funkce main vrací číslo typu int a přijímá pole stringů. Pole stringů lze iterovat použitím slova foreach. Zápis je podobný C++, konec konců stejně jako v C++ je uveden i zápis pole stringů. Na konci každého příkazu je uveden středník. Protože je uveden návratový typ funkce, je nutné funkci ukončit vrácením hodnoty daného typu.
Stdout je statický objekt třídy FileStream
, jenž mimo jiných obsahuje i metodu printf
. Metoda printf je totožná s fprintf z céčkového stdio.h
. Vedle stdout
je možno použít i stdin
, nebo stderr
. Jak je vidět na třetím řádku, pole stringů obsahuje vlastnost length
.
A konečně šestý a sedmý řádek názorně ukazuje, jak je možné dobrat se dvojí cestou k jednomu výsledku. Pravdou samozřejmě je, že použití druhé, pro jazyk C typické varianty je o něco méně náročnější na výsledný C kód. Ovšem co je optimálnější pro výsledný assembler, resp. binárku jsem nezkoumal.
Jak jsem v minulém díle naznačil, kompilátor valac, jakožto zatím jediný kompilátor jazyka Vala, umožňuje kompilaci různým způsobem. Ten nejjednodušší způsob je prostě zavolat kompilátor s názvem zdrojového souboru.
$~ valac hello_world.vala
Kompilátor soubor přímo zkompiluje do výsledné binární podoby. Spustitelný soubor se nečekaně jmenuje hello_world
. Kompilátor má samozřejmě mnoho různých voleb, k některým se teprve dostaneme, již nyní by se hodilo prozradit alespoň některé.
-?, --help | vypíše nápovědu |
--version | vypíše verzi kompilátoru |
--pkg=PACKAGE | použije balíček pro valu |
-C, --ccode | vytvoří zdrojové .c soubory |
-H, --header=SOUBOR | vytvoří hlavičkové .h soubory |
-d, --directory=ADRESÁŘ | soubor pro výstupní soubory |
-o, --output=FILE | nastavení výstupního souboru |
-g, --debug | kompilace s debug informacema |
--cc=COMMAND | nastavení C kompilátoru |
--profile=PROFILE | nastavení profilu generování C kódu |
Při psaní aplikace se programátor málokdy obejde bez různých knihoven. Tyto knihovny jsou ve vale přístupné jako tzv. balíčky. Funguje to tak, že pro knihovnu je vytvořen soubor vapi
. Ten vlastně popisuje způsob, jakým jsou interpretované objekty, struktury, funkce, metody a výjimky patřičné knihovny. Jaké knihovny mají tzv. vala binding se dovíte na stránkách projektu. Použití takových balíčků si ukážeme později, pro teď zmíním, že jde o parametr --pkg
.
V minulém díle jsme také probíraly, že kompilátor valac, vlastně generuje C soubory a ty pak kompiluje C kompilátorem. Volby -C a -H
umožní vytvoření patřičných .c a .h souborů. To se může hodit při různých příležitostech. Mimo jiné například při kompilaci rozsáhlého projektu, kdy programátor ušetří strojový čas inkrementální kompilací jednotlivých .c souborů. Parametr --cc
pak umožňuje nastavit jiný než výchozí (gcc) kompilátor.
Poslední parametry, na které se dnes podíváme jsou -g a --profile
. Parametr -g
stejně jako v případě c kompilátoru přidává do výsledné binární podoby řetězce používané k ladění. Jak ladit takovou aplikaci si ukážeme později. Parametr --profile
říká kompilátoru valac, jak má generovat c-kód. Na výběr má programátor tři možnosti: gobject
(implicitní), posix a dova
(experimentální). Valac podle toho generuje c-kód s odlišnými závislostmi.
Za domácí úkol si můžete zkusit vygenerovat zdrojový c soubor. Při letmé studii výstupního souboru zjistíte, jak Vala vlastně pracuje. A přeci jen, studovat zdrojový c soubor je snazší, než assembler :)
Psaní programu v jazyce Vala jsou dle mého názoru intuitivní a autoři jazyka nevymýšleli žádné nové druhy zápisů pokud nemuseli. A když už to udělali, inspirovali se jinde. Tedy, názvy tříd začínají velkými písmeny. V případě víceslovných názvů pak každé slovo začíná velkým písmenem „MojeNovaTrida”
.
Názvy metod a funkcí a proměnných se píší malými písmeny. V případě víceslovných názvů se slova oddělují podtržítkem „moje_super_metoda”
. Konstanty se píší velkými písmeny, což C/C++ programátorům správně připomíná že konstanty jsou implementovány jako #define
. Kapitálkami se píší i jednotlivé stavy výčtového typu. To platí i pro výjimky, které se, jak jsem zmínil v předchozím článku, zapisují stejně jako výčtový typ. Název error domény, i výčtového typu se zapisují stejně jako názvy tříd, tedy s prvním velkým písmenem v každém slově.
Jako jiné jazyky i Vala podporuje namespace. Ten je uvozen klíčovým slovem namespace a zapisuje se stejně jako název tříd nebo výčtového typu. Veškeré cesty v takto definované struktuře se oddělují tečkou a to platí i pro výčtové typy. Zápis tedy vypadá takto:
throw new Namespace.ErrorDomena.TENTO_TYP("Text vyjimky");
Namespace.Trida.staticka_metoda("parametr metody");
var obj = new Namespace.SuperTrida();
var foo = new Namespace.Foo.pretizeny_konstruktor();
int boo = Namespace.Vycet.STAV_VYCTU;
Výše popsaný zápis podrobně vysvětlím v dalších článcích. Je dobré ale zmínit že namespace se nemusí stejně jako v C++ psát, pokud nejprve deklarujete, že tento namespace budete použivat. Použití namespacu deklarujete podobně jako v C++ slovem using, ovšem bez klíčového slova namespace:
using Gtk;
int main(string [] args){
init(ref args); // volá se Gtk.init
return 0;
}
Nejpoužívanější a v podstatě všudepřítomný namsespace je GLib. Ten je implicitně používán a proto není nutné jej explicitně jmenovat nebo deklarovat jeho používání slovem using
. Zde bych ale rád apeloval na Vás, vývojáře, abyste zvážili používání klíčového slova using. Můžeto totiž vést k nečekaným chybám, právě proto, že některé knihovny se velmi často a velmi rádi překrývají. A třeba později až budeme pracovat s Gtk, volání metody main z knihovny Gtk neuděláte jinak, než explicitním jmenováním namespace. To proto, že vyhrávají poslední deklarované / definované metody, a vytvořit metodu se stejným názvem (jako třeba main
) je velmi snadné.
Z tohoto důvodu a i pro větší přehlednost budu dále používat názvy metod a tříd včetně jejich namespace. A to i v případě, že jde o standardní GLib namespace.
Nejprve kód:
class HelloWorld : GLib.Object {
public static int main(string[] args) {
stdout.printf("Hello, World\n");
return 0;
}
}
Tento trochu výřečnější zápis, je brán jako pattern toho jak by to mělo vypadat. Jeho podoba asi nepřekvapí C# ani Java programátory, v podstatě se dá volně přeložit jako aplikace HelloWorld se standardní statickou metodou main.
V praxi se pak zvláště v případě Gtk+ aplikací budeme setkávat s oněco zřejmějším použitím:
class HelloWorld : GLib.Object {
public void run(ref string[] args) {
stdout.printf("Hello, World\n");
}
public static int main(string[] args) {
HelloWorld app = new HelloWorld();
app.run(ref args);
return 0;
}
}
Příště si ukážeme práci s textem. Pokusíme se vytvořit konsolovou aplikaci, která bude pracovat s json v souboru. Bude ho umět rozšiřovat, měnit a vizualizovat. A samozřejmě se nebráním Vašim nápadům, které můžete napsat do komentářů.
© 2023 Ondřej Tůma McBig. Ondřej Tůma | Based on: Morias | Twitter: mcbig_cz | RSS: články, twitter