peut être si bon fonctionnement plutôt que d'une forme particulière
-
19-09-2019 - |
Question
J'ai finalement commencé l'apprentissage des langues fonctionnelles (Lisp) et il établit une distinction explicite entre les fonctions et les formes spéciales telles que le contrôle de flux, par exemple, si.
Y at-il une raison fondamentale / théorique pourquoi les formes spéciales sont distinctes des fonctions? toutes les langues ne fournissent if
fonctionnelle?
Merci
La solution
Avec la distinction évaluation stricte est requise, les langues avec évaluation paresseuse (à savoir Haskell) si et al. peut être des fonctions.
Évaluation Désireuse:. Les arguments de la fonction sont évalués avant appelant la fonction, et seuls les résultats sont transmis à la fonction
Évaluation Lazy:. Les arguments de fonction évalués si et seulement si elles sont accessibles
Autres conseils
Si if
était une fonction normale, puis ses deux arguments -le forment alors et sous forme d'autre -would à la fois être évalués avant appelant la fonction if
, parce que c'est règle de href="http://www.lispworks.com/documentation/HyperSpec/Body/03_ababc.htm" : évaluer tous les arguments pour produire des valeurs, alors prévoir que la séquence de valeurs en tant que arguments de la fonction désignée par le premier symbole dans la liste.
Au lieu de cela, avec Dans les langues comme Emacs Lisp et Common Lisp, des formulaires spéciaux sont intégrés dans des constructions de langage. Ils ont des règles d'évaluation que les appels de fonction normale. Pour les appels de fonction normales, tous les arguments sont évalués. Donc, vous ne pouvez pas écrire un IF en fonction normale - la condition détermine la clause obtient évaluée. Aussi, vous pouvez généralement pas écrire vos propres formes spéciales -. En Common Lisp il n'y a pas construction de langage pour définir une forme particulière (bien que les mises en œuvre individuelles doivent avoir mis en place ceux qui existent déjà en quelque sorte Cela conduit à des macros avec des macros vous pouvez écrire une transformation syntaxique. qui transforme une expression dans un autre. pour pouvoir écrire SI comme une macro, vous devez avoir une autre forme conditionnelle, que vous pouvez utiliser pour le code transformé. Lisp fournit conditionals comme des constructions de base. Supposons que COND est une construction de base , vous pouvez alors étendre IF dans une utilisation de COND. MY-IF comme une macro en Common Lisp: obtient élargi dans if
ce que vous voulez faire est d'évaluer exactement l'un des autres forment alors et forme , pas les deux. Afin de supprimer l'évaluation de l'un ou l'autre, vous avez besoin soit une macro ou
(defmacro my-if (condition true-clause false-clause)
`(cond (,condition ,true-clause)
(t ,false-clause)))
(my-if (foo-p) 'one 'two)
(cond ((foo-p) 'one)
(t 'two))
Pour être complet: il n'y a pas des formes particulières dans le Pico langage par exemple, et est if
une fonction primitive Pico est alors inspiré par le schéma et a évaluation stricte par défaut.
Dans le schéma, vous pouvez écrire
(define (true t f)
(t))
(define (false t f)
(f))
(define (function_if c t e)
(c t e))
et
(function_if true (lambda () 'true) (lambda () 'false))
==> true
Ce qui rend cette gérable à Pico est que vous pouvez définir paramètres fonctionnels qui prennent des arguments fonctionnels qui sont « automatiquement » retardé. Cela signifie que vous ne devez pas faire l'emballage à l'intérieur vous lambdas. Pico a donc évaluation stricte mais avec évaluation paresseuse à la demande, sans passer par la nécessité de formes spéciales.
Ainsi, dans la syntaxe des paramètres fonctionnels avec le schéma, vous pouvez encoder booléens comme:
(define (true (t) (f))
(t))
(define (false (t) (f))
(f))
Ensuite la fonction devient si:
(define (function_if c (t) (e))
(c (t) (e)))
et
(function_if true 'true 'false)
==> true
Comme autre exemple, la définition de la fonction and
est (define (and p (q)) (p (q) false))
.
De même, vous pouvez définir or
, not
, while
, for
, ... comme des fonctions, en utilisant le codage ci-dessus de booléens.
Réponse courte:. Non
Réponse longue (er): (si ...) exige que vous contrôlez l'ordre d'évaluation des arguments. Lisp, étant une langue avide ne peut pas le faire en fonction.
Solution: faire dans une macro:
(defmacro _if (cnd true false)
(let ( (gcond (gensym))
(gresp (gensym)))
`(let ( (,gcond ,cnd) ;`#quotes
(,gresp nil))
(and ,gcond (setf ,gresp (multiple-value-list ,true)))
(and (not ,gcond) (setf ,gresp (multiple-value-list ,false)))
(values-list ,gresp))))
Par exemple:
[dsm@localhost:~]$ clisp -q
[1]> (defmacro _if (cnd true false)
(let ( (gcond (gensym))
(gresp (gensym)))
`(let ( (,gcond ,cnd) ;`#quotes
(,gresp nil))
(and ,gcond (setf ,gresp (multiple-value-list ,true)))
(and (not ,gcond) (setf ,gresp (multiple-value-list ,false)))
(values-list ,gresp))))
_IF
[2]> (_if (= 1 1) (+ 2 3) "bar")
5
[3]> (_if (= 1 2) (+ 2 3) "bar")
"bar"
[4]>
Dans Scala il est possible de modéliser if
avec une évaluation correcte des effets secondaires en utilisant des arguments d'appel par nom.
def If[A](cond : Boolean, truePart : => A, falsePart : => A) = if (cond) truePart else falsePart
Ces caractéristiques peuvent être utilisées pour modéliser beaucoup de nouvelles structures de contrôle ainsi.
IF peut être une fonction dans un langage fonctionnel ayant la sémantique appel par nom (évaluation paresseuse), comme dans Lambda Calculus ou Algol. En fait, c'est, je pense, au cœur de la relation entre Machines et Lambda Turing calcul comme bases équivalentes pour l'informatique. Cependant, dans les langues ayant des effets secondaires (comme les affectations à des variables), il est pas très utile, parce que quand les choses est important.