在Common Lisp中从键盘读取Lambda表达式

时间:2019-06-13 13:39:44

标签: input lambda common-lisp

我希望能够从键盘读取lambda表达式。例如,如果功能方块已经被拒绝,我可以输入符号名称:

(defun square (x) (* x x))

以便在评估以下内容时:

(funcall (read) 2)

用户可以键入square,结果为4。但是,如果用户键入

(lambda (x) (* x x))

结果为错误,例如在Macintosh Common Lisp中,

  

错误:(LAMBDA(X)(* X X))不能被启用或应用

有没有一种简单的方法可以做到这一点,而我却不见了?

谢谢。

4 个答案:

答案 0 :(得分:9)

read返回一个list,必须对其进行{em>评估才能对其进行funcall编辑。

这可以使用read-time evaluation完成:

(funcall (read) 2)
#.(lambda (x) (* x x))
==> 4

但是,通常来说,这是一个安全漏洞(您正在评估用户提供的代码-如果他们键入#.(start-nuclear-war)会怎样?),因此谨慎的工程师会将*read-eval*绑定到nil读取输入内容时,他们无法控制。

因此最好显式使用coerce

(funcall (coerce (let ((*read-eval* nil)) (read)) 'function) 2)
1+
==> 3
(funcall (coerce (let ((*read-eval* nil)) (read)) 'function) 2)
(lambda (x) (* x x))
==> 4

答案 1 :(得分:7)

由于使用的是read,因此通常需要评估返回的表格以获得有意义的值。但是在特定情况下,您可以使用COERCE。例如,从REPL:

CL-USER> (coerce '+ 'function)
#<FUNCTION +>

上面找到了符号+fbound的函数。

CL-USER> (coerce '(lambda (x) (* x x)) 'function)
#<FUNCTION (LAMBDA (X)) {53F2BF2B}>

上面的代码使用lambda expression并将其转换为功能对象。

答案 2 :(得分:3)

您会收到此错误,因为READ仅返回列表 (LAMBDA (X) (* x x)),而不会将其评估为函数。为此,您需要编写:

(funcall (eval (read)) 2)

请注意,尽管在那种情况下,仅写square不再有效,用户现在需要输入#'square

答案 3 :(得分:2)

CL-USER 8 > (defun read-function (&optional (stream *standard-input*))
              (let ((f (read stream)))
                (cond (; function object
                       (functionp f) f)
                      (; symbol naming a function
                       (symbolp f) (symbol-function f))
                      (; (function f)
                       (and (consp f)
                            (eq (first f) 'function))
                       (eval f))
                      (; (lambda ...)
                       (and (consp f)
                            (eq (first f) 'lambda))
                       (eval f)))))
READ-FUNCTION

示例:

CL-USER 9 > (read-function)
#.#'+
#<Function + 40F0044AD4>

CL-USER 10 > (read-function)
+
#<Function + 40F0044AD4>

CL-USER 11 > (read-function)
#'+
#<Function + 40F0044AD4>

CL-USER 12 > (read-function)
(lambda (a b) (+ a b))
#<anonymous interpreted function 4060000C8C>