2011-07-29 13 views
7

¿Es posible rastrear un cierre en CL? Por ejemplo, ¿puedo rastrear foo-3 a continuación?Trazando un cierre

(defun foo (n) 
    (lambda (i) (incf n i))) 
FOO 
(setf foo-3 (foo 3)) 
#<CLOSURE :LAMBDA (I) (INCF N I)> 

(funcall foo-3 2) 
5 
(funcall foo-3 2) 
7 
(trace ???) 
+1

¡Gran pregunta! –

Respuesta

1

De hecho, es posible hacerlo. Trace busca funciones en el espacio de nombres de funciones, así que asegúrese de no mezclar valores y funciones.

(setf (symbol-function 'test) 
    (let ((n 0)) 
    (lambda (x) 
    (incf n x)))) 
=> 
#<Interpreted Closure TEST> 
(trace test) 
... 
(test 4) 
=> 
0[2]: (TEST 4) 
0[2]: returned 4 
4 
(test 3) 
=> 
0[2]: (TEST 3) 
0[2]: returned 7 
7 
+0

Gracias! He estado revisando http://www.gnu.org/s/emacs/manual/html_node/elisp/Symbol-Components.html#Symbol-Components, http://www.dreamsongs.com/Separation.html y el CLTL. Me siento bien por esto ahora. ¿Algún otro recurso sobre este tema de espacios de nombres a los que valga la pena hacer referencia? – user869081

3

No creo que esto es posible: por lo que yo sé, la macro traza generalmente funciona mediante la sustitución de la función en un símbolo dado por una envoltura que llama a la original y también imprime el bit de rastreo.

Si está interesado en los detalles de implementación (complicados), el código SBCL está en src/code/ntrace.lisp (probablemente quiera ver la función trace-1).

Por supuesto, si lo que quieres hacer es algo de impresión cuando foo-3 se llama, siempre se puede poner una declaración de impresión dentro de la forma de lambda en foo ...

+1

¿Hay algo fundamental acerca de los cierres que hace que escribir una función de rastreo para ellos sea imposible? – user869081

0

Creo que el problema aquí es que trace requiere un nombre de función, en lugar de que haya un problema con los cierres de seguimiento. Continuando con el ejemplo anterior, puede llamar foo-3 de una función llamada, y la huella que:

(defun call-foo-3 (i) 
    (funcall foo-3 i)) 
(trace call-foo-3) 
(call-foo-3 2) 
    0: (CALL-FOO-3 2) 
    0: CALL-FOO-3 returned 15