Generic lisp: got different result with SBCL after saving image

(This is the first time I posed a question here, I searched but couldn't find any useful information ....)

I found it interesting (which confused me all the damn morning), something common lisp.

I am using SBCL 1.1.18 running on Gentoo / Linux. Here's my problem:

Suppose there is a package named eql-test that has an asd file, package.lisp and main.lisp (a fairly common configuration). There is only one function inside main.lisp:

    (defun main ()
      (format t "~a~%" (eql 'hello (read-from-string "hello"))))

      

Now if we run:

    sbcl --eval "(progn (load \"main.lisp\") \
      (sb-ext:save-lisp-and-die \"eql-test\" :toplevel #'main \
      :executable t))"

      

and then run the "eql-test" binary, we get a nice T.

However, if we use another file named "make.lisp" which contains:

    (asdf:load-system 'eql-test)
    (sb-ext:save-lisp-and-die "eql-test2"
          :toplevel #'eql-test:main
          :executable t)

      

and then run:

    sbcl --load "make.lisp"

      

then run the binary "eql-test2" it will give NIL.

I don't understand why the same code gives a different result (definitely the second is wrong). Because it is an implicit ASDF error? Or is there something wrong with my code?

Thanks for any help! :)

+3


source to share


2 answers


Rule of thumb: When in doubt, always monitor which package is used in the source code, in I / O operations, when creating new characters when looking for characters, ...

If you are reading a line, you have to make sure that any generated symbol will be in the correct package. You can link *package*

:

CL-USER 1 > *package*
#<The COMMON-LISP-USER package, 155/256 internal, 0/4 external>

CL-USER 2 > (read-from-string "FOO")
FOO
3

      

Above: FOO

found in the package CL-USER

.

Create a new package:

CL-USER 3 > (defpackage "BAR" (:use "CL"))
#<The BAR package, 0/16 internal, 0/16 external>

      



The global has *package*

n't changed:

CL-USER 4 > *package*
#<The COMMON-LISP-USER package, 155/256 internal, 0/4 external>

      

Bind variable:

CL-USER 5 > (let ((*package* (find-package "BAR")))
              (read-from-string "FOO"))
BAR::FOO
3

      

Above: FOO

found in the package BAR

.

Also make sure any source code is a package specific ... make sure the package is not modified in various ways to download the code ...

+5


source


Finally I got an answer that seems to be correct ... the post is here to help.

Suppose you want to (eq 'foo (read-from-string "foo"))

return the T which "foo is in MY-PACKAGE

.

First, and most IMPORTANT, if we are doing (read-from-string "foo")

either or (intern "foo")

or (find-symbol "foo")

or whatever, the real character readable by the reader |foo|

, which means "foo" in lowercase as the name of the character, but not FOO

what we want. As these functions will exactly read the character you give as a string. So, (read-from-string "foo")

will return a character FOO

. - This is exactly what we want.



Second, and also importantly, when we are (save-lisp-and-die ...)

in SBCL (use "buildapp" instead) and run the generated image executable, we are in the package COMMON-LISP-USER

, but not something else. So actually LISP is trying eq

MY-PACKAGE::FOO

and COMMON-LISP::FOO

what will be NIL.

FIX:
(intern "FOO" :my-package)

must do the trick.

Note: the
"name"

argument in the function "intern"

will be NAME as the name of the symbol, including case.

0


source







All Articles