<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Fonctionnel on Ocarina — précis</title>
    <link>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/series/fonctionnel/</link>
    <description>Recent content in Fonctionnel on Ocarina — précis</description>
    <generator>Hugo</generator>
    <language>fr-FR</language>
    <lastBuildDate>Thu, 28 May 2026 21:02:53 +0200</lastBuildDate>
    <atom:link href="https://mojo-molotov.github.io/from-ocarina-to-igor/fr/series/fonctionnel/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>03.01 — Effect, Thunk[T], Result[T]</title>
      <link>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/03-functional/01-effect-thunk-result/</link>
      <pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate>
      <guid>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/03-functional/01-effect-thunk-result/</guid>
      <description>&lt;h1 id=&#34;0301effect-thunkt-resultt&#34;&gt;03.01 — &lt;code&gt;Effect&lt;/code&gt;, &lt;code&gt;Thunk[T]&lt;/code&gt;, &lt;code&gt;Result[T]&lt;/code&gt;&lt;a class=&#34;anchor&#34; href=&#34;#0301effect-thunkt-resultt&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;Trois lignes de code dans &lt;code&gt;custom_types/&lt;/code&gt; + une dans &lt;code&gt;railway/&lt;/code&gt;. Tout le DSL repose dessus.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;h2 id=&#34;triplet&#34;&gt;Triplet&lt;a class=&#34;anchor&#34; href=&#34;#triplet&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;# src/ocarina/custom_types/effect.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;type&lt;/span&gt; Effect &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; Callable[[], &lt;span style=&#34;color:#ff79c6&#34;&gt;None&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;type&lt;/span&gt; Effects &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;tuple&lt;/span&gt;[Effect, &lt;span style=&#34;color:#ff79c6&#34;&gt;...&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;# src/ocarina/custom_types/thunk.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;type&lt;/span&gt; Thunk[T] &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; Callable[[], T]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;# src/ocarina/railway/result.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;type&lt;/span&gt; Result[T] &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; Ok[T] &lt;span style=&#34;color:#ff79c6&#34;&gt;|&lt;/span&gt; Fail&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Type&lt;/th&gt;&#xA;          &lt;th&gt;Sémantique FP&lt;/th&gt;&#xA;          &lt;th&gt;Définition&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;Effect&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Effet de bord (déféré)&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;() -&amp;gt; None&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;Thunk[T]&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;em&gt;Computation&lt;/em&gt; déférée avec valeur&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;() -&amp;gt; T&lt;/code&gt; (paresse + valeur)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;Result[T]&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;em&gt;Computation&lt;/em&gt; qui peut échouer&lt;/td&gt;&#xA;          &lt;td&gt;Union discriminée &lt;code&gt;Ok[T] | Fail&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;distinction-effect-vs-thunk&#34;&gt;Distinction Effect vs Thunk&lt;a class=&#34;anchor&#34; href=&#34;#distinction-effect-vs-thunk&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;log_msg: Effect &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;lambda&lt;/span&gt;: &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;)        &lt;span style=&#34;color:#6272a4&#34;&gt;# () -&amp;gt; None&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;get_42: Thunk[&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;int&lt;/span&gt;] &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;lambda&lt;/span&gt;: &lt;span style=&#34;color:#bd93f9&#34;&gt;42&lt;/span&gt;                 &lt;span style=&#34;color:#6272a4&#34;&gt;# () -&amp;gt; int&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fetch:  Thunk[Result[&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;int&lt;/span&gt;]] &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;lambda&lt;/span&gt;: Ok(&lt;span style=&#34;color:#bd93f9&#34;&gt;42&lt;/span&gt;)     &lt;span style=&#34;color:#6272a4&#34;&gt;# () -&amp;gt; Result[int]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Si la fonction &lt;em&gt;retourne&lt;/em&gt; quelque chose qu&amp;rsquo;on va consommer ailleurs → &lt;code&gt;Thunk[T]&lt;/code&gt;.&lt;br&gt;&#xA;Sinon → &lt;code&gt;Effect&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>03.02 — Closures comme primitive d&#39;inversion de contrôle</title>
      <link>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/03-functional/02-closures-ioc/</link>
      <pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate>
      <guid>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/03-functional/02-closures-ioc/</guid>
      <description>&lt;h1 id=&#34;0302closures-comme-primitive-dinversion-de-contrôle&#34;&gt;03.02 — Closures comme primitive d&amp;rsquo;inversion de contrôle&lt;a class=&#34;anchor&#34; href=&#34;#0302closures-comme-primitive-dinversion-de-contr%c3%b4le&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;Pas de DI container. Pas de framework d&amp;rsquo;injection. &lt;strong&gt;Une closure est la primitive d&amp;rsquo;injection&lt;/strong&gt; d&amp;rsquo;Ocarina.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;h2 id=&#34;lidée&#34;&gt;L&amp;rsquo;idée&lt;a class=&#34;anchor&#34; href=&#34;#lid%c3%a9e&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Une closure capture des valeurs dans son scope englobant. Quand on retourne une fonction depuis une autre fonction, les paramètres de l&amp;rsquo;extérieur sont &lt;strong&gt;disponibles à l&amp;rsquo;intérieur&lt;/strong&gt;, même après que la fonction extérieure ait rendu la main.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;make_handler&lt;/span&gt;(logger: ILogger) &lt;span style=&#34;color:#ff79c6&#34;&gt;-&amp;gt;&lt;/span&gt; Callable[[&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;str&lt;/span&gt;], FailureHandler]:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;make_failure_handler&lt;/span&gt;(msg: &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;str&lt;/span&gt;) &lt;span style=&#34;color:#ff79c6&#34;&gt;-&amp;gt;&lt;/span&gt; FailureHandler:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;actual_handler&lt;/span&gt;(exc: Exception) &lt;span style=&#34;color:#ff79c6&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;None&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            logger&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;error(msg, exc&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;exc)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; actual_handler&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; make_failure_handler&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;C&amp;rsquo;est aussi du &lt;em&gt;currying&lt;/em&gt; : &lt;code&gt;make_handler(logger)(msg)(exc)&lt;/code&gt;. Chaque appel capture une nouvelle couche d&amp;rsquo;environnement.&lt;/p&gt;</description>
    </item>
    <item>
      <title>03.03 — Évaluation paresseuse</title>
      <link>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/03-functional/03-lazy-evaluation/</link>
      <pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate>
      <guid>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/03-functional/03-lazy-evaluation/</guid>
      <description>&lt;h1 id=&#34;0303évaluation-paresseuse&#34;&gt;03.03 — Évaluation paresseuse&lt;a class=&#34;anchor&#34; href=&#34;#0303%c3%a9valuation-paresseuse&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;Dans Ocarina, &lt;strong&gt;rien n&amp;rsquo;est exécuté tant qu&amp;rsquo;on ne l&amp;rsquo;a pas explicitement déclenché&lt;/strong&gt;. C&amp;rsquo;est ce qui rend les scénarios composables comme des valeurs.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;h2 id=&#34;zzz&#34;&gt;Zzz&lt;a class=&#34;anchor&#34; href=&#34;#zzz&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Endroit&lt;/th&gt;&#xA;          &lt;th&gt;Forme&lt;/th&gt;&#xA;          &lt;th&gt;Déclencheur&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;ChainRunner[T]&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;Thunk[ActionChain[T]]&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;runner.run()&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;validate(...)&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;ValidationStartBlock&lt;/code&gt; / &lt;code&gt;ValidationAssertBlock&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;.execute()&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;match_page(...)&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;retourne un &lt;code&gt;ChainRunner[Any]&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;.run()&lt;/code&gt; (via la chaîne englobante)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;Watcher.callback&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;Callable[[Watcher], None]&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;_loop&lt;/code&gt; quand &lt;code&gt;start()&lt;/code&gt; est appelé&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;logger.set_prefix(thunk)&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;Thunk[str]&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;recalculé à chaque appel de log&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;Scenario.setup&lt;/code&gt; / &lt;code&gt;teardown&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;Effect&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;appelé par &lt;code&gt;TestExecutor&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;bootstrap(post_exec=...)&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;Callable[[TestCycleResults], None]&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;appelé après &lt;code&gt;run_plugins&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;CliBuilder(effects_factory=lambda ns: (...))&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;Effects&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;appelés après le parse argparse&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;test_scenario: TestScenario[Driver]&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;Callable[[Driver, ILogger], Scenario[Driver]]&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;appelé par &lt;code&gt;Test.spawn&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;code&gt;dispatch[mode]()&lt;/code&gt; dans &lt;code&gt;TestCycle.run_all&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;dict de &lt;code&gt;Thunk[bool]&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;appelé en lookup&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;chainrunner&#34;&gt;&lt;code&gt;ChainRunner&lt;/code&gt;&lt;a class=&#34;anchor&#34; href=&#34;#chainrunner&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;runner &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; drive_page(act1, act2, act3)        &lt;span style=&#34;color:#6272a4&#34;&gt;# ⚠️  rien exécuté&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;# … plus tard …&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;chain &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; runner&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;run()                         &lt;span style=&#34;color:#6272a4&#34;&gt;# ▶︎  exécution&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Capacité&lt;/th&gt;&#xA;          &lt;th&gt;Sans paresse&lt;/th&gt;&#xA;          &lt;th&gt;Avec paresse&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Stocker un scénario dans une variable&lt;/td&gt;&#xA;          &lt;td&gt;impossible (déjà exécuté)&lt;/td&gt;&#xA;          &lt;td&gt;trivial&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Multiplier &lt;code&gt;[runner] * 5&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;exécute 1 fois, on a 5 références au résultat&lt;/td&gt;&#xA;          &lt;td&gt;exécute 5 fois&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Passer un &lt;code&gt;runner&lt;/code&gt; à un autre &lt;code&gt;runner&lt;/code&gt; (composition)&lt;/td&gt;&#xA;          &lt;td&gt;impossible&lt;/td&gt;&#xA;          &lt;td&gt;trivial&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Réordonner les &lt;code&gt;act&lt;/code&gt; dans un test refactor&lt;/td&gt;&#xA;          &lt;td&gt;difficile&lt;/td&gt;&#xA;          &lt;td&gt;trivial&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;validateexecute&#34;&gt;&lt;code&gt;validate(...).execute()&lt;/code&gt;&lt;a class=&#34;anchor&#34; href=&#34;#validateexecute&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;v &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; validate(value, name&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;x&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;assert_that(is_positive)&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;assert_that(is_not_zero)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;# … on peut composer …&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;combined &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; chain_validations(v, other_validation)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;# … rien d&amp;#39;exécuté jusqu&amp;#39;ici …&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;combined&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;execute()&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;raise_if_invalid()        &lt;span style=&#34;color:#6272a4&#34;&gt;# ▶︎  exécution + agrégation&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;C&amp;rsquo;est ce qui permet à &lt;code&gt;_ValidationChain&lt;/code&gt; de &lt;strong&gt;collecter&lt;/strong&gt; toutes les erreurs avant d&amp;rsquo;en lever une seule (&lt;code&gt;AggregateInvariantViolationError&lt;/code&gt;).&lt;/p&gt;</description>
    </item>
    <item>
      <title>03.04 — reduce / fold dans Ocarina</title>
      <link>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/03-functional/04-fold-reduce/</link>
      <pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate>
      <guid>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/03-functional/04-fold-reduce/</guid>
      <description>&lt;h1 id=&#34;0304reduce-fold-dans-ocarina&#34;&gt;03.04 — &lt;code&gt;reduce&lt;/code&gt; / fold dans Ocarina&lt;a class=&#34;anchor&#34; href=&#34;#0304reduce-fold-dans-ocarina&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;Un seul &lt;code&gt;reduce&lt;/code&gt; dans toute la base de code. Mais c&amp;rsquo;est &lt;strong&gt;le&lt;/strong&gt; réducteur central : il fait fonctionner &lt;code&gt;chain_actions&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;h2 id=&#34;code&#34;&gt;Code&lt;a class=&#34;anchor&#34; href=&#34;#code&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;# src/ocarina/dsl/testing_with_railway/chain_actions.py&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;from&lt;/span&gt; functools &lt;span style=&#34;color:#ff79c6&#34;&gt;import&lt;/span&gt; reduce&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;chain_actions&lt;/span&gt;[T](&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    first: ActionSuccess[T], &lt;span style=&#34;color:#ff79c6&#34;&gt;*&lt;/span&gt;rest: ActionSuccess[T]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;) &lt;span style=&#34;color:#ff79c6&#34;&gt;-&amp;gt;&lt;/span&gt; ChainRunner[T]:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;thunk&lt;/span&gt;() &lt;span style=&#34;color:#ff79c6&#34;&gt;-&amp;gt;&lt;/span&gt; ActionChain[T]:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;reducer&lt;/span&gt;(chain: ActionChain[T], step: ActionSuccess[T]) &lt;span style=&#34;color:#ff79c6&#34;&gt;-&amp;gt;&lt;/span&gt; ActionChain[T]:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff79c6&#34;&gt;if&lt;/span&gt; chain&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;has_failed():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; chain&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                chain&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;then(step&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;__action__)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;failure(step&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;__failure_handler__)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;success(step&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;__success_handler__)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;execute()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; reduce(reducer, rest, first&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;execute())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; ChainRunner(thunk&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;thunk)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;anatomie&#34;&gt;Anatomie&lt;a class=&#34;anchor&#34; href=&#34;#anatomie&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Concept FP&lt;/th&gt;&#xA;          &lt;th&gt;Réalisation Python&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Type accumulator&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;ActionChain[T]&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Type element&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;ActionSuccess[T]&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Reducer&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;reducer(chain, step) -&amp;gt; ActionChain[T]&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Initial value&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;first.execute()&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Iterable&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;rest&lt;/code&gt; (le tuple de &lt;code&gt;*rest&lt;/code&gt;)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Short-circuit&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;if chain.has_failed(): return chain&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Result&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;ActionChain[T]&lt;/code&gt; (le dernier)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;flot-dexécution&#34;&gt;Flot d&amp;rsquo;exécution&lt;a class=&#34;anchor&#34; href=&#34;#flot-dex%c3%a9cution&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;initial = first.execute()                                          # → ActionChain(ok=True, result=Ok(...))&#xA;&#xA;step 1 : reducer(&amp;lt;initial&amp;gt;, act2) :&#xA;  chain.has_failed() = False&#xA;  chain.then(act2.__action__).failure(...).success(...).execute()&#xA;  → action lève → Fail&#xA;  → failure_handler(exc)  ❌ FIRE&#xA;  → ActionChain(ok=False, result=Fail(exc))&#xA;&#xA;step 2 : reducer(&amp;lt;failed&amp;gt;, act3) :&#xA;  chain.has_failed() = True&#xA;  return chain                                                     ⚠️  short-circuit&#xA;&#xA;result du reduce = &amp;lt;failed ActionChain&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;pourquoi-reduce&#34;&gt;Pourquoi &lt;code&gt;reduce&lt;/code&gt;&lt;a class=&#34;anchor&#34; href=&#34;#pourquoi-reduce&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;# Approche impérative (équivalente)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;thunk&lt;/span&gt;() &lt;span style=&#34;color:#ff79c6&#34;&gt;-&amp;gt;&lt;/span&gt; ActionChain[T]:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    chain &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; first&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;execute()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;for&lt;/span&gt; step &lt;span style=&#34;color:#ff79c6&#34;&gt;in&lt;/span&gt; rest:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;if&lt;/span&gt; chain&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;has_failed():&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff79c6&#34;&gt;break&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        chain &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; (&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            chain&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;then(step&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;__action__)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;failure(step&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;__failure_handler__)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;success(step&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;__success_handler__)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;execute()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; chain&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Reduce&lt;/th&gt;&#xA;          &lt;th&gt;Boucle impérative&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Une seule &lt;strong&gt;valeur&lt;/strong&gt; circule (le &lt;code&gt;chain&lt;/code&gt;)&lt;/td&gt;&#xA;          &lt;td&gt;Un état + une mutation&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Reducer = fonction pure (testable en isolation)&lt;/td&gt;&#xA;          &lt;td&gt;Logique inline&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Sémantique « &lt;em&gt;accumulateur&lt;/em&gt; » explicite&lt;/td&gt;&#xA;          &lt;td&gt;Logique implicite&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Standard fonctionnel&lt;/td&gt;&#xA;          &lt;td&gt;Standard impératif&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;C&amp;rsquo;est une &lt;strong&gt;expression d&amp;rsquo;intention&lt;/strong&gt; : on &lt;em&gt;replie&lt;/em&gt; une liste sur un accumulator. La sémantique est claire dès la première lecture. C&amp;rsquo;est ce qu&amp;rsquo;on appelle un &lt;strong&gt;catamorphisme&lt;/strong&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>03.05 — Programmation déclarative</title>
      <link>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/03-functional/05-declarative/</link>
      <pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate>
      <guid>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/03-functional/05-declarative/</guid>
      <description>&lt;h1 id=&#34;0305programmation-déclarative&#34;&gt;03.05 — Programmation déclarative&lt;a class=&#34;anchor&#34; href=&#34;#0305programmation-d%c3%a9clarative&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;Un scénario d&amp;rsquo;Ocarina &lt;strong&gt;décrit&lt;/strong&gt;, il n&amp;rsquo;exécute pas. C&amp;rsquo;est ce qui le rend factorisable, multipliable, et lisible.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;h2 id=&#34;démonstration&#34;&gt;Démonstration&lt;a class=&#34;anchor&#34; href=&#34;#d%c3%a9monstration&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; [&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    drive_page(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        act(on_homepage, open_then_verify_homepage)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;failure(just_log_error(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Failed to reach the homepage...&amp;#34;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;success(log_success_with_current_url_and_take_screenshot(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;On the homepage!&amp;#34;&lt;/span&gt;)),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        act(on_homepage, click_book_call_page_cta)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;failure(just_log_error(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Failed to click on the &amp;#39;Book a call&amp;#39; CTA...&amp;#34;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;success(just_log_success(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Clicked on the &amp;#39;Book a call&amp;#39; CTA!&amp;#34;&lt;/span&gt;)),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    drive_page(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        act(on_book_a_call_page, verify_book_call_page)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;failure(just_log_error(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Failed to verify the &amp;#39;Book a call&amp;#39; page...&amp;#34;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;success(log_success_with_current_url_and_take_screenshot(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;On the &amp;#39;Book a call&amp;#39; page!&amp;#34;&lt;/span&gt;)),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ce code &lt;strong&gt;n&amp;rsquo;exécute rien&lt;/strong&gt;. Il &lt;strong&gt;décrit&lt;/strong&gt; :&lt;/p&gt;</description>
    </item>
    <item>
      <title>03.06 — Generics PEP 695 dans Ocarina</title>
      <link>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/03-functional/06-pep-695-generics/</link>
      <pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate>
      <guid>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/03-functional/06-pep-695-generics/</guid>
      <description>&lt;h1 id=&#34;0306generics-pep-695-dans-ocarina&#34;&gt;03.06 — Generics PEP 695 dans Ocarina&lt;a class=&#34;anchor&#34; href=&#34;#0306generics-pep-695-dans-ocarina&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;Ocarina exploite à fond la syntaxe générique introduite par PEP 695 (Python 3.12+). C&amp;rsquo;est ce qui rend tout l&amp;rsquo;écosystème typé &lt;em&gt;sans que ce soit le foutoir&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;h2 id=&#34;trois-formes-de-pep-695&#34;&gt;Trois formes de PEP 695&lt;a class=&#34;anchor&#34; href=&#34;#trois-formes-de-pep-695&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;h3 id=&#34;1-classes-génériques&#34;&gt;1. Classes génériques&lt;a class=&#34;anchor&#34; href=&#34;#1-classes-g%c3%a9n%c3%a9riques&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@final&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;Ok&lt;/span&gt;[T](_BaseResult):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    value: T&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    error: &lt;span style=&#34;color:#ff79c6&#34;&gt;None&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;None&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;TestSuite&lt;/span&gt;[Driver]:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;Watcher&lt;/span&gt;[Driver]:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;ChainRunner&lt;/span&gt;[T]:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;ValidationStartBlock&lt;/span&gt;[T]:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;CliStore&lt;/span&gt;[TKeys: &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;str&lt;/span&gt;]:  &lt;span style=&#34;color:#6272a4&#34;&gt;# avec bound&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Avant PEP 695 :&lt;/p&gt;</description>
    </item>
    <item>
      <title>03.07 — Unions discriminées &#43; TypeGuard &#43; @final = unions « sealed »</title>
      <link>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/03-functional/07-discriminated-unions-typeguards/</link>
      <pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate>
      <guid>https://mojo-molotov.github.io/from-ocarina-to-igor/fr/03-functional/07-discriminated-unions-typeguards/</guid>
      <description>&lt;h1 id=&#34;0307unions-discriminées--typeguard--final--unions-sealed&#34;&gt;03.07 — Unions discriminées + TypeGuard + @final = unions « &lt;em&gt;sealed&lt;/em&gt; »&lt;a class=&#34;anchor&#34; href=&#34;#0307unions-discrimin%c3%a9es--typeguard--final--unions-sealed&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;Le combo qui rend &lt;code&gt;Result[T]&lt;/code&gt; et &lt;code&gt;TestResult&lt;/code&gt; à la fois &lt;strong&gt;typés&lt;/strong&gt; et &lt;strong&gt;utilisables sans cast&lt;/strong&gt;.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&lt;h2 id=&#34;union-discriminée&#34;&gt;Union discriminée&lt;a class=&#34;anchor&#34; href=&#34;#union-discrimin%c3%a9e&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@final&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@dataclass(frozen&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;Ok&lt;/span&gt;[T](_BaseResult):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    value: T&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    error: &lt;span style=&#34;color:#ff79c6&#34;&gt;None&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;None&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@final&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@dataclass(frozen&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;Fail&lt;/span&gt;(_BaseResult):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    error: Exception &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; field(default_factory&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;lambda&lt;/span&gt;: Exception(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Unknown error&amp;#34;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;type&lt;/span&gt; Result[T] &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; Ok[T] &lt;span style=&#34;color:#ff79c6&#34;&gt;|&lt;/span&gt; Fail&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#xA;&lt;li&gt;Deux constructeurs : &lt;code&gt;Ok[T]&lt;/code&gt; et &lt;code&gt;Fail&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Le &lt;em&gt;discriminant&lt;/em&gt; est l&amp;rsquo;&lt;em&gt;isinstance check&lt;/em&gt; (pas un champ comme &lt;code&gt;tag: Literal[&amp;quot;ok&amp;quot;, &amp;quot;fail&amp;quot;]&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;Les deux sont &lt;code&gt;@final&lt;/code&gt; : &lt;em&gt;aucun&lt;/em&gt; sous-type possible. → l&amp;rsquo;union est &lt;strong&gt;exhaustive&lt;/strong&gt;, donc « &lt;em&gt;sealed&lt;/em&gt; ».&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;narrowing-typeguard&#34;&gt;Narrowing, &lt;code&gt;TypeGuard&lt;/code&gt;&lt;a class=&#34;anchor&#34; href=&#34;#narrowing-typeguard&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;is_ok&lt;/span&gt;[T](result: Result[T]) &lt;span style=&#34;color:#ff79c6&#34;&gt;-&amp;gt;&lt;/span&gt; TypeGuard[Ok[T]]:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;isinstance&lt;/span&gt;(result, Ok)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;is_fail&lt;/span&gt;[T](result: Result[T]) &lt;span style=&#34;color:#ff79c6&#34;&gt;-&amp;gt;&lt;/span&gt; TypeGuard[Fail]:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;isinstance&lt;/span&gt;(result, Fail)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;handle_result&lt;/span&gt;(result: Result[&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;int&lt;/span&gt;]) &lt;span style=&#34;color:#ff79c6&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;str&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;if&lt;/span&gt; is_ok(result):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Got: &lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;{&lt;/span&gt;result&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;value&lt;span style=&#34;color:#f1fa8c&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&lt;/span&gt;          &lt;span style=&#34;color:#6272a4&#34;&gt;# mypy : result est Ok[int], donc .value existe&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;if&lt;/span&gt; is_fail(result):&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;f&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Error: &lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;{&lt;/span&gt;result&lt;span style=&#34;color:#ff79c6&#34;&gt;.&lt;/span&gt;error&lt;span style=&#34;color:#f1fa8c&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&lt;/span&gt;        &lt;span style=&#34;color:#6272a4&#34;&gt;# mypy : result est Fail, donc .error existe&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6272a4&#34;&gt;# mypy peut détecter que cette branche est inatteignable (exhaustivité)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;_baseresult&#34;&gt;&lt;code&gt;_BaseResult&lt;/code&gt;&lt;a class=&#34;anchor&#34; href=&#34;#_baseresult&#34; data-pagefind-ignore=&#34;all&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;_BaseResult&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    error: Exception &lt;span style=&#34;color:#ff79c6&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;None&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Cette base permet d&amp;rsquo;accéder à &lt;code&gt;result.error&lt;/code&gt; &lt;strong&gt;sans narrower&lt;/strong&gt; :&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
