Reading lambda expressions from keyboard in Common Lisp

read returns a list which has to be evaluated before it can be funcalled.

This can be accomplished using read-time evaluation:

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

However, generally speaking, this is a security hole (you are evaluating user-supplied code - what if they typed #.(start-nuclear-war)?) so a cautious engineer will bind *read-eval* to nil when reading input they have no control over.

Thus it is much better to use coerce explicitly:

(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

Since you are using read, in general you would need to evaluate the returned forms to obtain meaningful values. But in your particular case, you can use COERCE. For example, from a REPL:

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

The above finds the function to which the symbol + is fbound.

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

The above takes a lambda expression and turn it into a function object.


You get that error because READ returns just the list (LAMBDA (X) (* x x)), it does not evaluate it to a function. To do that, you would need to write:

(funcall (eval (read)) 2)

Note though that in that case, just writing square doesn't work anymore, the user would now need to enter #'square.