SBCL中调用导出函数提示‘Function Undefined’问题咨询
问题描述
我是Common Lisp新手,正在通过Exercism练习入门。我的环境是Windows 10上WSL2中的Debian,使用SBCL 2.1.1及Quicklisp。
我的代码文件内容如下:
(defpackage :lillys-lasagna-leftovers (:use :cl) (:export :preparation-time :remaining-minutes-in-oven :split-leftovers)) (in-package :lillys-lasagna-leftovers) (defun preparation-time (&rest rest) (* 19 (length rest))) (defun remaining-minutes-in-oven (&optional (opt :normal opt-provided)) (if opt-provided (cond ((eql opt :shorter) 337) ((eql opt :very-short) 137) ((eql opt :longer) 437) ((eql opt :very-long) 537) (t nil)) opt))
我尝试了两种加载文件的方式:
- 进入SBCL后执行:
(load "test-file-name") (preparation-time 1 2 3)
- 通过命令行执行:
sbcl --load "test-file-name"
然后在SBCL提示符里输入(preparation-time 1 2 3)
两种方式都遇到了相同的错误:
CL-USER(1): (preparation-time) ; in: PREPARATION-TIME ; (PREPARATION-TIME) ; ; caught STYLE-WARNING: ; undefined function: COMMON-LISP-USER::PREPARATION-TIME ; ; compilation unit finished ; Undefined function: ; PREPARATION-TIME ; caught 1 STYLE-WARNING condition
请问我哪里操作有误?我想找到本地测试代码的正确方法。
问题原因与解决方法
核心问题是包的作用域限制:你定义的preparation-time函数属于自定义包:lillys-lasagna-leftovers,但调用时你处在默认的CL-USER包中,CL-USER无法直接访问其他包的导出符号,除非显式指定。
正确的测试方法有两种:
切换到自定义包后调用
加载文件后,先切换到目标包,再直接调用函数:(load "test-file-name") (in-package :lillys-lasagna-leftovers) (preparation-time 1 2 3) ; 此时可直接调用在CL-USER包中使用包前缀调用
若不想切换包,可通过包名前缀明确指定要调用的函数:(load "test-file-name") (lillys-lasagna-leftovers:preparation-time 1 2 3)
命令行一次性执行的优化方式
如果想通过命令行直接完成加载+测试,无需进入交互模式,可以用--eval参数指定执行语句:
sbcl --load "test-file-name" --eval "(lillys-lasagna-leftovers:preparation-time 1 2 3)" --quit
或者切换包后执行:
sbcl --load "test-file-name" --eval "(in-package :lillys-lasagna-leftovers)" --eval "(preparation-time 1 2 3)" --quit
额外提示
你的代码已经通过(:export ...)导出了preparation-time,所以以上两种调用方式均合法。如果未导出符号,只能使用包前缀的方式调用(新手阶段不推荐用intern等复杂方法)。
内容的提问来源于stack exchange,提问作者Artexias
相关产品推荐
相关产品推荐

