Quand faut-il utiliser des guillemets nets?

10

Je vois des guillemets nets utilisés dans le code eLisp d'autres personnes, et je les utilise moi-même, mais je ne sais pas exactement quand ils sont appropriés et quand ils ne le sont pas.

Quelqu'un pourrait-il préciser exactement quand il convient d'utiliser des guillemets nets et quand les guillemets simples ordinaires devraient être utilisés à la place?

izkon
la source
3
nb Il existe de nombreux doublons pour cette question ici ou sur SO
phils
Duplicata possible de Quand citer avec précision une expression lambda?
Andrew Swann
1
Je ne pense pas que ce soit un doublon: emacs.stackexchange.com/questions/3595 concerne l'utilisation #'avec lambda (où la réponse est fondamentalement "jamais"), tandis que la question de @ izkon s'applique plutôt à l'utilisation d' #'appliqué aux symboles.
Stefan

Réponses:

12

#'est juste un raccourci pour function, tout comme un 'raccourci pour quote.

Vous pouvez l'utiliser partout où vous voulez indiquer au compilateur d'octets ou à l'interpréteur ou à un lecteur humain que son argument devrait être (est traité comme) une fonction.

Dans de nombreux contextes, le contexte détermine la façon dont l'argument est traité si, par exemple, vous le citez simplement (utilisez quoteou ') au lieu d'utiliser #'(ou function). Par exemple, dans un contexte où un symbole n'est utilisé que pour sa symbol-functionpropriété, c'est-à-dire qu'il est utilisé en tant que fonction, vous pouvez simplement passer le symbole (par exemple en le citant ou en passant une variable dont la valeur est le symbole).

Mais parfois, le code est plus clair si vous l'utilisez #'dans de tels contextes. Même si Emacs-Lisp comprend lui-même que le symbole est utilisé en tant que fonction dans de tels contextes, cela pourrait aider à le souligner pour un lecteur humain du code.

Dans certains autres Lisps, le traitement des formes lambda simplement citées (avec ') ou non citées peut différer de leur utilisation dans une position de fonction lorsqu'elles sont citées avec function( #'). Mais pas dans Emacs Lisp. Dans Emacs Lisp, vous n'avez pas besoin de citer (en utilisant l'un 'ou l' autre #') un formulaire lambda que vous souhaitez traiter comme une fonction (et pas simplement comme une liste). Si vous voulez qu'il soit traité comme une simple liste, avec une voiture, lambdaetc., citez-le (avec ') - l'exemple ci-dessous illustre cela.

De (elisp) Fonctions anonymes :

- Formulaire spécial: function function-object

Ce formulaire spécial revient FUNCTION-OBJECTsans l'évaluer.

En cela, il est similaire à quote(* note Quoting: :). Mais contrairement à quotecela, il sert également de note à l'évaluateur Emacs et au compilateur d'octets qui FUNCTION-OBJECTest destiné à être utilisé en tant que fonction. En supposant FUNCTION-OBJECTque l'expression lambda est valide, cela a deux effets:

• Lorsque le code est FUNCTION-OBJECTcompilé en octets , il est compilé en un objet fonction de code en octets (* remarque Compilation d'octets: :).

• Lorsque la liaison lexicale est activée, FUNCTION-OBJECTest converti en fermeture. * Notez les fermetures ::.

La syntaxe de lecture #'est un raccourci pour l'utilisation function. Les formulaires suivants sont tous équivalents:

(lambda (x) (* x x))
(function (lambda (x) (* x x)))
#'(lambda (x) (* x x))

Dans l'exemple suivant, nous définissons une change-propertyfonction qui prend une fonction comme troisième argument, suivie d'une double-property fonction qui l'utilise change-propertyen lui passant une fonction anonyme:

(defun change-property (symbol prop function)
   (let ((value (get symbol prop)))
     (put symbol prop (funcall function value))))

(defun double-property (symbol prop)
   (change-property symbol prop (lambda (x) (* 2 x))))

Notez que nous ne citons pas le lambdaformulaire.

Si vous compilez le code ci-dessus, la fonction anonyme est également compilée. Cela ne se produirait pas si, par exemple, vous aviez construit la fonction anonyme en la citant comme une liste:

(defun double-property (symbol prop)
   (change-property symbol prop '(lambda (x) (* 2 x))))

Dans ce cas, la fonction anonyme est conservée en tant qu'expression lambda dans le code compilé. Le compilateur d'octets ne peut pas supposer que cette liste est une fonction, même si elle en ressemble à une, car il ne sait pas qu'il a l' change-propertyintention de l'utiliser comme fonction.

A dessiné
la source
9

#'(aka function) peut être utilisé devant (lambda ...)mais il est redondant là-bas, donc le seul endroit où il est vraiment significatif est devant un symbole, comme dans #'car. Dans ELisp, #'caret 'carsont presque complètement équivalents, l'un des principaux objectifs est simplement de documenter l'intention (c'est-à-dire d'indiquer à celui qui lit ce code que vous avez l'intention d'utiliser ce symbole comme fonction). Pourtant, il existe quelques circonstances, où la différence est plus importante:

  • Le compilateur d'octets tire parti de cette intention documentée et lorsque vous l'écrivez, #'caril vérifie s'il carexiste en tant que fonction, et s'il ne le trouve pas, il émet un avertissement, tout comme si vous aviez appelé cette fonction. .
  • À l'intérieur cl-fletet cl-labels, seul #'fpeut faire référence à la fonction définie localement f, car 'ffera toujours référence au symbole global f(et quelle que soit la fonction qui peut être stockée dans son symbol-functionemplacement). Par exemple

    (cl-flet ((car (x y) (+ x y)))
      (list #'car 'car))
    =>
    ((closure nil (x y) (+ x y)) car)
    
Stefan
la source