4

因为我是 Common Lisp 的新手,所以我尝试使用 Common Lisp ( SBCL )来解决SPOJ上的问题。第一个问题是阅读数字直到找到数字 42 的简单任务。这是我的解决方案:

(defun study-num ()
  (let ((num (parse-integer (read-line t))))
    (when (not (= num 42))
      (format t "~A~%" num)
      (study-num))))
(study-num)

解决方案被接受。但是当我查看结果的细节时,我发现它使用了 57M 的 MEM!这太不合理了,但我不知道为什么。我可以做些什么来进行优化?

4

3 回答 3

5

您正在进行重复的递归调用,但没有打开足够的优化来消除尾调用(SBCL 确实这样做,但只有当您将“优化速度”设置为高且“优化调试信息”设置为低时)。

Common Lisp 标准将尾调用消除作为实现质量问题,并提供了其他循环结构(如 LOOP 或 DO,两者都可能适用于该应用程序)。

此外,由于需要拉入其运行时环境和基础映像,新启动的 SBCL 可能会比您预期的要大。

于 2012-01-25T12:46:54.417 回答
4

各种 Lisp 实现有不同的方法来创建程序。一种是转储 Lisp 系统的内存映像并将其写入磁盘。重新启动时,此图像会加载运行时,然后再次启动。这很常见。

这也是 SBCL 在保存可执行文件时所做的。因此,这个可执行文件包括完整的 SBCL。

其他一些实现正在使用图像(CLISP)创建更小的可执行文件,一些可以从可执行文件中删除未使用的代码(Allegro CL、LispWorks),还有一些通过编译为 C(mocl)来创建非常小的程序。

SBCL 只有一种简单的方法来减小可执行文件的大小:可以压缩图像。

于 2015-01-22T09:19:09.003 回答
4

我想你没有意识到 Common Lisp 是一个在线语言环境,它有完整的库和编译器加载到 RAM 中,只是为了给你第一个提示。在那之后,您的程序中的负载可能几乎不会显着增加。Lisp 不会编译和链接仅由您的代码和您的代码可访问的任何 lib 例程组成的独立可执行文件。这就是 C 和类似语言所做的。相反,Lisp 将您的代码添加到其已经相当大的在线环境中。作为一个新用户,它接缝可怕。但是,如果您拥有一台配备 100 MB RAM 的现代通用计算机,那么当您享受在线环境的好处时,您很快就会忘记它。Thins 也称为“动态语言环境”。

于 2014-02-09T22:28:02.193 回答