"Il valore del simbolo come variabile è nullo" nella richiamata da url-recuperare


8

Quando eseguo quanto segue ricevo un errore:

(defun caller (func)
  (url-retrieve "http://m0smith.freeshell.org/"
   (lambda (status) (funcall func))))


(caller (lambda() (message "called")))

Risultato:

error in process filter: Symbol's value as variable is void: func

Qual è il modo migliore per risolvere questo problema? Fondamentalmente ho bisogno di accettare un callback da qualche altra parte, avvolgerlo in un altro lambda e usarlo come callback per recuperare l'URL.

Se cambio chiamante a

(defun caller (func)
  (url-retrieve "http://m0smith.freeshell.org/"
   `(lambda (status) (funcall ,func))))

Funziona. Tuttavia, non posso farlo poiché il flycheck viene superato da func e l'espansione della macro lo interrompe. Per vedere il contesto completo di ciò che sto facendo: https://gist.github.com/m0smith/b5961fda6afd71e82983


Quale espansione macro? Il tuo ultimo paragrafo non è chiaro. Pubblica qui una spiegazione completa del problema. L'uso di backquote con virgola è la soluzione (una soluzione). Un altro potrebbe essere l'uso lexical-leto l'impostazione della variabile lexical-binding. Si prega di chiarire qual è il problema con la "macro" non visualizzata.
Estratto il

Ho assunto il `e, erano macro espansi. Qualunque sia la forma che viene chiamata allora. Vorrei lavorare in EMACS 23. È disponibile una funzione lessicale?
M Smith,

Se non c'è alcun uso FUNColtre a quello funcalllogico, qui non è necessario il legame lessicale. Non c'è niente di sbagliato nell'usarlo, ma non ne hai bisogno , a meno che un po 'di codice non abbia effettivamente bisogno di usare la variabile FUNC . Se non ti serve (che è quello che sembra, finora), sostituisci semplicemente la sua occorrenza con il suo valore, usando il backquote con la virgola.
Estratto il

La rilegatura lessicale è disponibile in Emacs 23 (e precedenti), utilizzando lexical-let. La variabile globale lexical-bindingè disponibile in Emacs 24.
Estratto il

Risposte:


5

Puoi farlo localmente usando il lessico di cl.el :

(eval-when-compile '(require 'cl))

(defun my-test-caller (func)
  (lexical-let ((ext-func func))
    (url-retrieve "http://www.google.com"
                  (lambda (status) (funcall ext-func)))))

(my-test-caller #'(lambda() (message "called")))

Per essere espliciti come dice l'aiuto:

Like `let', but lexically scoped.
The main visible difference is that lambdas inside BODY will create
lexical closures as in Common Lisp.

Ora puoi ottenere lo stesso effetto abilitando il legame lessicale che è stato aggiunto in Emacs 24.1. Questa è una variabile locale del buffer che può essere impostata e abiliterà le chiusure lessicali su tutto il codice nel buffer. Quindi il tuo buffer sarebbe simile al seguente:

;; -*- lexical-binding: t; -*-

(defun my-lexical-test-caller (func)
  (url-retrieve "http://www.google.com"
                (lambda (status) (funcall func))))

(my-lexical-test-caller
 #'(lambda()
     (message "called from lexical-binding def")))

Grazie. Comunque ottengo my-test-caller: Symbol's function definition is void: lexical-letnei miei emacs: GNU Emacs 24.4.1 (x86_64-w64-mingw32) `del 20-10-2014 su KAEL
M Smith

@MSmith - ahh add (richiede 'cl)
stsquad

lexical-letè definito in cl-macs.el. Quindi(eval-when-compile '(require 'cl))
disegnato il

Non è necessario richiedere cl.elin fase di esecuzione, solo per questo. lexical-letè una macro, quindi è sufficiente richiederla al momento della compilazione.
Estratto il

2
Per favore, no. Usa lexical-binding. Flycheck non supporta comunque Emacs 23, quindi non ha senso cercare di essere compatibile con esso.

5

Abilita lexical-bindingper la tua libreria, con M-x add-file-local-variable-prop-line RET lexical-binding RET t.

Si prega di non utilizzare lexical-letcome suggerito dall'altra risposta. Flycheck stesso non è compatibile con Emacs 23, quindi non ha senso cercare di mantenere la compatibilità di Emacs 23 nel tuo codice.


Grazie. Questo mi aiuterà, quindi non sto cercando di far funzionare le emacs più vecchie senza motivo
M Smith,

Cosa c'è di sbagliato nell'usare lessical-let per questo?
stsquad,

@stsquad È più lento e più dettagliato. Con lexical-bindingnon è necessario un ulteriore binding, poiché l'argomento stesso ha un ambito lessicale. Inoltre, lexical-bindingcrea vere chiusure, mentre lexical-letutilizza simboli non orientati per emulare il legame lessicale.

@lunaryorn: non c'è alcun rischio abilitando il legame lessicale su un buffer esistente di codice legacy che potresti ottenere effetti imprevisti? Comunque ho ampliato la mia risposta per menzionare entrambe le soluzioni.
stsquad,

@stsquad Sì, potrebbero esserci effetti imprevisti in un codice legacy scritto male che si basa sul letlegame dinamico di variabili indefinite. Ma ancora una volta, Flycheck è comunque per Emacs 24, quindi non stiamo parlando di codice legacy.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.