How can I specify the package name when launching

2019-07-06 06:41发布

I'm calling a Lisp function (and a few other thing) from a shell script. For brevity, below is relevant part of the script :

./gcl -load /tmp/calendrica-3.0.cl -batch -eval '(format T "~a" (CC3::sunset (CC3::fixed-from-gregorian (CC3::gregorian-date 1996 CC3::february 25)) CC3::jerusalem))' 728714.7349874675

The above code works fine but I had to append the package name CC3 for every symbol that is used; which makes the code unwieldy and hard to type.

I tried to simplify it like so, using use-package :

./gcl -load /tmp/calendrica-3.0.cl -batch -eval '(format T "~a" (use-package "CC3") (sunset (fixed-from-gregorian (gregorian-date 1996 february 25)) jerusalem))'

Much easier to read and type, but unfortunately it doesn't work. I've tried all sorts of ways to include the use-package directive but so far no success.

Is it even possible to include a use-package directive while launching a Lisp program via the GNU Common Lisp's (gcl) load directive?

Update: The solution is to use multiple evals as suggested by the accepted answer.

./gcl -load /tmp/calendrica-3.0.cl -batch -eval '(use-package "CC3")' -eval '(format T "~a" (sunset (fixed-from-gregorian (gregorian-date 1996 february 25)) jerusalem))'

2条回答
唯我独甜
2楼-- · 2019-07-06 07:25

Maybe you could use multiple eval, here is what I do with sbcl.

#!/bin/sh
sbcl --noinform \
   --eval '(load "boot.lisp")' \
   --eval '(in-package #:my-pkg)' \
   --eval "(do-something-useful)" # do-something-useful is in my-pkg
查看更多
【Aperson】
3楼-- · 2019-07-06 07:35

It's maybe possible to do that but it will be ugly.

If you give it a form form evaluation, it will read the form first. Thus it then is too late during evaluation to change the reader (telling new packages, ...). Thus it needs to be done before.

CL-USER 1 > (eval (read-from-string "(foo::bar)"))
Error: Reader cannot find package FOO.

Better:

CL-USER 5 > (eval '(progn (defpackage foo (:use "CL"))
                          (read-from-string "(foo::bar)")))
(FOO::BAR)

So, if you want to pass a single form to eval, you would write which first creates the package and then reads/evals from a string, which is encoded in the form. Tricky.

Alternatives:

  • maybe the Lisp allows at startup multiple -eval forms? Do whatever you need to initialize Lisp to know about the packages in the first -eval form. Then have the code to execute in the second form.

  • write a file and put the necessary forms there. Load it. Since a file can contain multiple forms, you can have DEFPACKAGE, IN-PACKAGE or similar on top and then have the rest of the code in the file depending on it.

查看更多
登录 后发表回答