2

I'd like to use a function reference in place of a lambda, however the lambda in question captures a lot of locally scoped vars declared in an enclosing let.

For example:

(let ((x 1)(y 2)(z 3)
      (l '(1 2 3 4 5 6 7 8 9)))
  (mapcar (lambda (i) (list x y z i)) l))

Let's assume the entire thing is way more complex, but is similar in essence. I'd want to move the lambda out to a defun, like this.

(defun fn (i)
  "Function to use I in context."
  (list x y z i))

(let ((x 1)(y 2)(z 3)
      (l '(1 2 3 4 5 6 7 8 9)))
  (mapcar 'fn l))

This doesn't work, x y z are void (of course.)

Is there a way to make this possible? (Assume Emacs versions which allow lexical scope.)

2 Answers 2

3

Use flet:

(let ((x 1)(y 2)(z 3)
      (l '(1 2 3 4 5 6 7 8 9)))
  (flet ((fn (i)
             (list x y z i)))
    (mapcar #'fn l)))
10
  • Thank you! Am I correct in assuming that lexical binding is required for this to work as expected?
    – ocodo
    Commented Sep 5, 2022 at 6:06
  • 1
    No, it works fine with dynamic bindings.
    – db48x
    Commented Sep 5, 2022 at 9:06
  • Just noticed there's a pretty big problem with this. The flet has to be included in the let body. So the goal, which was to move the function body away somewhere else hasn't really been met.
    – ocodo
    Commented Sep 5, 2022 at 14:23
  • 1
    It’s called lexical scope for a reason. The scope is defined by where the lexemes (as it were) of the definition are. If you want it to have access to the variables inside the function, it has to be inside the function too.
    – db48x
    Commented Sep 5, 2022 at 15:09
  • 1
    What else do you want? There are a lot of general rules of thumb, such as breaking large functions into smaller, more self–contained pieces, that can help.
    – db48x
    Commented Sep 5, 2022 at 16:10
1

Ok, so the answers I'm looking for are along the lines of "is this possible", i.e. can scope state be shared to a function arbitrarily.

These two cover the topic effectively.

The fact that the internal structure of a closure is "exposed" to the rest of the Lisp world is considered an internal implementation detail. For this reason, we recommend against directly examining or altering the structure of closure objects.

Effectively, the answer is NO, it can't be done (and this goes for relying on internal implementation details in general). The state in use by the lambda in this case, needs to be passed via a conventional method, i.e. parameters, a list structure, etc.

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.