Hi Felix,

You need to use the noweb-ref header argument instead of #+NAME, then the
block are all concatenated on output.

Best,
--Diego


On Sat, 28 Nov 2020 at 23:35, mooss <mo...@protonmail.com> wrote:

> 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