• [^] # Re: C'est bien dommage

    Posté par . En réponse au journal C++17 est sur les rails. Évalué à 3. Dernière modification le 18 mars 2016 à 17:34.

    Effectivement je ne connaissais pas la terminologie Lisp, une macro n'est rien d'autre qu'une fonction si je comprend bien ? ou sont-ce des fonctions d'une forme particulière ? De fait la syntaxe Lisp représente directement son AST, là où en OCaml on passe par des modules du compilateur pour le manipuler. Mais il me semble que c'est essentiellement pour des raisons de typage : le Lisp est du lambda-calcul faiblement typé, là où OCaml est du lambda-calcul fortement typé statiquement.

    Après le lambda-calcul est certes un outil essentiellement théorique (utile pour la théorie des langages), mais c'est juste du Lisp encore plus fruste : il n'y a qu'un seul opérateur, à savoir lambda, et on ne peut pas donner de nom aux termes (il n'y a pas d'opérateur d'affectation comme defun ou let). Par exemple ((lambda x) (x)) est la fonction identité ou encore ((lambda x) (y)) est la fonction constante égale à y. Ainsi si on applique le premier terme à n'importe quoi (n'importe quelle s-expression dont le seul opérateur de construction est lambda) alors il le renvoie, du genre (((lambda x) (x))((lambda z) (u v))) s'évalue en ((lambda z) (u v)).

    Sinon, on peut aussi coder du OCaml à la manière de Lisp en notation purement préfixée. Il suffit d'entourer un opérateur infixe par des parenthèses pour l'utiliser en préfixe comme dans ( + ) 1 2 qui vaut 3.

    Exemple sur la fonction factorielle en récursif terminal :

    (defun factorial (n &optional (acc 1))
     (if (<= n 1)
     acc
     (factorial (- n 1) (* acc n))))

    dans le même style en OCaml

    (* je commence par renommer les opérateurs infixes sous forme préfixe *)
    let le = ( <= ) and mul = ( * ) and minus = ( - )
    (* je code le test if-then-else en fonctionnel pure *)
    let iff b e1 e2 = if b then e1 else e2
    (* maintenant je code à la Lisp *)
    let rec factorial ?(acc=1) n =
    (* pour des raisons de typage on rajoute le mot clé rec et le paramètre optionnel est en premier *)
     (iff (le n 1)
     acc
     (factorial ~acc:(mul acc n) (minus n 1)))
    (* en OCaml plus idomiatique cela donnerait *)
    let factorial n =
     let rec loop acc n =
     match n with
     | 1 -> acc
     | _ -> loop (acc * n) (n - 1)
     in loop 1 n

    Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.