2

I'm following Paul Graham's book On Lisp, where Section 5.7 says "A sharp-quoted lambda-expression is a constant, but a call to a constructor function will be evaluated at run time."

This reminds me of Lisp's general principle of code-data duality.

Can someone please help explain how a function is a constant when represented in computer memory? Sure it's just a set of instructions, but the functions still take inputs, so doesn't that mean the actual execution during run-time isn't constant?

2 Answers 2

2

What is meant is that a function is a constant object which cannot be modified. Like a shovel: you cannot change the shovel, but you can dig many different ditches with it. Similarly, you cannot change the function, but you can apply it to different arguments and get different values.

Incidentally, this is not necessarily always the case for all implementations. E.g., in CLISP:

(defun f(x) (+ x 10))
(compile 'f)
(f 5)
==> 15
(disassemble #'f)

Disassembly of function F
(CONST 0) = 10
1 required argument
0 optional arguments
No rest parameter
No keyword parameters
4 byte-code instructions:
0     (CONST&PUSH 0)                      ; 10
1     (LOAD&PUSH 2)
2     (CALLSR 2 55)                       ; +
5     (SKIP&RET 2)

Pretty straightforward, huh?

now, if you use internal functionality of CLISP to modify its vector of constants and replace 10 with something else, you will change the function's behavior:

(setf (sys::closure-const #'f 0) 42)
(f 7)
==> 49

This is similar to running a C program under a debugger and modifying local variables.

See also Why does an elisp local variable keep its value in this case? and Why does this function return a different value every time?

PS. Please note that doing this may lead to hard crashes (segfaults). Beware.

Sign up to request clarification or add additional context in comments.

2 Comments

so basically a function is a constant once translated into assembly code?
yes, it should be treated as such. however, there are underhanded ways to defeat that, and one should not do those things.
2

Paul Graham talks of constructors as functions which return new function objects. Not just simple function objects, but closures -> a function object and a binding environment. Thus a closure might be allocated at runtime, when a constructor call is evaluated at runtime. In his example he also shows that closures can sometimes also be allocated at read time - though that may have problems like compiling files and dumping function objects - which does not work.

Simple lambda expressions are pre-computed when compiled and thus may not see additional allocation at runtime to exist.

3 Comments

I've yet to find a satisfactory (for my current understanding) definition of closure -- can you please help explain it? I know closures get created when free variables are involved. But are closures themselves functions? Or environments? Or data?
a closure is a function object. So you can call it as a function. For example via FUNCALL or APPLY. The closure remembers the state of the functions lexically bound variables. (funcall (let ((a 10)) (lambda (x) (+ a x))) 32) -> 42 The lambda form in this example evaluates to a closure.
!!! That explains Paul Graham's On Lisp Figure 6.5 page 79. I've been chewing on that one for days! Thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.