运行 通过 CLISP 在 Linux (Ubuntu WSL) 上的 LISP 代码

Running LISP code via CLISP on Linux (Ubuntu WSL)

我是 LISP 的新手,想知道如何在 Ubuntu Linux 上正确地 运行 一个简单的 lisp 程序。目前,我有一个名为“intmax.lisp”的 LISP 文件,其中包含以下代码:

(defun intmax (x y) (if (> x y) x y))

然而,当我进入命令行并且 运行:

clisp intmax 2 4

为了比较 2 和 4,我没有得到任何输出。关于我做错了什么有什么建议吗?

首先,请使用 REPL。那不是 shell 命令行,而是类似于 Lisp 内部的命令行。

启动 Lisp 系统:

clisp

您会收到如下提示:

[1]>

加载您的文件:

[1]> (load "intmax.lisp")

现在你可以调用你的函数了:

[2]> (intmax 2 4)

它会打印:

4

并再次提示:

[3]>

您可能希望稍后了解包和系统,以便组织您的代码。

如果你想从命令行调用东西,你需要告诉clisp加载需要的东西,然后执行一个lisp命令。查看手册页。示例:

clisp -q -i intmax.lisp -x '(intmax 2 4)'

clisp 可执行文件不会将其参数转换为函数调用。但是,您可以编写执行此操作的 CLISP 程序。我为 Lisp 应用程序的许可后端做了这样的事情。我想要一种简单的管理命令语言来查找用户并从系统提示符授予他们许可证和类似的东西。所以我只是写了一个 shim,它将各个命令行参数转换为 Lisp 对象,这些对象收集到一个列表中,并将它或多或少地作为一个函数进行调度。

让我们在名为 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 reader 扫描字符串,返回其语法隐含的 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 函数接受一个或多个参数,returns 最大值:(max 1 3 2) 产生 3。因为 (int-max x y) 只是 (max x y),所以 int-max 没有存在的理由。它只是 max 的一个受损同义词,它需要多输入四个字符并且不超过两个参数。