Common Lisp中loop循环内调用with定义的lambda函数时出现未定义错误的问题咨询
Common Lisp中loop循环内调用with定义的lambda函数时出现未定义错误的问题咨询
嘿,我来帮你理清这个问题~你遇到的错误其实是Common Lisp里函数命名空间和值命名空间分离导致的小坑!
问题根源
你在loop里用with some_func = (lambda (x) (* x x))定义的some_func是一个变量,它存储的是一个lambda函数对象,但直接写(some_func item)的时候,Lisp会把some_func当成一个函数符号去函数命名空间里查找定义,而不是去值空间里读取这个变量存的函数对象,所以才会报“函数未定义”的错。
要调用存储在变量里的函数对象,你需要用funcall(参数是单个值时用这个)或者apply(参数是列表时用)来触发调用,语法是(funcall 函数变量 参数...)。
先修复你的现有代码
把调用some_func的地方改成这样就能正常运行:
(defun calcVarianz (vec) "Berechnet die Varianz eines Vektors." (loop with len = (length vec) with mean = (/ (sum vec) len) with some_func = (lambda (x) (* x x)) for item in vec collecting (square (- item mean)) into squared collecting (funcall some_func item) into some_vector ; 用funcall调用lambda变量 finally (return (/ (sum squared) (- len 1)))))
关于把sum和square改成lambda放在loop里的问题
当然可以实现!同样遵循“用with定义lambda变量,用funcall调用”的规则就行。比如修改后的完整代码可以是这样:
(defun calcVarianz (vec) "Berechnet die Varianz eines Vektors." (loop with len = (length vec) with sum-func = (lambda (v) (apply '+ v)) ; 把sum改成lambda变量 with square-func = (lambda (x) (* x x)) ; 把square改成lambda变量 with mean = (/ (funcall sum-func vec) len) with some_func = (lambda (x) (* x x)) for item in vec collecting (funcall square-func (- item mean)) into squared collecting (funcall some_func item) into some_vector finally (return (/ (funcall sum-func squared) (- len 1)))))
这样就把所有辅助逻辑都封装在loop内部,不需要单独定义外部函数了。
补充说明
简单总结下:Common Lisp有两个独立的命名空间——函数命名空间(存储函数符号对应的定义)和值命名空间(存储变量的值)。普通的函数调用(func-name args)是在函数命名空间查找,而存在变量里的lambda属于值空间的内容,必须用funcall明确告诉Lisp:“去值空间读取这个变量里的函数对象,然后调用它”。
备注:内容来源于stack exchange,提问作者Jan
相关产品推荐
相关产品推荐

