Uso simple de request.el

9

Mi pregunta embarazosamente fácil es la siguiente:

¿Por qué funciona el siguiente código?

(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)

Mientras que este no?

(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")

¿Cómo debo enviar un parámetro para solicitar?

baol
fuente

Respuestas:

11

Esto se debe a que '(("address" . address))se cita (es decir, con el prefijo del 'operador), lo que significa que lo que está dentro no se evalúa. Por lo requesttanto, la función se llama con un argumento que es el address símbolo no evaluado (mientras que en su primera implementación, la requestfunción obtiene una cadena literal, que no necesita evaluarse primero).

Puedes arreglar esto de 2 maneras:

1) citando el argumento, lo que le permite obtener principalmente el mismo comportamiento pero especificar partes que aún deben evaluarse:

`(("address" . ,address))

Tenga en cuenta que la comilla simple ( ') ha sido reemplazada por una comilla invertida ( `), y ,se agregó un marcador especial antes addresspara indicar que debe evaluarse y sustituirse con su valor.

2) (según el comentario de @ JordonBiondo) construyendo la estructura explícitamente usando primitivas como listo cons. En su caso, esto se haría así:

(list (cons "address" address))

donde, de nuevo, "address"es un literal de cadena (que se evalúa a sí mismo), y addressse evalúa ya que es el argumento en una llamada a la función.

François Févotte
fuente
Gracias por la explicación. Está mejorando, pero ahora aparece "Argumento de tipo incorrecto: integerp, \," :(
baol
¡Ah, está bien: gnu.org/software/emacs/manual/html_node/elisp/Quoting.html que es una cita inversa!
baol
1
Agregué enlaces a partes relevantes del manual para hacerlo más claro. Y también mencioné explícitamente el presupuesto ya que, como era de esperar, no era tan obvio a primera vista ...
François Févotte
66
alternativamente, podrías escribir eso como (list (cons "address" address))si no quisieras usar backticks
Jordon Biondo