Bonjour, Mélodium
Source: tutorial/01_hello_melodium See in Playground
Le plus petit programme Mélodium réellement utile. Il n’a pas de point d’entrée procédural : main est un graphe de traitements connectés entre eux, pas un corps de fonction qui s’exécute du début à la fin. startup() se déclenche une seule fois au démarrage du moteur, et chaque autre traitement réagit dès que les données dont il a besoin sont disponibles.
Exécution
cd tutorial/01_hello_melodium
melodium run Compo.toml --name "World" --times 3Le programme calcule une salutation unique avec une fonction pure et l’écrit dans hello.txt (la moitié Block), et génère ce même nom répété times fois sous forme de flux, en numérotant chaque occurrence (la moitié Stream). Les deux sont journalisées, ce qui permet de voir les deux styles d’exécution côte à côte lors d’une exécution.
Optionnel : ajoutez --api-report et un jeton d’API (MELODIUM_API_TOKEN) pour voir la trace complète de cette exécution sur Cadence.CI .
Fonctionnement
Cet exemple n’utilise aucun modèle : uniquement des traitements et fonctions sans état.
Flux de données
startup.trigger se déclenche une fois et se propage vers les deux moitiés du graphe : rien ici ne s’exécute “en premier” ou “en second”, les deux démarrent dès que le déclencheur arrive.
Le côté Block : une salutation, écrite une seule fois
|format et |map/|entry construisent la chaîne de salutation à partir du paramètre name, de façon purement fonctionnelle, sans aucune entrée/sortie. emit la transforme en Block<string>, et stream l’élargit en un Stream<string> d’un seul élément, pour que writeTextLocal puisse la consommer :
greeting: emit<string>(value=|format("Hello, {name}! Welcome to Mélodium.", |map([|entry("name", name)])))
asText: stream<string>()
write: writeTextLocal(path=output)
logWritten: logInfoMessage(label="hello", message="greeting written to file")
startup.trigger -> greeting.trigger,emit -> asText.block,stream -> write.text
write.finished -> logWritten.triggerstd/flow::stream est le moyen standard de transformer une valeur ponctuelle en un flux d’un seul élément, lorsqu’un traitement en aval attend un Stream plutôt qu’un Block.
Le côté Stream : le même nom, répété et numéroté
emit<u128>(value=times) fournit la longueur à generate, qui répète name ce nombre de fois sous forme de Stream<string>. Ce flux part directement vers logInfos, et séparément à travers count et toString avant d’être journalisé à nouveau :
howMany: emit<u128>(value=times)
names: generate<string>(data=name)
tally: count<string>()
tallyText: toString<u128>()
logNames: logInfos(label="greeting-stream")
logCount: logInfos(label="greeting-count")
startup.trigger -> howMany.trigger,emit -> names.length,stream -> tally.stream
names.stream -> logNames.messages
tally.count -> tallyText.value,into -> logCount.messagescount numérote les éléments à partir de 1 : une exécution avec --times 3 journalise donc 1, 2, 3.
Fonctions et traitements
|format, |map, |entry sont des fonctions pures : elles n’ont pas de port et sont appelées comme des valeurs, en ligne. emit, stream, generate, count sont des traitements : ils ont des ports et vivent dans le graphe. Les fonctions Mélodium prennent leurs arguments positionnels dans leur ordre de déclaration, par exemple |format(format_string, entries), ce qui ne correspond pas toujours à l’ordre alphabétique : en cas de doute, mieux vaut vérifier un exemple qui fonctionne ou valider avec melodium check.
Dépendances
[dependencies]
std = "0.10.3" # flux de base, journalisation, structures de données
fs = "0.10.3" # lecture/écriture de fichiers locaux