Les deux langages sont petits à dessein et compilent en natif. Keal diffère sur trois points : la nullité est dans le type au lieu que chaque pointeur soit nil-able, les génériques compilent vers une copie par instanciation, et l'échec est un throw qu'on attrape plutôt qu'une seconde valeur de retour.
| Concept | Go | Keal |
|---|---|---|
| Liaison | x := 1 | val x = 1 |
| Mutable | var x = 1 | var x = 1 |
| Struct | type P struct { X int } | record P(val x: Int) |
| Méthode | func (p P) Len() int | func length(): Int (inside the class) |
| Interface | type Ord interface { … } | trait Ord { … } |
| Nil | var s *string = nil | val s: String? = null |
| Erreur | v, err := f(); if err != nil | try { f() } catch (e) { … } |
| Slice | []int{1, 2} | [1, 2] |
| Map | map[string]int{"a": 1} | {"a": 1} |
| Goroutine | go work(ch) | sys.spawn({ self, msg -> … }) |
| Switch | switch n { case 0: } | when (n) { 0 -> … } |
throw "…" et try { } catch (e) { }, sur les trois moteurs y compris le code natif — où cela compile en déroulement vérifié plutôt qu'en setjmp.
Une fonction C par instanciation, sans boxing ni passage de dictionnaire. firstOr<T> utilisé en Int et String devient deux fonctions ordinaires.
Il n'y a ni select ni type canal. Un acteur possède son état, les messages sont copiés en profondeur à l'entrée, et le vérificateur refuse un gestionnaire qui atteint un état mutable partagé.
Compilez un paquet Go en c-archive et passez-le à keal build ; l'exemple du dépôt fait exactement cela.