2011-02-22 12 views
9

Primero, soy muy nuevo en el ceceo, por lo que es posible que me esté perdiendo algo muy obvio. Dicho esto, tengo Practical Common Lisp abierto al lado mío y CL Hyper Spec abierto en la siguiente pestaña, y no he podido resolver este problema:Common Lisp: ¿Por qué se transfieren símbolos al paquete incorrecto cuando se lee desde un archivo?

Estoy tratando de leer un árbol de un archivo y asignar valores a ranuras en una clase utilizando este código:

(defun load-char (file) 
    (with-open-file (in file) 
    (with-standard-io-syntax 
     (let ((chr-in (read in)) 
      (chr (make-instance 'pc))) 
     (mapcar #'(lambda (x) (setf (slot-value chr (car x)) (cdr x))) chr-in) 
     chr)))) 

Cuando originalmente hackeado esto juntos y corrió bajo el paquete todo cl-usuario funcionaba perfectamente - yo estaba muy orgulloso de mí mismo, en realidad. El problema comenzó cuando empaqué esto junto con mi definición de clase y algunas funciones auxiliares en un nuevo paquete. Cargué el paquete usando asdf, luego usé (in-package :package-name) para cambiar el paquete activo de mi REPL.

Ahora cuando ejecuto (load-char "/path/to/file") me sale un error que dice que COMMON-LISP-USER::ID (ID es la primera ranura en mi clase de pc) no existe, así que escribí esto para ver lo que estaba obteniendo cuando leí el archivo en:

(defun load-char-test (file) 
    (with-open-file (in file) 
    (with-standard-io-syntax 
     (let ((chr-in (read in)) 
      (chr (make-hash-table))) 
     (mapcar #'(lambda (x) (setf (gethash (car x) chr) (cdr x))) chr-in) 
     (maphash #'(lambda (k v) (format t "~a: ~a~%" k v)) chr) 
     chr)))) 

Luego, en el REPL hago (defparameter hsh (load-char-test "/path/to/file")) y todo va sin errores, y mis devuelve la llamada de formato exactamente lo que espero (SLOT: VALOR). Pero cuando hago un (gethash 'id hsh), devuelve NIL NIL. Pero, cuando lo hago (gethash 'common-lisp-user::id hsh), devuelve el valor esperado.

Por lo tanto, estoy leyendo todo muy bien, pero todo en mi lista está siendo internado en el paquete COMMON-LISP-USER en lugar del que yo definí, y no puedo entender por qué. La ayuda es muy apreciada.

P.S. Lo siento si esta publicación es innecesariamente larga, solo quería mostrar que había intentado resolver esto por mi cuenta.

Respuesta

13

símbolos creados por READ están internados en el paquete que es el actual valor de *PACKAGE* en tiempo de ejecución, no el valor *PACKAGE* tenía cuando se definió el código que llama READ. Una opción, entonces, es ajustar sus formularios de lectura en un formulario que se une al *PACKAGE*, p.

(let ((*package* (find-package :package-name))) 
    ...) 
+0

¿Es esto lo que quieres decir? http://pastebin.com/e0xmUAmp. Todavía está internado bajo cl-usuario. – oobivat

+0

@oobivat: ver mi respuesta. El LET debe estar dentro de la macro WITH-STANDARD-IO-SYNTAX. –

+0

Solucionado aquí: http://pastebin.com/f0V06uzm. Gracias por las respuestas rápidas. – oobivat

10

Tenga en cuenta que la variable se une WITH-STANDARD-IO-SYNTAX*PACKAGE* al paquete CL-USER.

Debe vincular la variable *PACKAGE* dentro de esa macro con LET al paquete que desea utilizar.

Tenga en cuenta también que WITH-STANDARD-IO-SYNTAX vincula la variable *READ-EVAL* a T. Que por razones de seguridad generalmente no es lo que uno podría querer como predeterminado. Nuevamente, cambie eso a través de un enlace LET.

+0

Reparado. Muchas gracias. – oobivat

Cuestiones relacionadas