Zelphir Kaltstahl <zelphirkaltstahl@posteo.de> writes:
I am not sure (let ...) is a correct wrapper for noweb included source blocks.
What, if I write a (define ...) in my source block and want to use that source
block via noweb in another source block? Expected behavior I think would be to
be able to access those variables in other source blocks, since they are defined
on a top level in an earlier source block, but if they are wrapped in a (let
...), that would make them only available in the (let ...)? It seems to me, that
the simple wrapping with a (let ...) might not be the right thing to do. Testing
that:
~~~~START~~~~
#+name: scheme-defs
#+begin_src scheme :eval query-export :noweb strip-export :session myguile
:results output replace drawer :var x=1 :var y=2
(define a x)
(define b y)
#+end_src
#+name: scheme-time
#+begin_src scheme :eval query-export :noweb strip-export :session myguile
:results output replace drawer
<<scheme-defs>>
(simple-format #t "~a ~a\n" a b)
#+end_src
~~~~~END~~~~~
Indeed, that also does not work.
I just checked ob-C, ob-shell, ob-emacs-lisp, and ob-clojure.
Non-lisps appear to assign the values globally.
In contrast, all the lisp babel backends are using let-bindings.
Considering the existing inconsistency, and the raised bug I'd be in
favor of making variable assignments global in all the lisp babel
backends.
The only possible exception is ob-emacs-lisp. Executing elisp code is
done in current Elisp session and thus using global variable assignments
may be tricky. Unless we juggle with multiple obarrays.
I guess I did never hit this problem earlier, because I "oursourced" my imports
and in imports I do not need any :var header arguments.
I've asked on the Guile IRC channel and something interesting is the case here
(thanks for clearing it up flatwhatson!) and I understand it as follows:
Imports inside (let ...) work. It is just that let-values is a macro and macros
are expanded before execution time. However, Guile gets to the body of the
wrapping (let ...) at execution time. That means, that when Guile gets to
evaluate the body of the let, it does not expand the let-values, because it is
already at execution time and no longer at macro expansion time. The import
might import the let-values form, or might not, but it is already too late to
expand the (let-values ...).
So, apparently using `let' is not universally safe in Guile.
OK, the question is though, whether org should wrap anything in a (let ...) at
all. During discussion on the Guile IRC, some points against let-wrapping were
brought up:
(1) The presence of a :var header argument currently determines, whether the
code in the source block is wrapped with a (let ...). One argument for that was,
that this way the variables do not leak. But this also decides, whether other
things leak. For example (import ...) or (define ...). Should :var decide,
whether bindings created with (define ...) are visible in other source blocks
including the source block with the :var header arguments? It seems like a
responsibility :var should not have and definitely is unexpected for the user.
This is something Guile-specific. In Elisp, let-binding still allows
`defun' or `defvar'.