Tutoriel KC3 et exemples

Voici quelques exemples ikc3 avec lesquels vous pouvez vous exercer.

Maps

Les maps KC3 sont des structures clé-valeur. Vous pouvez utiliser n’importe quel Tag comme clé et lui associer une valeur.

Vous pouvez utiliser la déstructuration pour accéder aux maps KC3 :

ikc3> a = %{id: 1, title: "My title", message: "Hello, world !"}
%{id: 1, title: "My title", message: "Hello, world !"}
ikc3> a = %{}
%{id: 1, title: "My title", message: "Hello, world !"}
ikc3> %{id: id, title: "My title", message: message} = a
%{id: 1, title: "My title", message: "Hello, world !"}
ikc3> id
1
ikc3> message
"Hello, world !"

Vous pouvez utiliser la syntaxe par point pour accéder aux valeurs d'une clé Sym :

ikc3> a = %{id: 1, title: "My title", message: "Hello, world !"}
%{id: 1, title: "My title", message: "Hello, world !"}
ikc3> a.id
1
ikc3> a.message
"Hello, world !"

Vous pouvez également utiliser la fonction KC3.access pour obtenir le même résultat :

ikc3> a = %{id: 1, title: "My title", message: "Hello, world !"}
%{id: 1, title: "My title", message: "Hello, world !"}
ikc3> access(a, :id)
1
ikc3> access(a, :message)
"Hello, world !"

Unicode characters

ikc3 prend entièrement en charge Unicode :

Quelques caractères Unicode :

ikc3> '\U+1B2FB'
'𛋻'
ikc3> '𐅀'
'𐅀'
ikc3> '🤩'
'🤩'
ikc3>

Grands entiers

ikc3> a = 1 + 100000000000000000000000000000000
100000000000000000000000000000001
ikc3> a * a
10000000000000000000000000000000200000000000000000000000000000001
ikc3>

Ratios

Les ratios sont créés avec un couple d'entiers : le numérateur qui peut être n'importe quel entier, et le dénominateur qui doit être positif. Ils représentent des fractions de nombres entiers. Ils s’écrivent avec un slash sans espace.

ikc3> 1/2 + 2/3
7/6
ikc3> 1/2 * 2/3
1/3
ikc3> 1/2 / 2/3
3/4
ikc3> 1/2 - 2/3
-1/6

Nombres complexes

Les nombres complexes sont construits à l’aide de l’opérateur +i sur tout type de nombre (entiers signés, non signés, flottants, ratios, ou même d'autres nombres complexes). Par exemple vous pouvez ecrire a +i ba et b sont des nombre flottants.

ikc3> 1 +i 2
1 +i 2
ikc3> 1 +i 2 + 2 +i 3
3 +i 5
ikc3> (1 +i 2) * (2 +i 3)
-4 +i 7
ikc3> (1 +i 2) / (2 +i 3)
0 +i 0
ikc3> (1/1 +i 2/1) / (2 +i 3)
8/13 +i 1/13

Comme vous pouvez voir la division entiere ne produit pas de fractions. Cela pourrait changer dans les versions futures.

Lists

Les listes s'écrivent avec des crochets : [].

Les listes régulières peuvent être :

  • un élément et une liste : [1 | []][1]
  • plusieurs éléments : [1, 2, 3]
  • plusieurs éléments et une liste : [1, 2 | [3, 4]][1, 2, 3, 4]
  • la liste vide : []

Les listes régulières se terminent toutes par la liste vide : [1] == [1 | []].

On peut également contruire des listes pointées comme en Common Lisp où le pointeur de liste suivante est une valeur arbitraire (Tag). Par exemple :

  • un élément et un élément : [1 | 2]
  • plusieurs éléments et un élément : [1, 2, 3 | 4]
  • la liste vide et un élément : [[] | 1]

Tous ces formats de listes sont supportés dans la déstructuration.

L'identification de motifs et la déstructuration

Les principes de pattern-matching viennent d'Erlang et Elixir.

Toutes les structures de données taggées de KC3 peuvent être identifiées (match) par un motif (pattern) en utilisant le signe égal (=) sur des valeurs littérales contenant des identifiants. Tous les identifiants sont repérés comme des nouvelles variables qui seront liées à une valeur lors de la déstructuration. Si vous voulez utiliser une variable c'est possible dans un appel de fonction ou en utilisant l'operateur identité : ^ ma_variable. Les variables peuvent se trouver de chaque coté du signe égal tant qu'une vraie valeur se trouve dans la même structure de l'autre côté de l'operateur égal.

Exemples :

ikc3> a = 1
1
ikc3> a = 2
2
ikc3> a
2
ikc3> ^ a = 1
void
ikc3> ^ a = 2
2
ikc3> ^ a = b
2
ikc3> b
2

Pour utiliser la déstructuration il suffit de taper la valeur littérale que l'on veut identifier et de mettre des identifiants sur les parties inconnues que l'on veut récupérer de l'autre coté du signe égal. C'est l'approche la plus visuelle possible pour programmer une identification de valeurs, bien plus simple que SQL ou SPARQL. Les données sont constamment affichées dans le code en affichant les variables dans la structure d'origine. On voit les données et leur type à l'écran constamment. Cela aide vraiement pour écrire de gros programmes qui ont besoin de grandir en terme d'abstractions : laisser les données passer dans le code à travers des types visuels.

Exemples :

ikc3> [x, y | z] = List.reverse([1, 2, 3, 4])
[4, 3, 2, 1]
ikc3> x
4
ikc3> y
3
ikc3> z
[2, 1]

Macros

Les macros KC3 sont comme les macros Common Lisp avec le pattern-matching (déstructuration) d'Elixir.

Les macros sont comme des fonctions mais sont introduites par macro au lieu de fn et leurs arguments ne sont pas évalués. Par contre ils sont déstructurés avec toute la puissance du pattern-matcher pour extraire des variabes des arguments passés à la fonction. On peut utiliser un Map pour avoir des arguments nommés, une liste pour avoir des arguments &rest, ou un bloc pour avoir un argument &body.

Une fois évaluée un appel de macro retourne un Tag (une valeur) qui est à son tour évaluée dans l'environnement lexical de l'appel. Cela permet la création de DSL (domain-specific languages) en KC3.

Plusieurs opérations basiques sont définies comme des macros en KC3 : la gestion des erreurs, les segment de code de clean-up avec unwind_protect, les opérations sur la base de données en graphe.

If, then, else.

Les conditions en KC3 fonctionnent comme en Ruby, par exemple :

ikc3> if true && true
ikc3>   1 + 1
ikc3>   2 + 2
ikc3> end
4

ikc3> if true && false
ikc3>   1 + 1
ikc3>   2 + 2
ikc3> else
ikc3>   3 + 3
ikc3>   4 + 4
ikc3> end
8

Un if renvoie toujours une valeur. Si la condition est vraie une fois castée en Bool avec Bool.cast (bool_init_cast), le premier bloc est évalué et retourné. Si la condition donne false (faux) alors le second bloc est évalué (else). Si la condition est fausse et qu'il n'y a pas de second bloc, void est retourné.

Exemples sur une seule ligne avec then :

ikc3> if 42 then 100 else 101 end
100
ikc3> if 0 then 100 else 101 end
101

defmodule et def

Exemple :

ikc3> defmodule Example do
ikc3>   def three = 3
ikc3>   def double = fn (x) do x * 2 end
ikc3>   def double_tuple = macro (x) do {x, x} end
ikc3>   def operator_double = %KC3.Operator{sym: :double, symbol_value: fn (x) { x * 2 }
ikc3> end
Example
ikc3> Example.three
3
ikc3> Example.double
fn (x) do x * 2 end
ikc3> Example.double(21)
42
ikc3> Example.double_tuple(:ok)
{:ok, :ok}
ikc3> double 21
42

Facts

Le module Facts (faits) permet un acces en lecture et en écriture vers une base de données en graphe contenant des faits : des triplets sujet, relation, objet.

Des exemples pour faire des requêtes sur la base de données de KC3 contenant toutes les définitions de l'interpreteur :

ikc3> Facts.with_tags(Facts.env_facts(), KC3, :op, ?,
        fn (fact) { puts(fact.object); :ok })
operator_eq
operator_gt
operator_lt
[...]
:ok

Top : KC3 Guides

Previous : Guide de la structure de KC3