Derniers messages sur Zeste de Savoirhttps://zestedesavoir.com/forums/2018-04-18T10:53:15+02:00Les derniers messages parus sur le forum de Zeste de Savoir.(C++) Quelques questions sur la Métaprogrammation , message #1778732018-04-18T10:53:15+02:00El Poulpos/@El%20Poulposhttps://zestedesavoir.com/forums/sujet/10503/c-quelques-questions-sur-la-metaprogrammation/?page=1#p177873<p>@Freedom : Merci pour ta réponse <img alt=":)" src="/static/smileys/smile.png"> ,<br>
Je crois que la dernière édition de C++ Templates-The Complete Guide date de 2017 , j’ai un peu régardé il y a même les fameuses "fold expression" . J’irai jeter un coup d’oeil sur Modern C++ Design.</p>(C++) Quelques questions sur la Métaprogrammation , message #1778402018-04-17T20:29:53+02:00Freedom/@Freedomhttps://zestedesavoir.com/forums/sujet/10503/c-quelques-questions-sur-la-metaprogrammation/?page=1#p177840<p>C++ Templates - The Complete Guide commence à dater un peu je pense. Je l’avais trouvé bien quand je l’ai lu, il couvre les aspects techniques des templates et décrit les utilisations qu’on peut en faire. Cependant pour les aspects méta-programmations il reste assez succinct. Je le vois comme un ouvrage technique, pas un support d’apprentissage.</p>
<p>Pour l’utilisation des templates, j’avais apprécié Modern C++ Design et C++ Template Metaprogramming, mais ils commencent aussi tout les deux à dater. Je dirais que Modern C++ Design reste une bonne source aujourd’hui pour le fond, mais la forme des codes peut être revu avec les derniers outils du C++. Pour C++ Template Metaprogramming, même si le fond reste bon, je pense que les derniers éléments du langage changent la façon dont l’apprentissage peut être fait.</p>
<p>Edit: Je ne savais pas qu’une nouvelle édition avait été publiée.</p>(C++) Quelques questions sur la Métaprogrammation , message #1777172018-04-16T16:22:56+02:00El Poulpos/@El%20Poulposhttps://zestedesavoir.com/forums/sujet/10503/c-quelques-questions-sur-la-metaprogrammation/?page=1#p177717<p>@jo_link_noir : Merci beaucoup pour ta réponse <img alt=":)" src="/static/smileys/smile.png"> .<br>
Je regarde ça dès que je rentre chez moi .</p>(C++) Quelques questions sur la Métaprogrammation , message #1776922018-04-16T00:52:42+02:00jo_link_noir/@jo_link_noirhttps://zestedesavoir.com/forums/sujet/10503/c-quelques-questions-sur-la-metaprogrammation/?page=1#p177692<blockquote>
<p>je pensais juste que lorsque la fonction était déclarée inline et suffisamment petite ,le compilateur l’inliner.</p>
</blockquote>
<p>Il faut distinguer ce que le compilateur fait et ce que le code dit pouvoir faire. Le compilateur va probablement inliner et tout remplacer par des constantes, mais le code dit qu’il ne faut pas considérer la fonction comme retournant une expression constante ; d’où l’erreur.</p>
<blockquote>
<p>Après le livre c’était plus histoire de savoir comment utiliser les templates et les différents concepts qu’il y a derrière de manière optimale dans un projet.</p>
</blockquote>
<p>Je n’ai pas lu le livre "C++ Templates - The Complete Guide", mais les initiateurs de <a href="https://github.com/edouarda/brigand">Brigand</a> on fait un livre sur la méta-programmation (lien du livre sur le dépôt). C’est de la méta-programmation par type avec des classes et des spécialisations de template. C’est intéressant de comparer les sources avec d’autres bibliothèques connues:</p>
<ul>
<li><a href="https://github.com/brunocodutra/metal">Metal</a> qui se veut "pur", c’est à dire un code sans optimisation défigurant le code. Je crois que la seule concession se trouve sur fold. Toute les fonctions sont documentés.</li>
<li><a href="https://github.com/odinthenerd/mpl">Kvasir::mpl</a> qui utilise le principe de continuation. Il vaut mieux lire le blog de l’auteur pour bien comprendre. Il l’utilise aussi pour ces projets (exemple: une version de std::tuple).</li>
<li><a href="https://github.com/boostorg/hana">Boost.Hana</a> qui contrairement au 3 autres est de la méta-programmation par valeur: des fonctions constexpr. La doc contient quelques usage possible. Le blog de l’auteur est aussi très intéressant.</li>
</ul>(C++) Quelques questions sur la Métaprogrammation , message #1770002018-04-05T12:54:23+02:00El Poulpos/@El%20Poulposhttps://zestedesavoir.com/forums/sujet/10503/c-quelques-questions-sur-la-metaprogrammation/?page=1#p177000<p>@Berdes : merci de m’avoir répondu, pour la 1) je pensais juste que lorsque la fonction était déclarée inline et suffisamment petite ,le compilateur l’inliner.<br>
Merci encore pour ces précisions <img alt=":)" src="/static/smileys/smile.png"></p>
<p>EDIT : Après le livre c’était plus histoire de savoir comment utiliser les templates et les différents concepts qu’il y a derrière de manière optimale dans un projet .Dis moi si je me trompe mais je crois que cppreference présente de manière synthétique dans des exemple simples les différentes manière d’utiliser les template sans but précis , mais pas comment on pourrait les utiliser dans un projet.</p>(C++) Quelques questions sur la Métaprogrammation , message #1769842018-04-04T22:20:06+02:00Berdes/@Berdeshttps://zestedesavoir.com/forums/sujet/10503/c-quelques-questions-sur-la-metaprogrammation/?page=1#p176984<p>Salut,</p>
<p>1) <code>inline</code> ne fait probablement exactement ce à quoi tu penses. Il était prévu à la base pour indiquer au compilateur qu’il est <strong>préférable</strong> d’inliner la fonction, mais rien ne force le compilateur à le faire. La seul chose vraiment importante à propos d’<code>inline</code> c’est que ça t’autorise à déclarer la même fonction dans plusieurs unités de compilations (ce qui n’est habituellement pas autorisé) qui sont linké dans le même programme. Pour le compilateur, appeler une fonction <code>inline</code> et écrire directement le contenu de la fonction à la place de l’appel sont deux choses différentes et seront traités différemment. Puisque ta fonction n’est pas déclaré <code>constexpr</code>, le compilateur refuse simplement de l’exécuter à la compilation (même si c’est possible). De la même manière, le compilateur refusera d’exécuter une fonction membre qui n’est pas marqué <code>const</code> sur un objet <code>const</code>, même si cette fonction membre ne modifie pas l’objet. Petite note: <code>constexpr</code> implique <code>inline</code>.</p>
<p>2) Dans ton exemple <code>tab</code> n’est pas connu à la compilation (tout simplement parce que le tableau est alloué sur la stack) et ne peux donc pas être utilisé en tant que paramètre de template. C’est exactement la même chose que pour cet exemple:</p>
<div><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5
6</pre></div></td><td class="code"><div class="codehilite"><pre><span></span><span class="k">template</span> <span class="o"><</span><span class="k">const</span> <span class="kt">int</span> <span class="o">*</span><span class="n">pointeur</span><span class="o">></span> <span class="k">struct</span> <span class="n">Test</span><span class="p">{};</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="k">const</span> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span>
<span class="n">Test</span><span class="o"><&</span><span class="n">a</span><span class="o">></span> <span class="n">test</span><span class="p">;</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>Il toutefois possible d’utiliser un pointeur en temps qu’argument de template si l’adresse de ce pointeur est connu à la compilation, c’est-à-dire l’adresse d’une variable qui est déclaré directement dans un namespace:</p>
<div><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5
6
7</pre></div></td><td class="code"><div class="codehilite"><pre><span></span><span class="k">const</span> <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span>
<span class="k">template</span> <span class="o"><</span><span class="k">const</span> <span class="kt">int</span> <span class="o">*</span><span class="n">pointeur</span><span class="o">></span> <span class="k">struct</span> <span class="n">Test</span><span class="p">{};</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="n">Test</span><span class="o"><&</span><span class="n">a</span><span class="o">></span> <span class="n">test</span><span class="p">;</span> <span class="c1">// autorisé</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>J’ai cependant du mal à voir dans quel circonstance c’est utile…</p>
<p>3) Je ne pas te conseiller de livre sur le C++ puisque je n’en ai jamais lu. En revanche, lorsque tu rencontres un problème avec le langage, je peux te suggérer d’aller lire la documentation (par exemple sur <a href="http://en.cppreference.com/w/cpp/language">cppreference.com</a>. C’est relativement difficile à comprendre au début parce qu’il n’y a pas vraiment de distinction entre les concepts importants et les trucs quasiment jamais utilisés. En revanche, avec un peu d’habitude ça permet de bien comprendre tous les détails de certains concepts et donc de voir pourquoi quelque chose ne fonctionne pas.</p>(C++) Quelques questions sur la Métaprogrammation , message #1768322018-04-02T15:29:01+02:00El Poulpos/@El%20Poulposhttps://zestedesavoir.com/forums/sujet/10503/c-quelques-questions-sur-la-metaprogrammation/?page=1#p176832<p>Salut tout le monde,<br>
En ce moment je fais un peu de métaprogrammation en c++ depuis que j’ai regardé cette conférence (<a href="https://www.youtube.com/watch?v=Am2is2QCvxY">CppConf</a>) et cet article sur developpez . com (<a href="https://loulou.developpez.com/tutoriels/cpp/metaprog/">Article</a>)<br>
J’ai plusieurs questions très différentes à poser :</p>
<p>1) Je ne comprend pas pourquoi ce code ne fonctionne pas :</p>
<div><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10</pre></div></td><td class="code"><div class="codehilite"><pre><span></span><span class="kr">inline</span> <span class="kt">int</span> <span class="nf">doSomething</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">constexpr</span> <span class="kt">int</span> <span class="n">value</span><span class="o">=</span><span class="n">doSomething</span><span class="p">();</span> <span class="c1">// Erreur apparemment, doSomething ne peut pas être évalué à la compilation.</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>Je sais que je devrais utiliser constexpr au lieu de inline mais vu que la fonction doSomething est inline et peut être exécuté à la compilation je ne comprend pas pourquoi ça ne marche pas.</p>
<p>2)Pourquoi les pointeurs dans les paramètres template doivent poivent pointer sur un objet "linkable".</p>
<div><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5
6
7</pre></div></td><td class="code"><div class="codehilite"><pre><span></span><span class="k">template</span> <span class="o"><</span><span class="k">const</span> <span class="kt">int</span> <span class="o">*</span><span class="n">pointeur</span><span class="o">></span> <span class="k">struct</span> <span class="n">Test</span><span class="p">{}</span>
<span class="kt">int</span> <span class="n">main</span><span class="p">()</span>
<span class="p">{</span>
<span class="k">const</span> <span class="kt">int</span> <span class="n">tab</span><span class="p">[]</span><span class="o">=</span><span class="p">{</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">5</span><span class="p">};</span>
<span class="n">Test</span><span class="o"><</span><span class="n">tab</span><span class="o">></span> <span class="n">test</span> <span class="c1">// Erreur !!! tab n'a pas de linkage !</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</td></tr></table></div>
<p>3) je voudrais approfondir mes connaissance sur les Templates (je sais le sujet est vaste ) ,est ce que <strong>C++ Templates - The Complete Guide</strong> serait un livre que vous me conseilleriez , sinon quelles lectures me conseilleriez vous ? </p>
<p>Bon lundi de Pâques à tous <img alt=":)" src="/static/smileys/smile.png"></p>Polymorphisme sur des fonctions de toutes signatures, message #716352015-09-04T18:42:31+02:00Berdes/@Berdeshttps://zestedesavoir.com/forums/sujet/3943/polymorphisme-sur-des-fonctions-de-toutes-signatures/?page=1#p71635<p>Juste pour signaler que l'associativité de <code>-></code> donne <code>Int -> Int -> Int === Int -> (Int -> Int)</code> et non <code>(Int -> Int) -> Int</code>.</p>Polymorphisme sur des fonctions de toutes signatures, message #716332015-09-04T18:26:24+02:00felko/@felkohttps://zestedesavoir.com/forums/sujet/3943/polymorphisme-sur-des-fonctions-de-toutes-signatures/?page=1#p71633<p>Salut,</p>
<p>J'ai enfin réussi à faire marcher tout ça, c'est un peu long pour faire des bindings depuis Haskell mais ça marche bien <img alt=":p" src="/static/smileys/langue.png"></p>
<p>Ça m'a quand même l'air d'être plus propre que d'utiliser du "boilerplate" comme avec Dynamic.</p>
<p>Merci beaucoup Dinosaure et Dominus Carnufex</p>Polymorphisme sur des fonctions de toutes signatures, message #713972015-09-01T11:30:15+02:00felko/@felkohttps://zestedesavoir.com/forums/sujet/3943/polymorphisme-sur-des-fonctions-de-toutes-signatures/?page=1#p71397<p>Merci beaucoup Dinosaure,</p>
<p>J'essaye ça dès que possible</p>Polymorphisme sur des fonctions de toutes signatures, message #713582015-08-31T21:42:32+02:00Dinosaure/@Dinosaurehttps://zestedesavoir.com/forums/sujet/3943/polymorphisme-sur-des-fonctions-de-toutes-signatures/?page=1#p71358<blockquote>
<p>Le souci c'est que dans ta définition de TArrow et de VArrow, les fonctions n'acceptent qu'un seul argument de ce que j'ai compris (je ne fais pas d'OCaml, promis je m'y met un jour).</p>
</blockquote>
<p>Alors je me souviens plus de l'associativité de <code>-></code> mais une fonction tel que <code>int -> int -> int</code> peut être vu de cette manière <code>(int -> int) -> int</code> et donc <code>Arrow (Arrow (Int, Int), Int)</code> ce qui permet d'ailleurs de faire de la curryfication <img alt=";)" src="/static/smileys/clin.png"> !</p>Polymorphisme sur des fonctions de toutes signatures, message #713222015-08-31T16:32:54+02:00felko/@felkohttps://zestedesavoir.com/forums/sujet/3943/polymorphisme-sur-des-fonctions-de-toutes-signatures/?page=1#p71322<p>Merci Dinausaure pour tes explications.</p>
<blockquote>
<p>Comme tu le constates, tu dois avoir l'information du type de la valeur que tu manipules</p>
</blockquote>
<p>Oui, j'ai une fonction qui s'en charge.</p>
<blockquote>
<p><code>Arrow</code> est l'équivalent de l'abstraction en lambda calcul.</p>
</blockquote>
<p>Le souci c'est que dans ta définition de <code>TArrow</code> et de <code>VArrow</code>, les fonctions n'acceptent qu'un seul argument de ce que j'ai compris (je ne fais pas d'OCaml, promis je m'y met un jour).</p>
<blockquote>
<p>La limite à cela, c'est que tu ne pourras pas faire de liste de <code>Function a</code> dont le <code>a</code> est différent</p>
</blockquote>
<p>Du coup on peut pas les mettre dans l'environnement :/</p>
<p>Je vais approfondir mes recherches sur Data.Dynamic, c'est la seule piste que j'ai pour l'instant.</p>
<blockquote>
<p>Pour ta deuxième question, c'est non. Int, Float et String sont déjà des constructeurs de valeur, tu ne peux pas les redéfinir.</p>
</blockquote>
<p>Le fait est que ça marche (parce que Int, Float, etc… ne sont pas des constructeurs mais des types), ma question était surtout pour les conventions <img alt=":euh:" src="/static/smileys/unsure.gif"></p>Polymorphisme sur des fonctions de toutes signatures, message #712992015-08-31T12:47:27+02:00Dominus Carnufex/@Dominus%20Carnufexhttps://zestedesavoir.com/forums/sujet/3943/polymorphisme-sur-des-fonctions-de-toutes-signatures/?page=1#p71299<p>Une solution en première approximation serait de paramétrer ton type <code>Function</code>, ainsi que les types <code>Value</code> et <code>Environment</code> qui en dépendent. Tu aurais ainsi la définition suivante.</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3</pre></div></td><td class="code"><div class="codehilite"><pre><span class="kr">data</span> <span class="kt">Function</span> <span class="n">a</span>
<span class="ow">=</span> <span class="kt">UserFn</span> <span class="kt">Signature</span> <span class="kt">AST</span><span class="o">.</span><span class="kt">Expr</span>
<span class="o">|</span> <span class="kt">HaskellFn</span> <span class="n">a</span>
</pre></div>
</td></tr></table>
<p>Je viens de faire l'essai, il n'y a aucune difficulté à faire <code>HaskellFn (+)</code> et <code>HaskellFn (&&)</code>. La limite à cela, c'est que tu ne pourras pas faire de liste de <code>Function a</code> dont le <code>a</code> est différent. Par exemple <code>[HaskellFn (+), HaskellFn (&&)]</code> ne passera pas.</p>
<p>Maintenant, si tu as besoin de quelque chose de plus solide, ça va commencer à devenir compliqué.</p>Polymorphisme sur des fonctions de toutes signatures, message #712982015-08-31T12:38:36+02:00Dinosaure/@Dinosaurehttps://zestedesavoir.com/forums/sujet/3943/polymorphisme-sur-des-fonctions-de-toutes-signatures/?page=1#p71298<p>La question du polymorphisme dans la conception d'un langage informatique est une vraie question qui a plusieurs solutions selon les objectifs du créateurs.</p>
<p>En OCaml, nous avons un polymorphisme uniforme ou polymorphisme paramétrique dans le sens où les opérations de la fonction polymorphe sur les valeurs seront <strong>toujours</strong> les mêmes quelque soit le type. Par exemple, <code>let rec map f = function [] -> [] | x :: r -> f x :: map f r</code> donne le type <code>('a -> 'b) -> 'a list -> 'b list</code>. Que la liste soit <code>int list</code> ou <code>float list</code>, le traitement restera le même - à savoir l'application de la fonction <code>f</code> sur tout les éléments de la liste.</p>
<p>Au contraire du polymorphisme ad-hoc, nous avons une fonction générique (note bien la différence entre générique et polymorphe) qui accepte des valeurs de tous types mais dont les opérations diffèrent selon le type des valeurs. C'est le cas en C++ par exemple avec une différence notable a OCaml qui est la surcharge des opérateurs comme <code>+</code> qui peut autant s'appliquer à des <code>int</code> qu'à des <code>float</code> ou à d'autres objets plus complexes pour peu qu'on est défini le traitement.</p>
<p>Dans un polymorphisme ad-hoc, une fonction générique à donc plusieurs algorithmes selon le type des valeurs. C'est le cas par exemple du <code>print</code> en Python qui, selon le type, va afficher d'une certaines manières la valeur (un dictionnaire n'apparait pas de la même manière qu'un entier avec cette fonction). Sur la question que tu te poses, tu pars déjà sur un polymorphisme ad-hoc: avoir des fonctions du même nom mais avec une signature différente - et par extension un traitement différent selon le type.</p>
<p>Maintenant, la vraie question que tu te poses, c'est d'implémenter un mécanisme de <code>dispatch</code> lors de l'application de la fonction pour savoir qu'elle algorithme il faut utiliser - ce choix dépendra, comme tu le sais, du type de ton argument. Par exemple, pour l'implémentation d'un <code>print</code> tel que celui de Python, nous pourrions avoir ceci:</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">let</span> <span class="n">print</span> <span class="o">=</span> <span class="k">function</span>
<span class="o">|</span> <span class="nc">Int</span> <span class="n">v</span> <span class="o">-></span> <span class="n">print_int</span> <span class="n">v</span>
<span class="o">|</span> <span class="nc">Float</span> <span class="n">v</span> <span class="o">-></span> <span class="n">print_float</span> <span class="n">v</span>
<span class="o">|</span> <span class="nc">String</span> <span class="n">v</span> <span class="o">-></span> <span class="n">print_string</span> <span class="n">v</span>
<span class="o">|</span> <span class="o">_</span> <span class="o">-></span> <span class="k">raise</span> <span class="nc">Not_implemented</span>
</pre></div>
</td></tr></table>
<p>On a bien un mécanisme de <code>dispatch</code> selon le type de l'argument. Bien entendu, l'extensibilité de la fonction <code>print</code> à d'autres types (comme ceux créé par l'utilisateur) n'est pas possible, on peut alors imaginer ce code modifié tiré de <a href="http://gallium.inria.fr/%7Exleroy/publi/dynamics-in-ML.pdf">ce document</a>:</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">type</span> <span class="n">type_id</span> <span class="o">=</span> <span class="kt">string</span>
<span class="k">type</span> <span class="k">val</span> <span class="o">=</span> <span class="nc">VInt</span> <span class="k">of</span> <span class="kt">int</span> <span class="o">|</span> <span class="nc">VFloat</span> <span class="k">of</span> <span class="kt">float</span> <span class="o">|</span> <span class="nc">VObject</span> <span class="k">of</span> <span class="k">value</span>
<span class="k">type</span> <span class="n">ty</span> <span class="o">=</span> <span class="nc">TInt</span> <span class="o">|</span> <span class="nc">TFloat</span> <span class="o">|</span> <span class="nc">TObject</span> <span class="k">of</span> <span class="n">type_id</span>
<span class="k">let</span> <span class="n">printers</span> <span class="o">=</span>
<span class="n">ref</span> <span class="o">([(</span><span class="nc">TInt</span><span class="o">,</span> <span class="o">(</span><span class="k">function</span> <span class="nc">VInt</span> <span class="n">i</span> <span class="o">-></span> <span class="n">print_int</span> <span class="n">i</span> <span class="o">|</span> <span class="o">_</span> <span class="o">-></span> <span class="k">assert</span> <span class="bp">false</span><span class="o">));</span>
<span class="o">(</span><span class="nc">TFloat</span><span class="o">,</span> <span class="o">(</span><span class="k">function</span> <span class="nc">VFloat</span> <span class="n">f</span> <span class="o">-></span> <span class="n">print_float</span> <span class="n">f</span> <span class="o">|</span> <span class="o">_</span> <span class="o">-></span> <span class="k">assert</span> <span class="bp">false</span><span class="o">))]</span>
<span class="o">:</span> <span class="o">(</span><span class="n">ty</span> <span class="o">*</span> <span class="o">(</span><span class="k">value</span> <span class="o">-></span> <span class="kt">unit</span><span class="o">))</span> <span class="kt">list</span><span class="o">)</span>
<span class="k">let</span> <span class="k">rec</span> <span class="n">print</span> <span class="o">(</span><span class="n">ty</span><span class="o">,</span> <span class="k">value</span><span class="o">)</span> <span class="o">=</span>
<span class="k">try</span> <span class="k">let</span> <span class="o">(_,</span> <span class="n">printer</span><span class="o">)</span> <span class="o">=</span> <span class="nn">List</span><span class="p">.</span><span class="n">find</span> <span class="o">((=)</span> <span class="n">ty</span><span class="o">)</span> <span class="o">!</span><span class="n">printers</span> <span class="k">in</span>
<span class="n">printer</span> <span class="k">value</span>
<span class="k">with</span> <span class="nc">Not_found</span> <span class="o">-></span> <span class="k">raise</span> <span class="nc">Not_implemented</span>
</pre></div>
</td></tr></table>
<p>Comme tu le constates, tu <strong>dois</strong> avoir l'information du type de la valeur que tu manipules - ce dernier va pouvoir faire un <code>dispatch</code> recherchant selon le type, le bon <code>printer</code> dans liste. Ici, c'est une liste associative <code>ty * printer</code> mais on peut imaginer une <code>Map</code> avec pour clé <code>ty</code> pour être plus efficient dans la recherche.</p>
<p>On peut rendre ce genre d'algorithme plus général pour l'application d'une fonction. Puisque tu fais un LISP, ça reste de la programmation fonctionnel et on peut décrire les types d'une fonction à l'aide d'un <code>TArrow</code>:</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19</pre></div></td><td class="code"><div class="codehilite"><pre><span class="k">type</span> <span class="n">ty</span> <span class="o">=</span> <span class="nc">TTop</span> <span class="o">|</span> <span class="nc">TInt</span> <span class="o">|</span> <span class="nc">TFloat</span> <span class="o">|</span> <span class="nc">TArrow</span> <span class="k">of</span> <span class="o">(</span><span class="n">ty</span> <span class="o">*</span> <span class="n">ty</span><span class="o">)</span>
<span class="k">type</span> <span class="k">value</span> <span class="o">=</span> <span class="nc">VTop</span> <span class="o">|</span> <span class="o">...</span> <span class="o">|</span> <span class="nc">VArrow</span> <span class="k">of</span> <span class="o">(</span><span class="k">value</span> <span class="o">-></span> <span class="k">value</span><span class="o">)</span>
<span class="k">let</span> <span class="k">rec</span> <span class="n">ty_eq</span> <span class="n">ty1</span> <span class="n">ty2</span> <span class="o">=</span> <span class="k">match</span> <span class="n">ty1</span><span class="o">,</span> <span class="n">ty2</span> <span class="k">with</span>
<span class="o">|</span> <span class="nc">TTop</span><span class="o">,</span> <span class="o">_</span> <span class="o">|</span> <span class="o">_,</span> <span class="nc">TTop</span> <span class="o">-></span> <span class="bp">true</span>
<span class="o">|</span> <span class="o">...</span>
<span class="o">|</span> <span class="nc">TArrow</span> <span class="o">(</span><span class="n">tya</span><span class="o">,</span> <span class="n">tyb</span><span class="o">),</span> <span class="nc">TArrow</span> <span class="o">(</span><span class="n">tya'</span><span class="o">,</span> <span class="n">tyb'</span><span class="o">)</span> <span class="o">-></span>
<span class="n">ty_eq</span> <span class="n">tya</span> <span class="n">tya'</span> <span class="o">&&</span> <span class="n">ty_eq</span> <span class="n">tyb</span> <span class="n">tyb'</span>
<span class="k">let</span> <span class="k">rec</span> <span class="n">eval</span> <span class="o">?(</span><span class="n">expected_ty</span> <span class="o">=</span> <span class="nc">TTop</span><span class="o">)</span> <span class="n">environment</span> <span class="o">=</span>
<span class="o">|</span> <span class="nc">Variable</span> <span class="n">name</span> <span class="o">-></span>
<span class="nn">Env</span><span class="p">.</span><span class="n">find</span> <span class="n">name</span> <span class="n">environment</span> <span class="o">:</span> <span class="o">(</span><span class="n">ty</span> <span class="o">*</span> <span class="k">value</span><span class="o">)</span> <span class="kt">list</span>
<span class="o">|></span> <span class="nn">List</span><span class="p">.</span><span class="n">find</span> <span class="o">(</span><span class="n">ty_eq</span> <span class="n">expected_ty</span><span class="o">)</span>
<span class="o">|</span> <span class="nc">Application</span> <span class="o">(</span><span class="n">f</span><span class="o">,</span> <span class="n">v</span><span class="o">)</span> <span class="o">-></span>
<span class="k">let</span> <span class="o">(</span><span class="n">ty_v</span><span class="o">,</span> <span class="n">v</span><span class="o">)</span> <span class="o">=</span> <span class="n">eval</span> <span class="n">environment</span> <span class="n">v</span> <span class="k">in</span>
<span class="k">let</span> <span class="o">(</span><span class="n">ty_f</span><span class="o">,</span> <span class="n">f</span><span class="o">)</span> <span class="o">=</span> <span class="n">eval</span> <span class="o">~</span><span class="n">expected_ty</span><span class="o">:</span><span class="n">ty_v</span> <span class="n">environment</span> <span class="n">f</span> <span class="k">in</span>
<span class="k">match</span> <span class="n">f</span> <span class="k">with</span>
<span class="o">|</span> <span class="nc">VArrow</span> <span class="n">f</span> <span class="o">-></span> <span class="n">f</span> <span class="n">v</span>
<span class="o">|</span> <span class="o">_</span> <span class="o">-></span> <span class="k">raise</span> <span class="nc">Is_not_function</span>
</pre></div>
</td></tr></table>
<p>Alors plusieurs choses, j'ai enlevé <code>Object</code> pour simplifié le code (ce dernier permettait à ce que l'utilisateur puisse définir ses propres types mais il faudrait implémenter une fonction <code>unlink</code> qui réduirait l'<code>Object</code> à ce qu'il peut être structurellement - et à ce moment, on parle déjà de <em>duck typing</em> comme en Python). Le type <code>Top</code> est la borne supérieur à tout les types (comme le type <code>Object</code> en Java) - en général, on y associe aucuns traitements, et si on est face à une valeur <code>Top</code>, c'est qu'on essaye d'appliquer une fonction à une valeur où nous n'aurions pas trouver une signature/un algorithme correspondant et c'est notamment pour éviter que l'évaluation s'arrête face à ce genre d'erreur. Enfin, <code>Arrow</code> est l'équivalent de l'abstraction en lambda calcul.</p>
<p>Cela reste une implémentation imparfaite mais qui donne une idée général de ce que peut être le polymorphisme ad-hoc. Cependant, il y a plusieurs points à expliquer ici qui ne sont pas forcément facile à comprendre sans recul.</p>
<p>Le premier point, c'est l'obligation de se <em>coltiner</em> le type de nos valeurs tout le long de l'évaluation (et c'est le cas en Python) qui fait qu'à un niveau plus bas, on parle de valeur boxé. Bien entendu, on trouve toujours d'autres moyens comme en C++ avec le <em>name-mangling</em> mais ce qu'il faut dénoter, c'est qu'à vouloir du polymorphisme ad-hoc, on complexifie fortement le <em>runtime</em> pour quelque chose qui, AMHA, reste de l'utilisation occasionnelle.</p>
<p>Ensuite, c'est la gestion des erreurs. Il est difficile de gérer de manière exhaustive toutes les erreurs qui peuvent provenir du polymorphisme ad-hoc (je me souviens des messages d'erreurs de link avec GCC avec l'utilisation de template parce qu'il ne trouver pas tel ou tel méthode dans ma classe). L’inexistence d'une signature d'une fonction peut donc poser des soucis lors de l'évaluation et c'est pour cette raison que j'ai créé le type <code>Top</code> qui rend cette erreur silencieuse d'une certaines manières mais doit on considérer que cette erreur doit arrêter tout le programme ou non ? C'est encore une question ouverte.</p>
<p>La finalité, c'est qu'au travers de tout ces inconvénients, j'ai une préférence pour un système de type statique comme celui d'OCaml ou Haskell mais où l'implémentation est certainement un peu plus complexe au niveau du compilateur mais où l'<em>overhead</em> est inexistant au niveau du <em>runtime</em>. C'est pour cette raison que j'ai fait une présentation au début du polymorphisme paramétrique comme une autre solution.</p>Polymorphisme sur des fonctions de toutes signatures, message #712882015-08-31T12:20:24+02:00felko/@felkohttps://zestedesavoir.com/forums/sujet/3943/polymorphisme-sur-des-fonctions-de-toutes-signatures/?page=1#p71288<blockquote>
<p>Un exemple précis, avec un bout de code, pourrait aider.</p>
</blockquote>
<p>Voici les principaux types que j'utilise:</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre> 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</pre></div></td><td class="code"><div class="codehilite"><pre><span class="kr">type</span> <span class="kt">Name</span> <span class="ow">=</span> <span class="kt">String</span>
<span class="kr">type</span> <span class="kt">Environment</span> <span class="ow">=</span> <span class="p">[(</span><span class="kt">Name</span><span class="p">,</span> <span class="kt">Value</span><span class="p">)]</span>
<span class="kr">data</span> <span class="kt">Value</span>
<span class="ow">=</span> <span class="kt">IntegerV</span> <span class="kt">Integer</span>
<span class="o">|</span> <span class="kt">DoubleV</span> <span class="kt">Double</span>
<span class="o">|</span> <span class="kt">StringV</span> <span class="kt">String</span>
<span class="o">|</span> <span class="kt">ListV</span> <span class="p">[</span><span class="kt">Value</span><span class="p">]</span>
<span class="o">|</span> <span class="kt">TupleV</span> <span class="p">[</span><span class="kt">Value</span><span class="p">]</span>
<span class="o">|</span> <span class="kt">FunctionV</span> <span class="kt">Function</span>
<span class="o">|</span> <span class="kt">TypeV</span> <span class="kt">Type</span>
<span class="kr">data</span> <span class="kt">Parameter</span> <span class="ow">=</span> <span class="kt">Parameter</span> <span class="kt">Name</span> <span class="kt">Type</span>
<span class="kr">data</span> <span class="kt">Signature</span> <span class="ow">=</span> <span class="kt">Signature</span> <span class="p">[</span><span class="kt">Parameter</span><span class="p">]</span> <span class="kt">Type</span>
<span class="kr">data</span> <span class="kt">Function</span>
<span class="ow">=</span> <span class="kt">UserFn</span> <span class="kt">Signature</span> <span class="kt">AST</span><span class="o">.</span><span class="kt">Expr</span>
<span class="o">|</span> <span class="kt">HaskellFn</span> <span class="o"><</span><span class="kr">type</span><span class="o">></span>
<span class="kr">data</span> <span class="kt">Type</span>
<span class="ow">=</span> <span class="kt">IntegerT</span>
<span class="o">|</span> <span class="kt">DoubleT</span>
<span class="o">|</span> <span class="kt">StringT</span>
<span class="o">|</span> <span class="kt">ListT</span> <span class="kt">Type</span>
<span class="o">|</span> <span class="kt">TupleT</span> <span class="p">[</span><span class="kt">Type</span><span class="p">]</span>
<span class="o">|</span> <span class="kt">FunctionT</span> <span class="kt">Signature</span>
<span class="o">|</span> <span class="kt">TypeT</span>
<span class="kr">deriving</span> <span class="kt">Eq</span>
</pre></div>
</td></tr></table>
<p>Je voudrais un type tel que je puisse écrire par exemple "HaskellFn (+)" mais aussi "HaskellFn (div)", sachant que (+) et (div) sont de type différent.</p>Polymorphisme sur des fonctions de toutes signatures, message #712822015-08-31T12:02:52+02:00Dominus Carnufex/@Dominus%20Carnufexhttps://zestedesavoir.com/forums/sujet/3943/polymorphisme-sur-des-fonctions-de-toutes-signatures/?page=1#p71282<p>Je ne comprends pas ce que tu cherches à faire, donc je vais avoir du mal à t'aider sur ta première question. Un exemple précis, avec un bout de code, pourrait aider.</p>
<p>Pour ta deuxième question, c'est non. <code>Int</code>, <code>Float</code> et <code>String</code> sont déjà des constructeurs de valeur, tu ne peux pas les redéfinir.</p>Polymorphisme sur des fonctions de toutes signatures, message #712662015-08-31T10:36:52+02:00felko/@felkohttps://zestedesavoir.com/forums/sujet/3943/polymorphisme-sur-des-fonctions-de-toutes-signatures/?page=1#p71266<p>Salut,</p>
<p>Je code en ce moment un langage LISP-like pour tester Parsec. Cependant, je bloque pour l'évaluation des appels de fonction. Actuellement, je fais un <code>lookup</code> sur mon environnement pour récupérer ma fonction grâce à son nom. Le souci c'est que le type des fonctions varie selon leur signature, donc je peux pas stocker dans une structure de donnée plusieurs fonctions tant que leurs signatures sont différentes. Comment pourrai-je stocker ces fonctions dans mon environnement, ou quelle autre "architecture" mon programme pourrait prendre pour pouvoir importer des fonctions de Haskell dans mon langage ?</p>
<p>On m'a conseillé d'utiliser Data.Dynamic mais je n'ai pas trop compris comment l'utiliser malgré des recherches.</p>
<p>PS: (Autre question qui n'a rien à voir) Est-ce correct d'utiliser le même nom pour un constructeur et son argument ? ex:</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1</pre></div></td><td class="code"><div class="codehilite"><pre>data Value = Int Int | Float Float | String String
</pre></div>
</td></tr></table>Créer un module Python à l'exécution, message #525452015-04-20T10:11:47+02:00Kje/@Kjehttps://zestedesavoir.com/forums/sujet/2916/creer-un-module-python-a-lexecution/?page=1#p52545<p>Avec ec genre de chose tu peux faire des trucs marrants comme <a href="https://github.com/xando/github_import">de l'import directement depuis github</a></p>Créer un module Python à l'exécution, message #525442015-04-20T10:05:40+02:00felko/@felkohttps://zestedesavoir.com/forums/sujet/2916/creer-un-module-python-a-lexecution/?page=1#p52544<p>Bénis sois tu, Kje, le lien que tu m'as donné fait exactement ce que je voulais faire !</p>Créer un module Python à l'exécution, message #525392015-04-20T09:50:21+02:00Kje/@Kjehttps://zestedesavoir.com/forums/sujet/2916/creer-un-module-python-a-lexecution/?page=1#p52539<p>Dans ce cas là tu peux utiliser le fonction <code>__import__</code> directement ou <code>import_module </code> dans <code>importlib</code>.</p>
<p>Sinon va <a href="http://chimera.labs.oreilly.com/books/1230000000393/ch10.html">sur cette page</a> il y a l'exemple "Loading Modules from a Remote Machine Using Import Hooks" qui correspond peu ou prou a ce que tu veux faire avec les explications.</p>Créer un module Python à l'exécution, message #525362015-04-20T09:44:01+02:00felko/@felkohttps://zestedesavoir.com/forums/sujet/2916/creer-un-module-python-a-lexecution/?page=1#p52536<p>Ce qui m'intéresse serait de charger un module "virtuel" qui ne serait chargé que sur la RAM, le code source du fichier est stocké en ligne. Le but est de pouvoir importer ce module virtuel depuis n'importe quelle machine dotée d'une connexion internet comme n'importe quel autre module. Sinon je souhaite vraiment faire ça à partir de string, parce que je ne connais pas les autres possibilités qui s'offrent à moi.</p>
<blockquote>
<p>Et est ce que le module à importer est dans le path python ?</p>
</blockquote>
<p>Tu te poses cette question à cause du <code>import alea</code> ? Si oui, je peux faire ça parce que j'ai ajouté à <code>sys.modules</code> mon module. Ça revient à redéfinir le path python en effet.</p>
<p>En fait, le truc que je recherche, c'est une fonction qui puisse à partir de code source Python me renvoyer le module correspondant à ces sources. Quelque chose du genre:</p>
<table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5
6
7
8
9</pre></div></td><td class="code"><div class="codehilite"><pre><span class="n">alea</span> <span class="o">=</span> <span class="n">code_source_vers_module_fonction_magique</span><span class="p">(</span><span class="s">"""</span><span class="se">\</span>
<span class="s">import random, string</span>
<span class="s">def random_string(length):</span>
<span class="s"> res = ''</span>
<span class="s"> for _ in range(length):</span>
<span class="s"> res += random.choice(string.ascii_lowercase)</span>
<span class="s"> return res</span>
<span class="s">"""</span><span class="p">)</span>
</pre></div>
</td></tr></table>