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

Pau*_*ulM 7 lambda input common-lisp

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

(defun square (x) (* x x))
Run Code Online (Sandbox Code Playgroud)

以便在评估以下内容时:

(funcall (read) 2)
Run Code Online (Sandbox Code Playgroud)

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

(lambda (x) (* x x))
Run Code Online (Sandbox Code Playgroud)

结果是一个错误,例如在Macintosh Common Lisp中,

错误:(LAMBDA(X)(* XX))无法执行或应用

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

谢谢。

sds*_*sds 9

read返回list,必须先评估 a ,然后才能对其进行funcall编辑。

这可以使用读取时间评估来完成:

(funcall (read) 2)
#.(lambda (x) (* x x))
==> 4
Run Code Online (Sandbox Code Playgroud)

但是,通常来说,这是一个安全漏洞(您正在评估用户提供的代码-如果键入)#.(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
Run Code Online (Sandbox Code Playgroud)


cor*_*ump 7

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

CL-USER> (coerce '+ 'function)
#<FUNCTION +>
Run Code Online (Sandbox Code Playgroud)

上述的发现,以该符号的功能+fbound

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

上面的代码使用了一个lambda表达式并将其变成一个函数对象。


Rai*_*wig 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
Run Code Online (Sandbox Code Playgroud)

例子:

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>
Run Code Online (Sandbox Code Playgroud)