Utilisation simple de request.el

9

Ma question embarrassante est la suivante:

Pourquoi le code suivant fonctionne-t-il:

(require 'request)

(defun geocoder ()
  (request
   "http://rpc.geocoder.us/service/csv"
   ;;; **Hardcoded parameter!**
   :params '(("address" . "1600 Pennsylvania Ave, Washington DC"))
   :parser 'buffer-string
   :success (function*
             (lambda (&key data &allow-other-keys)
                (when data
                (with-current-buffer (get-buffer-create "*request demo*")
                  (erase-buffer)
                  (insert data)
                  (pop-to-buffer (current-buffer))))))
   :error
   (function* (lambda (&key error-thrown &allow-other-keys&rest _)
                (message "Got error: %S" error-thrown)))
   ))

(geocoder)

Alors que celui-ci ne fonctionne pas?

(require 'request)

(defun geocoder (address) ;; adding a parameter!
  (request
   "http://rpc.geocoder.us/service/csv"
   :params '(("address" . address))
   :parser 'buffer-string
   :success (function*
             (lambda (&key data &allow-other-keys)
                (when data
                (with-current-buffer (get-buffer-create "*request demo*")
                  (erase-buffer)
                  (insert data)
                  (pop-to-buffer (current-buffer))))))
   :error
   (function* (lambda (&key error-thrown &allow-other-keys&rest _)
                (message "Got error: %S" error-thrown)))
   ))

;;; Now with parameter!
(geocoder "1600 Pennsylvania Ave, Washington DC")

Comment envoyer un paramètre à demander?

baol
la source

Réponses:

11

C'est parce que '(("address" . address))est cité (c'est-à-dire préfixé par l' 'opérateur), ce qui signifie que ce qui est à l'intérieur n'est pas évalué. La requestfonction est donc appelée avec un argument qui est le address symbole non évalué (alors que dans votre première implémentation, la requestfonction obtient une chaîne littérale, qui n'a pas besoin d'être évaluée en premier).

Vous pouvez résoudre ce problème de 2 manières:

1) en citant presque l'argument, ce qui vous permet d'obtenir principalement le même comportement mais de spécifier les parties qui doivent encore être évaluées:

`(("address" . ,address))

Notez que le guillemet simple ( ') a été remplacé par un guillemet arrière ( `), et un marqueur spécial a ,été ajouté avant addresspour indiquer qu'il doit être évalué et remplacé par sa valeur.

2) (selon le commentaire de @ JordonBiondo) la construction explicite de la structure en utilisant des primitives telles que listou cons. Dans votre cas, cela se ferait comme ceci:

(list (cons "address" address))

où, encore "address"une fois, est un littéral de chaîne (qui s'évalue par lui-même) et addressest évalué car il s'agit de l'argument dans un appel de fonction.

François Févotte
la source
Merci pour l'explication. Il s'améliore, mais maintenant j'obtiens "Argument de type incorrect: integerp, \," :(
baol
Ah, ok: gnu.org/software/emacs/manual/html_node/elisp/Quoting.html qui est un backquote !!
baol
1
J'ai ajouté des liens vers les parties pertinentes du manuel pour le rendre plus clair. Et j'ai aussi explicitement mentionné la
citation arrière
6
vous pouvez également l'écrire comme (list (cons "address" address))si vous ne vouliez pas utiliser de backticks
Jordon Biondo