clisp 可执行文件不会将其参数转换为函数调用。但是,您可以制作执行此操作的 CLISP 程序。我为 Lisp 应用程序的许可后端做了这样的事情。我想要一种简单的管理命令语言来从系统提示符中查找用户并授予他们许可证和类似的东西。所以我只写了一个 shim,它将单个命令行参数转换为 Lisp 对象,并收集到一个 List 中,并将其作为或多或少的函数进行调度。
让我们通过在一个名为clisp-dispatch.lisp的文件中制作这个程序来热身:
#!/usr/bin/env clisp
(print *args*)
当我们像这样运行它时,我们看到*args* 提供了对参数的访问:
$ chmod a+x clisp-dispatch.lisp # give it exec permission
$ ./clisp-dispatch.lisp
NIL
$ ./clisp-dispatch.lisp a b c 1 2 3
("a" "b" "c" "1" "2" "3")
非常好。现在我们希望看到的是列表(A B C 1 2 3):符号和数字的列表,而不是字符串的列表。让我们稍微修改一下代码:
#!/usr/bin/env clisp
(print (mapcar #'read-from-string *args*))
read-from-string 函数使用 Lisp 阅读器扫描字符串,返回其语法所暗示的 Lisp 对象。如果语法看起来像一个符号,则返回一个符号;如果是数字,则返回一个数字,依此类推。例如(read-from-string "(1 2 3")) 产生列表(1 2 3)。这样,我们得到:
$ ./clisp-dispatch.lisp a b c 1 2 3
(A B C 1 2 3)
非常好!所以剩下的就是将此列表视为 Lisp 代码,为此我们只需将其传递给 eval 函数。让我们保留print,但将其用于eval 的结果:
#!/usr/bin/env clisp
(print (eval (mapcar #'read-from-string *args*)))
现在我们可以这样做了:
$ ./clisp-dispatch.lisp + 2 2
4
$ ./clisp-dispatch.lisp list 1 2 3
(1 2 3)
$ ./clisp-dispatch.lisp cons "'a" 3
(A . 3)
因此,如果我们定义一个intmax 函数,我们可以从系统提示符处调用它。
#!/usr/bin/env clisp
(defun intmax (a b)
(max a b))
(print (eval (mapcar #'read-from-string *args*)))
$ ./clisp-dispatch.lisp intmax 3 1
3
$ ./clisp-dispatch.lisp intmax 7 10
10
不过,您最好从 Lisp 中探索 Lisp,而不是像这样从命令行间接调用它。一方面,每次我们运行这个程序时,都会启动一个新的 Lisp 映像。我们无法与环境互动。我们还必须对某些语法使用非常笨拙的引用,例如我使用 "'a" 将 'a 传递给 Lisp 的方式。
我们所做的是以一种在clisp 可执行文件中不直接支持的非常特殊的方式使用 Lisp:像 Lisp 对象一样解析参数,然后将结果视为函数调用。无论如何,任何想像他一样“滥用” Lisp 的人都可以编写上面的小程序。
还要注意我是如何定义intmax 的,只需调用max。重点是Common Lisp中不需要定义intmax;内置的max 函数接受一个或多个参数并返回最大值:(max 1 3 2) 产生3。因为(int-max x y) 只是(max x y),所以int-max 没有理由存在。它只是 max 的一个受损同义词,它需要多输入四个字符,并且不需要超过两个参数。