Hi,

I have been using org-mode for almost three years and I loved it so much that I 
started working on a literate programming tool based on it.
One particular technique that I use is having multiple named code blocks, like 
so:

#+begin_src perl :noweb yes :results output
<<Before foo>>
sub foo {
<<In foo>>
}
foo;
#+end_src

#+name: Before foo
#+begin_src perl
print "Before foo definition.\n";
#+end_src

#+name: Before foo
#+begin_src perl
my $value = 'Inside foo call';
#+end_src

#+name: In foo
#+begin_src perl
print $value . "\n";
#+end_src

This technique worked without issue until I recently updated Emacs and org-mode 
with it.
I do not know the version of org-mode I was using before, but this was with 
Emacs 26.3 and I upgraded to Emacs 27.1 with org-mode 9.4 according to the 
information at the top of elpa/org-plus-contrib-20201116/org.el.

Before the update, the code block after expansion (obtained with 
org-babel-expand-src-block via the C-c C-v C-v shortcut) looked like this:
#+begin_src perl
print "Before foo definition.\n";
my $value = 'Inside foo call';
sub foo {
print $value . "\n";
}
foo;
#+end_src

Now the definition of $value is gone:
#+begin_src perl
print "Before foo definition.\n";
sub foo {
print $value . "\n";
}
foo;
#+end_src

I have looked at the info manual so I realise that according to "15.2 Structure 
of Code Blocks": "For duplicate names, Org mode’s behavior is undefined" so it 
follows that:
- Up until now, I was incorrectly assuming that duplicated named code blocks 
were supposed to result in them being concatenated in the noweb expansion phase.
- This is not a bug report, org-mode is working as documented.

I find this technique pretty useful for two reasons:
1. Importing packages right when they are needed.
2. Declaring variables in a broader scope than the one where they are first 
used.
Here is an short example of this kind of situation:

#+begin_src perl :noweb no
# Expansion of <<Variable declarations>>:
my $even_counter = 0;
my @array = (4, 8, 15, 16, 23, 42);
# A
# lot
# of
# other
# code
# [...]
foreach my $n (@array) {
# Expansion of <<Array processing>>:
$even_counter++ if $n % 2 == 0;
}
print "$even_counter";
#+end_src

In this example, $even_counter could not have been declared on the spot.
Of course, this example is too basic to really paint the usefulness of this 
technique but an actual example would be too long, the goal here is just to 
explain the general idea.

With all that being said I would suggest to define the behaviour for multiple 
named code blocks as resulting in a concatenation of the code blocks, in the 
order of their apparition.
If you agree about defining this behaviour but think adapting the 
implementation is of low priority, I could try to implement it myself though I 
have little experience in emacs-lisp development beyond basic configuration and 
no experience whatsoever in contributing to FOSS, but I'm willing to start in 
both domains.

Best regards,
Félix

Reply via email to