1

Evaluate the following code:

(package-initialize)
(unless package-archive-contents (package-refresh-contents))
(package-install-selected-packages)

(org-babel-do-load-languages
 'org-babel-load-languages '((emacs-lisp . t)))

(defun test () result) 
(add-hook 'org-babel-after-execute-hook 'test)

Then in org-mode, try to evaluate the block

#+begin_src emacs-lisp
0
#+end_src

In the *Messages* buffer, you should see run-hooks: Symbol’s value as variable is void: result.

result is bound locally within org-babel-execute-src-block. When I run org-babel-execute-src-block, test is not able to "see" result.

However, if I copy the source code defining org-babel-execute-src-block into the org buffer and evaluate it. Then when I run the src block, result is visible to test.

phil's comment pointed me to the fact that org-babel-execute-src-block is using lexical binding.

What is going on here? It seems that the bindings are associated with the file in which the defun was evaluated. But test is dynamically scoped, and so I would expect it to be able to "see" results. Perhaps if a function f using dynamic binding is executed within a function g using lexical binding, f won't be able to "see" bindings made in g.

4
  • Did you copy that function to a different file, or is that function definition only ever being evaluated in the original org library? (If you copied it elsewhere, you probably haven't matched the file-local lexical-binding of the original file in your custom file.)
    – phils
    Jan 22 at 22:50
  • Anyhow, "autoloaded functions" aren't different wrt scoping rules. If you call a function which only exists as an (autoload...) declaration, then the required file is loaded, and all the functions in that file are defined under the scoping rules for that file (based on the file-local lexical-binding declaration, if any, in that file's first line).
    – phils
    Jan 22 at 23:11
  • The top line of ob-core.el (where org-babel-execute-src-block is defined) contains lexical-binding: t. Presumably, org-babel-execute-src-block has lexical binding, but after I copy and re-evaluate the definition (with C-x C-e) it has dynamic binding. This doesn't quite explain why my-org-babel-after-execute-show-graphics cannot "see" result-params. Perhaps if a function f using dynamic binding is executed within a function g using lexical binding, f won't be able to "see" bindings made in g
    – user615536
    Jan 23 at 1:39
  • 1
    I have rewritten the question to make it simpler and more reproducible. I hope it will be easier to follow :)
    – user615536
    Jan 23 at 2:10

1 Answer 1

1

In your example, result is a let-bound lexical variable in the org-babel-execute-src-block function (which is defined in ob-core.el which uses -*- lexical-binding: t; -*-).

This means that result is visible only to the code of org-babel-execute-src-block within the let form. This is what "lexical scope" means -- only the code which is written within that let form can see it1.

The definition/code of your test function is not within that lexical scope, so no result variable exists there.

Conversely, variables with dynamic scope are globally visible until the form which binds them has completed. Dynamic variables must be defined with defvar (or similar) in order to be recognised as dynamic by code which uses lexical-binding.

In files which do not use lexical-binding, OTOH, all variables are dynamic. So if you redefine org-babel-execute-src-block under dynamic binding, the let-bindings in the new function will be dynamic variables, and hence your test function sees a value for result.


1 Notwithstanding any macro calls within the lexical scope, in which case the macro itself is defined elsewhere, but the expansion is generating code within the same lexical scope as the call (replacing the call to that macro) before the function is actually defined.

6
  • You should mention that lexical-binding has a default value of nil, so when the code is evaluated from inside the org file then it is evaluated using the dynamic scope rules.
    – db48x
    Jan 23 at 2:21
  • That makes sense. Except that when I copy and evaluate the code defining org-babel-execute-src-block into a buffer other than the org buffer, results is still invisible to test. Yet if it is copied and evaluated in the same org buffer as runs the src block, test can see it.
    – user615536
    Jan 23 at 2:24
  • Which other buffer? Depending on which version of Emacs you're using, some lisp buffers (notably *scratch*) may default to lexical-binding. Check C-h v lexical-binding within that buffer.
    – phils
    Jan 23 at 2:32
  • *scratch* has lexical-binding equal to t
    – user615536
    Jan 23 at 2:37
  • 1
    Yes, when you redefine the function, it is defined using the scoping rules for the file/buffer in which you have evaluated the function definition. If you copy it to *scratch* and evaluate it, it will use lexical binding. If you copy it to a lisp buffer using dynamic scope and redefine it there, it will use dynamic scope.
    – phils
    Jan 23 at 2:42

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.