Comment Softanza s'écrit
Softanza s'écrit de sorte qu'un nom dise ce que fait un appel, qu'une condition voyage dans un argument, qu'une boucle laisse place à une métaphore, et que la bibliothèque puisse s'expliquer elle-même. Ce sont des conventions tenues sur des milliers de méthodes. Cette page montre chacune en marche.
Un nom est une phrase
Le nom d'une méthode se lit comme une courte phrase : le verbe dit ce qui se passe, et la forme du mot dit comment. Remove() modifie l'objet. Removed() rend une copie modifiée et garde l'original. RemoveQ() le modifie et le rend, pour que la phrase continue. Les suffixes ajoutent un sens de la même façon dans toutes les classes : un réglage de casse, une condition, des options étendues, des positions ou des sections, une position de départ.


Les formes sont un système, pas une habitude : la bibliothèque lit ses propres noms avec une grammaire, et un audit liste chaque verbe auquel il manque l'une de ses trois formes principales. C'est pourquoi la classe des chaînes porte 2 117 méthodes propres et la classe des listes 1 583, et pourquoi un lecteur qui connaît un verbe connaît déjà sa famille.
Un verbe sous trois formes : la forme passive rend une copie inversée et garde l'original, la forme active modifie la liste, et la forme fluide la modifie puis laisse la phrase continuer.
o1 = new stzList(L(' "♥1" : "♥3" '))
# the passive form returns a copy and keeps the original
? @@( o1.ItemsReversed() )
? @@( o1.Content() )
# the active form changes the list itself
o1.Reverse()
? @@( o1.Content() )
# the fluent form changes it and lets the sentence go on
o1 = new stzList(L(' "♥1" : "♥3" '))
? o1.ReverseQ().ToStzListOfStrings().ConcatenatedUsing("~")[ "♥3", "♥2", "♥1" ] [ "♥1", "♥2", "♥3" ] [ "♥3", "♥2", "♥1" ] ♥3~♥2~♥1
exécuté le 2026-10-15 13:37 dans la bibliothèque au commit 4a184e6f0 ; tiré de base/test/list/69_understanding_the_ed_and_q_function_forms.ring(s'ouvre dans un nouvel onglet)
Le suffixe CS ajoute un réglage de casse : sans lui, il n'y a pas de second « arem » ; casse ignorée, le second est « AREM », en position 3.
o1 = new stzList([ "arem", "mohsen", "AREM" ]) ? o1.FindNth(2, "arem") ? o1.FindNthCS(2, "arem", :CS = FALSE)
0 3
exécuté le 2026-10-15 13:37 dans la bibliothèque au commit 4a184e6f0 ; tiré de base/test/list/372_findall.ring(s'ouvre dans un nouvel onglet)
- Un verbe, jamais un nom nu. Un nom dit ce que fait l'appel :
AddCircle(), pasCircle(). - Des verbes calmes. Remove, Clear, Close ; jamais Kill ni Destroy.
- Donnée ou objet, dit par le nom. Une forme simple rend une donnée ; la forme
Qrend l'objet, pour qu'une chaîne d'appels ne devine jamais ce qu'elle tient. - Le nom d'un paramètre dit son type.
pcpour un texte,pnpour un nombre,papour une liste,pbpour un oui ou un non.
De petites langues dans les arguments
Certains arguments ne sont pas des valeurs mais des phrases dans une petite langue. Une condition comme "{ @item > 5 }" est compilée par le moteur et vérifiée sur chaque élément, sans jamais évaluer de code : elle reste sûre même quand elle vient d'un utilisateur ou d'un fichier. Un paramètre nommé comme :With = "coffee" ou :StartingAt = 3 fait lire un appel comme une phrase. Les motifs sur les listes, les nombres, les tables et le temps suivent la même idée, et les chaînes quasi naturelles laissent une ligne de code se lire comme de l'anglais.
Une condition voyage comme un court texte dans l'argument ; le moteur la compile et répond par les positions, les éléments ou leur nombre.
o = new stzList([ 4, 7, 10, 3, 8 ])
? @@( o.FindW("{ @item > 5 }") )
? @@( o.ItemsW("{ @item > 5 }") )
? o.CountW("{ @item > 5 }")[ 2, 3, 5 ] [ 7, 10, 8 ] 3
exécuté le 2026-10-15 13:37 dans la bibliothèque au commit 4a184e6f0 ; tiré de base/education/program/courses/elementary-introduction/chapters/07-declare-what-not-how.en.md(s'ouvre dans un nouvel onglet)
Les paramètres nommés font lire un appel comme une phrase, et les positions comptent des caractères : chaque puce compte pour un.
? Q("tea, rice, tea").Replaced("tea", :With = "coffee")
o1 = new stzString("..•.•..")
? o1.FindNext("•", :StartingAt = 3)
? o1.FindPrevious("•", :StartingAt = 5)coffee, rice, coffee 5 3
exécuté le 2026-10-15 13:37 dans la bibliothèque au commit 4a184e6f0 ; tiré de base/education/program/courses/elementary-introduction/chapters/03-read-the-name-as-a-sentence.en.md(s'ouvre dans un nouvel onglet)
Une chaîne quasi naturelle se lit comme la phrase « chacun a au moins deux voyelles », et quand elle est fausse, Why() désigne l'élément fautif.
? Q([ "AnnIE", "aeiou" ]).EachQ().AtLeastQ(2).VowelNB() ? Q([ "AnnIE", "sky" ]).EachQ().AtLeastQ(2).VowelNB() ? Why()
1
0
no: item 2 ("sky") fails -- no: expected atleast 2, found 0exécuté le 2026-10-15 13:37 dans la bibliothèque au commit 4a184e6f0 ; tiré de base/test/natural/nnl_narrated.ring(s'ouvre dans un nouvel onglet)
La manière Softanza Une petite langue dans un argument dit ce que l'on veut, et la bibliothèque décide comment l'obtenir. La boucle, l'indice et la variable temporaire disparaissent de la page.
Quatre métaphores au lieu des boucles
Une boucle cache le geste qu'elle fait. Softanza nomme les quatre gestes, et une tâche se décompose en eux.
Le marcheur
Parcourt des positions : il connaît tout son trajet avant de bouger, les pas qu'il fera, ceux qu'il sautera, et l'endroit où il se trouve. Il vit dans la couche max.
Le vérificateur
Pose des questions par oui ou par non sur les éléments : tous, l'un d'eux, aucun, là où une condition vaut.
Le producteur
Produit de nouvelles données à partir des anciennes : il filtre, transforme et réduit, et son cœur tourne dans le moteur.
L'acteur
Agit sur place : il change les éléments qu'on lui dit de changer, là où une condition vaut.
Le « yielder », l'une des quatre métaphores : il filtre, transforme et additionne les recettes du jour sans une seule boucle.
oY = new stzYielder([ 12, 0, 30, -5, 18 ]) ? @@( oY.Filter(:IsPositive) ) ? @@( oY.Map(:Double) ) ? oY.Reduce(:Sum)
[ 12, 30, 18 ] [ 24, 0, 60, -10, 36 ] 55
exécuté le 2026-10-15 13:37 dans la bibliothèque au commit 4a184e6f0 ; tiré de base/education/program/courses/elementary-introduction/chapters/06-walk-ask-produce-act.en.md(s'ouvre dans un nouvel onglet)
Quatorze règles d'écriture
Tout ce qui précède est une seule grammaire. Écrite en règles, elle en compte quatorze, et une ligne de code qui les suit se lit comme la pensée qui la porte. Ce sont des lectures du code et des articles de la bibliothèque, énoncées en règles. L'exemple de chaque règle est écrit sous elle, sans être exécuté ; les exécutions qui suivent en montrent plusieurs à l'œuvre.
- Une valeur est élevée à son objet par Q(), ou par son élévateur typé quand le type est l'enjeu.
Q("Niamey ♥") - Une scène est un bloc d'accolades sur un objet, et les questions se posent à l'intérieur.
Q("Niamey ♥") { ? NumberOfChars() ? Uppercased() } - Chaque ligne imprimée porte sa réponse sous #--> ; une réponse sur plusieurs lignes est dessinée comme la console la montre.
? o1.CountEmptyStrings() #--> 3 - Un paramètre est nommé, et le nom se lit comme du français ou de l'anglais courant.
Q("tea, rice, tea").Replaced("tea", :With = "coffee") - Une chaîne suit l'ordre de la pensée : un pas par ligne, le point en fin de ligne.
Q("LIFE").LowercaseQ().SpacifyQ(). ... - La forme du verbe dit ce qui arrive : Remove agit, Removed rend une copie, RemoveQ rend l'objet.
Remove() Removed() RemoveQ() - Les suffixes et les préfixes sont petits et ne veulent dire qu'une chose chacun : CS, XT, FF, W, Z, ZZ.
FindNthCS(2, "arem", :CS = FALSE) - Une fonction a des variantes pour la façon dont une personne la dit.
NumberOfOccurrenceOfCharLeftSide("-") HowManyOccurrenceOfCharRightSide("-") - La précision avant la généralité, quand elle ne coûte rien : NumberOfChars() plutôt que Size() ; ContainsBoth, ContainsAll, ContainsSome.
Q("one two three").ContainsBoth("one", "three") - Le code voyage dans un argument comme une petite chaîne, avec @item, @char, @1 comme repères.
o.FindW("{ @item > 5 }") - De petits langages littéraux vivent dans des chaînes.
L(' "♥1" : "♥3" ') - Une phrase peut rester presque naturelle.
_(8).IsA(:Number).Which('IsDoubleOf(4)')._ - Une fonction peut être nommée dans n'importe quelle langue humaine.
字符数() - Un commentaire parle avant le code, de la voix du maître ; un bloc de test est encadré par /*--- titre, pr() et pf().
# the passive form returns a copy and keeps the original
Règles 1, 2 et 9 : la valeur élevée par Q(), une scène où l'on pose plusieurs questions à un seul objet, et NumberOfChars() plutôt qu'un vague Size().
# a scene: one object, and the questions asked inside it
Q("Niamey ♥") {
? NumberOfChars()
? Uppercased()
? StartsWith("Nia")
}8 NIAMEY ♥ 1
exécuté le 2026-10-15 13:37 dans la bibliothèque au commit 4a184e6f0 ; tiré de base/doc/narrations/stz-functions-as-linguistic-expressions.md(s'ouvre dans un nouvel onglet)
Règles 5 et 6 : une chaîne dans l'ordre de la pensée, un pas par ligne et le point en fin de ligne, chaque verbe sous sa forme Q pour que la phrase continue.
? Q("LIFE").
LowercaseQ().
SpacifyQ().
CharsQ().
RemoveSpacesQ().
UppercaseQ().
JoinQ().
SpacifyQ().
ReplaceQ("I", :With = AHeart()).
Content()L ♥ F E
exécuté le 2026-10-15 13:37 dans la bibliothèque au commit 4a184e6f0 ; tiré de base/doc/narrations/stzobject-history-narration.md(s'ouvre dans un nouvel onglet)
Règle 9, la précision avant la généralité : ContainsBoth dit exactement ce qui est demandé, là où un Contains général demanderait une boucle.
? Q("one two three").ContainsBoth("one", "three")
? Q([ 1, 2, 3 ]).ContainsBoth(1, 4)1 0
exécuté le 2026-10-15 13:37 dans la bibliothèque au commit 4a184e6f0 ; tiré de base/string/stzString.ring(s'ouvre dans un nouvel onglet)
Règle 12 : une ligne de code peut rester presque naturelle, une affirmation que la bibliothèque juge vraie ou fausse, une question à laquelle elle répond depuis ce qu'elle sait.
# a sentence the library can judge
? _(8).IsA(:Number).Which('IsDoubleOf(4)')._
# and a question it answers from what it was told
StzKnow(:Apple, :Fruit)
? @@( WhatIs(:Apple) )1 [ "fruit" ]
exécuté le 2026-10-15 13:37 dans la bibliothèque au commit 4a184e6f0 ; tiré de base/test/chainoftruth/16_all_these_return_1.ring(s'ouvre dans un nouvel onglet)
La manière Softanza Les mêmes règles servent les sept étapes du modèle mental, une règle ou deux à chaque étape. La page suivante met les deux côte à côte.
Conventions
- Les positions commencent à 1, et 0 veut dire « absent ». On compte à partir de un ; chaque couche aussi, moteur compris.
- Des caractères, pas des octets. Une longueur ou une position compte les lettres qu'une personne lit, dans toutes les écritures.
- Le moteur d'abord. La substance va dans le moteur, écrite une fois, et la langue au-dessus en est le visage.
Q()fait d'une valeur un objet. Une valeur simple reste une donnée ;Q("texte")devient un objet chaîne et ses milliers de méthodes.- Trouver d'abord, puis appliquer. Où est-ce, et que dois-je y faire : les deux mêmes étapes dans tous les domaines.
- Les mêmes verbes pour toutes les structures. Ce qui marche sur une chaîne marche en général sur une liste.
- Un vrai s'affiche 1. La console affiche une réponse vraie par 1 et une fausse par 0 : c'est pourquoi les sorties de ce site se lisent ainsi.
Une bibliothèque qui s'explique
Chaque méthode porte, juste au-dessus de sa définition, une ligne qui dit ce qu'elle fait dans les mots de l'utilisateur, et des étiquettes facultatives : d'autres noms qu'un lecteur pourrait employer, la forme de la réponse, un exemple, les méthodes voisines. Une vraie, tirée de la classe des textes :
# The overall tone/mood of the text as "positive", "negative", or "neutral".
#@ aka mood, emotion, feeling, attitude, opinion, how positive or negative
#@ out string: "positive" | "negative" | "neutral"
#@ eg Q("The food was terrible.").Text().Sentiment() #--> "negative"
#@ see SentimentScore, IsPositive, IsNegative
def Sentiment()
Un moissonneur lit ces lignes, les titres de section et les exemples promis dans les tests. Chaque objet répond alors à Ask(), HowTo() et ExplainMethod() à partir d'eux, sans aucun modèle d'IA : la réponse est celle de la bibliothèque, et une méthode qui n'existe pas est refusée nommément.
Demandez à la bibliothèque comment elle nomme ce que vous voulez : HowTo compose l'appel à partir de la grammaire des noms et le dit, et une méthode inconnue est refusée nommément.
oDoc = StzSelfDocQ("stzList")
? oDoc.HowTo("remove duplicates")
? oDoc.HasMethod("DuplicatesRemoved")
? oDoc.ExplainMethod("NoSuchThing")Q([...]).RemoveDuplicates() -- composed by grammar (remove duplicates) 1 No method 'NoSuchThing' in stzList.
exécuté le 2026-10-15 13:37 dans la bibliothèque au commit 4a184e6f0 ; tiré de base/education/program/courses/elementary-introduction/chapters/13-the-gap-question.en.md(s'ouvre dans un nouvel onglet)
en construction La convention n'est encore pleinement employée que sur peu de méthodes : 106 lignes donnent d'autres mots pour une méthode, et le moissonneur ne lit pas encore les étiquettes d'exemple et de forme de réponse. La référence de ce site est générée à partir de ce qui existe.
Sources : les formes sont décrites dans la narration stz-functions-as-linguistic-expressions.md(s'ouvre dans un nouvel onglet) ; la langue des conditions est compilée par engine/src/expr.zig(s'ouvre dans un nouvel onglet) ; la convention des commentaires est fixée dans stz-information-tagging-strategy.md(s'ouvre dans un nouvel onglet). Nombres de méthodes lus dans la bibliothèque au commit 010743cce.

