Using a lambda value from a function as the first element of a list

I am reading Peter Norwig's artificial intelligence programming paradigm, and I run into a problem that I cannot solve on my own (this is my introduction to Lisp). The question is quite small, indeed, but obviously not one of my little brains can solve it.

Why does this mean that when the function value is lambda, the error is to use this function as the first element in the list. For example:

Lisp:

(defun some-func () #'(lambda (x) x)) ;; At REPL ;; Does not work > ((some-func) 1) ;; Does work > ((lambda (x) x) 1) ;; Also works > (funcall (some-func) 1) 

Hope this makes sense!

+7
source share
4 answers

This is a good question, and one where Common Lisp can be quite confusing. The fact is, for historical reasons, Common Lisp has two namespaces: one for functions and the other for values. For this to happen, there are two different evaluation rules for the position of the head of the function application, and for the rest, the first will evaluate the symbol as the name of the function, and the second will evaluate the symbol as a reference to a variable. Obviously, when the value is actually a function, for example, if you write a mapcar function, you want to do something like

 (defun my-mapcar (fl) (if (null l) '() (cons (f (car l)) (my-mapcar f (cdr l))))) 

but this will not work - he will complain about f as an unknown function. For these cases, there is a special function called funcall that receives the function and argument for the function and will use this function as usual - and since funcall is a simple function, its arguments are evaluated as usual (as values). Thus, the above should be fixed using it:

 (defun my-mapcar (fl) (if (null l) '() (cons (funcall f (car l)) (my-mapcar f (cdr l))))) 

As you probably suspect now, there are mirror cases - where you want to evaluate something as a function, rather than as a value. For example, this does not work:

 (my-mapcar 1+ '(1 2 3)) 

because it refers to the variable 1+ , and not to the function. For these cases, there is a special form called function , which evaluates its contents as a function and returns it as a value:

 (my-mapcar (function 1+) '(1 2 3)) 

and it can be shortened with #' :

 (my-mapcar #'1+ '(1 2 3)) 

This is not the end of this story - to give a few examples:

  • in some cases, a simple quoted name may work as a function - for example, '1+ in the last example works - but it’s a kind of hack that can only see globally connected names, so #' almost always better

  • a similar hack can be used with lambda - so you can use (my-mapcar '(lambda (x) (1+ x)) '(1 2 3)) , in fact, you can use (list 'lambda '(x) '(1+ x)) , which is even worse (and IIRC, not portable), but using (lambda (x) (1+ x)) works because it is implicitly wrapped in #' (try expanding the lambda form as a macro, and you will see it). The hack associated with it allows you to use the lambda expression as the head of a function application (which is one of the things you tried).

  • let , etc. bind local values, and in some cases you want to bind local functions instead - new binding constructions appear for this: flet and labels

If all this looks strange and / or overly complicated, then you are not alone. This is one of the main differences between Common Lisp and Scheme. (The difference then leads to changes in common idioms in both languages: circuit code tends to use higher-order functions much more often than Common Lisp. As usual, with such religious questions, some people argue in favor of what the CL does, arguing that functions higher order are confusing, so they like the explicit reminder in the code.)

+6
source

((lambda (x) ...) ...) is hard code in appraiser rules. He does not evaluate the first element in the form and uses the result as a general case. It's normal that you should use funcall or apply to call a function that is the result of evaluating some other form.

+4
source

The reason Common Lisp does not allow a function that returns a lambda to be the first element in an expression is related to the difference between Lisp -1 and Lisp -2 .

If Common Lisp is allowed ((some-func) 1) equivalent to (funcall (some-func) 1) , then this can be taken as inconsistent to prevent say (let ((f #'some-func)) (f 1)) , and not require (funcall f 1) .

+2
source

In fact, there is a very good justification for supporting such forms: they are ambiguous. Consider the way function names are defined in Common Lisp:

function name n. 1. (in the environment) A symbol or list (setf symbol) , which is the name of a function in this environment. 2. A symbol or list (setf symbol) .

Given this, how a form should look like:

 ((setf car) 10 x) 

If this set x car matches the value 10 or should execute the form (setf car) (which would be an error) and try to use its return value as a function for a call with arguments 10 and x ? General Lisp does not indicate behavior, and it is not at all clear to me that this is a bad choice. In the end, as far as I can see, nothing in the standard allows matching implementations from expanding the definition of valid forms to support a wider range of operator names (therefore, special set-casing functions would not really help here either).

+1
source

All Articles