Branch :
# 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 :
```elixir
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` :
```elixir
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 :
```elixir
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 :
```elixir
ikc3> '\U+1B2FB'
'𛋻'
ikc3> '𐅀'
'𐅀'
ikc3> '🤩'
'🤩'
ikc3>
```
## Grands entiers
```elixir
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.
```elixir
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 b`
où `a` et `b` sont des nombre flottants.
```elixir
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 :
```elixir
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 :
```elixir
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 :
```elixir
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` :
```elixir
ikc3> if 42 then 100 else 101 end
100
ikc3> if 0 then 100 else 101 end
101
```
## defmodule et def
Exemple :
```elixir
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 :
```elixir
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](3.4_Structure)