Branch
Hash :
6244fe3b
Author :
Thomas de Grivel
Date :
2025-10-21T18:32:49
Make doc
Voici quelques exemples ikc3 avec lesquels vous pouvez vous exercer.
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 !"
ikc3 prend entièrement en charge Unicode :
Quelques caractères Unicode :
ikc3> '\U+1B2FB'
'𛋻'
ikc3> '𐅀'
'𐅀'
ikc3> '🤩'
'🤩'
ikc3>
ikc3> a = 1 + 100000000000000000000000000000000
100000000000000000000000000000001
ikc3> a * a
10000000000000000000000000000000200000000000000000000000000000001
ikc3>
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
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.
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.
Les listes s’écrivent avec des crochets : [].
Les listes régulières peuvent être :
[1 | []] → [1] [1, 2, 3] [1, 2 | [3, 4]] → [1, 2, 3, 4] []
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 :
[1 | 2] [1, 2, 3 | 4] [[] | 1] Tous ces formats de listes sont supportés dans 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]
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.
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
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
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
# 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)