emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* source blocks DAG evaluation
@ 2021-03-22  2:00 c4t0
  2021-03-22  2:44 ` Thomas S. Dye
  0 siblings, 1 reply; 3+ messages in thread
From: c4t0 @ 2021-03-22  2:00 UTC (permalink / raw)
  To: emacs-orgmode


Hi,

Is it possible to have a dependency hierarchy of source blocks?

i.e.: in C, if you use libA from a compilation unit and that library needs libB, you don't need to include it in main.c

-> main.c
#include "libB.h"
-> libB.c
#include "libA.h"

you don't need to:
-> main.c
#include "libB.h"
#include "libA.h"

because library headers are closed under inclusion.

I haven't succeeded in doing the same in org-mode. Even after populating org-babel-library-of-babel.

Using #+call just doesn't work. Using :var is better, evaluates all, but there appears to lack session support, it doesn't check for cycles and it feels a little hacky

With #+call I need to do it like this:

#+name: libA
#+begin_src scheme :results none
(define hi "hello")
#+end_src

#+name: libB
#+begin_src scheme :results none
(define greetings (string-append hi ", " "to all the people!"))
#+end_src

here is my "main" I need to C-c C-c in each #+call line and write the :session that the code block uses in each one, and do it in the correct order. If I C-c C-c in libB first it won't eval because 'hi' is not defined.

#+call: libB[:session example]
#+call: libA[:session example]
#+begin_src scheme :session example :results output
(display greetings)
#+end_src

source blocks can be #+call(ed) but aren't closed under #+call (a source block can be called but then the callee won't) 

instead I would like to :

#+name: libA
#+begin_src scheme :results none
(define hi "hello")
#+end_src

#+call: libA
#+name: libB
#+begin_src scheme :results none
(define greetings (string-append hi ", " "to all the people!"))
#+end_src

#+call: libB
#+begin_src scheme :session example :results output
(display greetings)
#+end_src

- there shouldn't be needed to C-c C-c in the #+call line, evaluating the source block alone should suffice.
- there shouldn't be a need to write the :session
  - it should use the session of the user evaled block, unless specified otherwise

In the other hand, using :var with a dummy variable:

#+name: libA
#+begin_src scheme :results none
(define hi "hello")
#+end_src

#+name: libB
#+begin_src scheme :results none :var _=libA
(define greetings (string-append hi ", " "to all the people!"))
#+end_src

#+HEADER: :var _=libB
#+begin_src scheme :session example :results output 
(display greetings)
#+end_src

It evals libA then libB and finally the (display greetings) code.
But it fails, because the :session example is ignored. Even if I add a :session example to every source block (which would be really bad, sessión must be decided by the consumer) it doesn't work. I think that is because :var expects a value, so it just opens a new session to evaluate code every time.

Besides if there are any dependency cycles, it just fails with: Lisp nesting exceeds ‘max-lisp-eval-depth’

So if I'm right and there is not an implemented way to do this, how can we do it? Adding session support for :var? constructing a DAG of #+calls and then evaluating in order? maybe using a new header?

COD.


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: source blocks DAG evaluation
  2021-03-22  2:00 source blocks DAG evaluation c4t0
@ 2021-03-22  2:44 ` Thomas S. Dye
  2021-03-22 13:41   ` c4t0
  0 siblings, 1 reply; 3+ messages in thread
From: Thomas S. Dye @ 2021-03-22  2:44 UTC (permalink / raw)
  To: emacs-orgmode

Aloha c4to,

I would be tempted to use noweb expansion here.

#+name: libB
#+begin_src scheme :results none :noweb yes
<<libA>>
(define greetings (string-append hi ", " "to all the people!"))
#+end_src

#+begin_src scheme :session example :results output :noweb yes
<<libB>>
(display greetings)
#+end_src

Does this do what you want?

All the best,
Tom

c4t0 writes:

> Hi,
>
> Is it possible to have a dependency hierarchy of source blocks?
>
> i.e.: in C, if you use libA from a compilation unit and that 
> library needs libB, you don't need to include it in main.c
>
> -> main.c
> #include "libB.h"
> -> libB.c
> #include "libA.h"
>
> you don't need to:
> -> main.c
> #include "libB.h"
> #include "libA.h"
>
> because library headers are closed under inclusion.
>
> I haven't succeeded in doing the same in org-mode. Even after 
> populating org-babel-library-of-babel.
>
> Using #+call just doesn't work. Using :var is better, evaluates 
> all, but there appears to lack session support, it doesn't check 
> for cycles and it feels a little hacky
>
> With #+call I need to do it like this:
>
> #+name: libA
> #+begin_src scheme :results none
> (define hi "hello")
> #+end_src
>
> #+name: libB
> #+begin_src scheme :results none
> (define greetings (string-append hi ", " "to all the people!"))
> #+end_src
>
> here is my "main" I need to C-c C-c in each #+call line and 
> write the :session that the code block uses in each one, and do 
> it in the correct order. If I C-c C-c in libB first it won't 
> eval because 'hi' is not defined.
>
> #+call: libB[:session example]
> #+call: libA[:session example]
> #+begin_src scheme :session example :results output
> (display greetings)
> #+end_src
>
> source blocks can be #+call(ed) but aren't closed under #+call 
> (a source block can be called but then the callee won't)
>
> instead I would like to :
>
> #+name: libA
> #+begin_src scheme :results none
> (define hi "hello")
> #+end_src
>
> #+call: libA
> #+name: libB
> #+begin_src scheme :results none
> (define greetings (string-append hi ", " "to all the people!"))
> #+end_src
>
> #+call: libB
> #+begin_src scheme :session example :results output
> (display greetings)
> #+end_src
>
> - there shouldn't be needed to C-c C-c in the #+call line, 
> evaluating the source block alone should suffice.
> - there shouldn't be a need to write the :session
>   - it should use the session of the user evaled block, unless 
>   specified otherwise
>
> In the other hand, using :var with a dummy variable:
>
> #+name: libA
> #+begin_src scheme :results none
> (define hi "hello")
> #+end_src
>
> #+name: libB
> #+begin_src scheme :results none :var _=libA
> (define greetings (string-append hi ", " "to all the people!"))
> #+end_src
>
> #+HEADER: :var _=libB
> #+begin_src scheme :session example :results output
> (display greetings)
> #+end_src
>
> It evals libA then libB and finally the (display greetings) 
> code.
> But it fails, because the :session example is ignored. Even if I 
> add a :session example to every source block (which would be 
> really bad, sessión must be decided by the consumer) it doesn't 
> work. I think that is because :var expects a value, so it just 
> opens a new session to evaluate code every time.
>
> Besides if there are any dependency cycles, it just fails with: 
> Lisp nesting exceeds ‘max-lisp-eval-depth’
>
> So if I'm right and there is not an implemented way to do this, 
> how can we do it? Adding session support for :var? constructing 
> a DAG of #+calls and then evaluating in order? maybe using a new 
> header?
>
> COD.


--
Thomas S. Dye
https://tsdye.online/tsdye


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: source blocks DAG evaluation
  2021-03-22  2:44 ` Thomas S. Dye
@ 2021-03-22 13:41   ` c4t0
  0 siblings, 0 replies; 3+ messages in thread
From: c4t0 @ 2021-03-22 13:41 UTC (permalink / raw)
  To: Thomas S. Dye; +Cc: emacs-orgmode


Hello Thomas!

That is fairly nice, thanks! I can use it for the moment.

I see a minor problem, if you export it, the last block will show all the
code and that may be redundant or undesired. But that can be solved
fiddling with exporting options or code I guess. btw, using :noweb no-export,
just leaves the <<lib*>> sintax, so it's not what I want. 

In this sense it also doesn't do any cycle resolving, when a there is
one it just fails with
"org-at-heading-p: Variable binding depth exceeds max-specpdl-size"

That may be ok, you shouldn't have cycles. But there is a more realist
problem, you *can* have, diamonds dependencies.

Say
libA -> libB -> libD -> main
     \> libC /

If you <<libD>> from main, you will get two copies of libA source
code. That may be a problem in some languages and it's definitely bad at
export time.

The good about noweb expansion is that you can ignore the problem with
the sessions all together and it will work with things that doesn't have
sessions at all (now I remember a home work in assembler that I did in
org-mode with noweb expansion ...)

So, maybe if I try to improve anything, to address this issue, maybe is
the code for noweb expansion? Maybe some options to conditional output
the template expansion or just remove the <<*>> calls.  I don't know if
the semantics of what I want go along a template expansion ... I have
the feeling that we might need something particular for this, like a
(require ...) for org-mode source blocks.

thanks!

COD.

"Thomas S. Dye" <tsd@tsdye.online> writes:

> Aloha c4to,
>
> I would be tempted to use noweb expansion here.
>
> #+name: libB
> #+begin_src scheme :results none :noweb yes
>
> <<libA>>
> (define greetings (string-append hi ", " "to all the people!"))
> #+end_src
>
> #+begin_src scheme :session example :results output :noweb yes
> <<libB>>
> (display greetings)
> #+end_src
>
> Does this do what you want?
>
> All the best,
> Tom
>
> c4t0 writes:
>
>> Hi,
>>
>> Is it possible to have a dependency hierarchy of source blocks?
>>
>> i.e.: in C, if you use libA from a compilation unit and that 
>> library needs libB, you don't need to include it in main.c
>>
>> -> main.c
>> #include "libB.h"
>> -> libB.c
>> #include "libA.h"
>>
>> you don't need to:
>> -> main.c
>> #include "libB.h"
>> #include "libA.h"
>>
>> because library headers are closed under inclusion.
>>
>> I haven't succeeded in doing the same in org-mode. Even after 
>> populating org-babel-library-of-babel.
>>
>> Using #+call just doesn't work. Using :var is better, evaluates 
>> all, but there appears to lack session support, it doesn't check 
>> for cycles and it feels a little hacky
>>
>> With #+call I need to do it like this:
>>
>> #+name: libA
>> #+begin_src scheme :results none
>> (define hi "hello")
>> #+end_src
>>
>> #+name: libB
>> #+begin_src scheme :results none
>> (define greetings (string-append hi ", " "to all the people!"))
>> #+end_src
>>
>> here is my "main" I need to C-c C-c in each #+call line and 
>> write the :session that the code block uses in each one, and do 
>> it in the correct order. If I C-c C-c in libB first it won't 
>> eval because 'hi' is not defined.
>>
>> #+call: libB[:session example]
>> #+call: libA[:session example]
>> #+begin_src scheme :session example :results output
>> (display greetings)
>> #+end_src
>>
>> source blocks can be #+call(ed) but aren't closed under #+call 
>> (a source block can be called but then the callee won't)
>>
>> instead I would like to :
>>
>> #+name: libA
>> #+begin_src scheme :results none
>> (define hi "hello")
>> #+end_src
>>
>> #+call: libA
>> #+name: libB
>> #+begin_src scheme :results none
>> (define greetings (string-append hi ", " "to all the people!"))
>> #+end_src
>>
>> #+call: libB
>> #+begin_src scheme :session example :results output
>> (display greetings)
>> #+end_src
>>
>> - there shouldn't be needed to C-c C-c in the #+call line, 
>> evaluating the source block alone should suffice.
>> - there shouldn't be a need to write the :session
>>   - it should use the session of the user evaled block, unless 
>>   specified otherwise
>>
>> In the other hand, using :var with a dummy variable:
>>
>> #+name: libA
>> #+begin_src scheme :results none
>> (define hi "hello")
>> #+end_src
>>
>> #+name: libB
>> #+begin_src scheme :results none :var _=libA
>> (define greetings (string-append hi ", " "to all the people!"))
>> #+end_src
>>
>> #+HEADER: :var _=libB
>> #+begin_src scheme :session example :results output
>> (display greetings)
>> #+end_src
>>
>> It evals libA then libB and finally the (display greetings) 
>> code.
>> But it fails, because the :session example is ignored. Even if I 
>> add a :session example to every source block (which would be 
>> really bad, sessión must be decided by the consumer) it doesn't 
>> work. I think that is because :var expects a value, so it just 
>> opens a new session to evaluate code every time.
>>
>> Besides if there are any dependency cycles, it just fails with: 
>> Lisp nesting exceeds ‘max-lisp-eval-depth’
>>
>> So if I'm right and there is not an implemented way to do this, 
>> how can we do it? Adding session support for :var? constructing 
>> a DAG of #+calls and then evaluating in order? maybe using a new 
>> header?
>>
>> COD.
>
>
> --
> Thomas S. Dye
> https://tsdye.online/tsdye


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-03-22 13:59 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-03-22  2:00 source blocks DAG evaluation c4t0
2021-03-22  2:44 ` Thomas S. Dye
2021-03-22 13:41   ` c4t0

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).