Add example.org and an accompanying picture.
This commit is contained in:
parent
576f204846
commit
e8af2055e6
2 changed files with 372 additions and 0 deletions
53
example/dots/exampleBQNp7Z.svg
Normal file
53
example/dots/exampleBQNp7Z.svg
Normal file
|
@ -0,0 +1,53 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 2.43.0 (0)
|
||||
-->
|
||||
<!-- Title: G Pages: 1 -->
|
||||
<svg width="307pt" height="270pt"
|
||||
viewBox="0.00 0.00 307.32 269.60" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 265.6)">
|
||||
<title>G</title>
|
||||
<polygon fill="white" stroke="transparent" points="-4,4 -4,-265.6 303.32,-265.6 303.32,4 -4,4"/>
|
||||
<!-- node0 -->
|
||||
<g id="node1" class="node">
|
||||
<title>node0</title>
|
||||
<ellipse fill="none" stroke="black" cx="272.32" cy="-243.6" rx="27" ry="18"/>
|
||||
<text text-anchor="middle" x="272.32" y="-239.9" font-family="Times-Roman" font-size="14.00">c</text>
|
||||
</g>
|
||||
<!-- node1 -->
|
||||
<g id="node2" class="node">
|
||||
<title>node1</title>
|
||||
<ellipse fill="none" stroke="black" cx="27" cy="-214.2" rx="27" ry="18"/>
|
||||
<text text-anchor="middle" x="27" y="-210.5" font-family="Times-Roman" font-size="14.00">b</text>
|
||||
</g>
|
||||
<!-- node0->node1 -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>node0->node1</title>
|
||||
<path fill="none" stroke="black" d="M245.6,-240.39C198.41,-234.74 100.85,-223.05 53.69,-217.4"/>
|
||||
</g>
|
||||
<!-- node2 -->
|
||||
<g id="node3" class="node">
|
||||
<title>node2</title>
|
||||
<ellipse fill="none" stroke="black" cx="175.3" cy="-18" rx="27" ry="18"/>
|
||||
<text text-anchor="middle" x="175.3" y="-14.3" font-family="Times-Roman" font-size="14.00">a</text>
|
||||
</g>
|
||||
<!-- node2->node0 -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>node2->node0</title>
|
||||
<path fill="none" stroke="black" d="M182.75,-35.33C199.61,-74.53 240.78,-170.25 260.89,-217.01"/>
|
||||
<polygon fill="black" stroke="black" points="257.68,-218.4 264.84,-226.21 264.11,-215.64 257.68,-218.4"/>
|
||||
</g>
|
||||
<!-- node2->node1 -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>node2->node1</title>
|
||||
<path fill="none" stroke="black" d="M162.91,-34.39C136.79,-68.96 75.93,-149.46 45.3,-189.99"/>
|
||||
<polygon fill="black" stroke="black" points="42.49,-187.91 39.25,-198 48.07,-192.13 42.49,-187.91"/>
|
||||
</g>
|
||||
<!-- node2->node2 -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>node2->node2</title>
|
||||
<path fill="none" stroke="black" d="M200.75,-24.69C211.33,-25.15 220.3,-22.92 220.3,-18 220.3,-13.08 211.33,-10.85 200.75,-11.31"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
319
example/example.org
Normal file
319
example/example.org
Normal file
|
@ -0,0 +1,319 @@
|
|||
#+TITLE: Examples of usage of =dds=
|
||||
|
||||
#+PROPERTY: header-args:racket :prologue "#lang racket\n(require graph (file \"~/Candies/prj/racket/dds/networks.rkt\") (file \"~/Candies/prj/racket/dds/utils.rkt\"))"
|
||||
|
||||
* Introduction
|
||||
This document shows some examples of usage of the modules in =dds=
|
||||
with Org-mode. It relies on [[https://github.com/hasu/emacs-ob-racket][emacs-ob-racket]].
|
||||
|
||||
The [[intro][following section]] describes how Org-mode can interact with
|
||||
Racket, and how this interaction can be used for a fluid workflow
|
||||
with =dds=. In particular, the code block =munch-table= is [[tabread][defined]]
|
||||
in this section.
|
||||
|
||||
The subsequent sections show off some the functionalities of the
|
||||
submodules of =dds=.
|
||||
|
||||
* Org-mode, Racket, and =dds= <<intro>>
|
||||
** Importing a module from file
|
||||
:PROPERTIES:
|
||||
:header-args:racket: :prologue "#lang racket\n(require (file \"~/Candies/prj/racket/dds/networks.rkt\"))"
|
||||
:END:
|
||||
|
||||
To require the modules from the files of =dds=, you can use the
|
||||
following code (I only reset the prelude here because I set at the
|
||||
top of this file):
|
||||
|
||||
#+BEGIN_SRC racket :results output :prologue ""
|
||||
#lang racket
|
||||
(require (file "~/Candies/prj/racket/dds/networks.rkt"))
|
||||
(require (file "~/Candies/prj/racket/dds/utils.rkt"))
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
|
||||
Note that this code will not work with =:results value=. I think it
|
||||
is because in this case the code is not really evaluated at top
|
||||
level.
|
||||
|
||||
These initialisation lines can be put into the prologue of every
|
||||
code block in a subtree by setting =:prologue= via
|
||||
=:header-args:racket:= in the properties drawer. Check out the
|
||||
properties drawer of this section for an example.
|
||||
|
||||
Alternatively, this property can be set via a =#+PROPERTY= line at
|
||||
the top the file. For example, this file has such a line. Whenever
|
||||
this property line changes, refresh the setup of the file by hitting
|
||||
=C-c C-c= on the property line. This will update the prologue for
|
||||
all racket code blocks.
|
||||
|
||||
Finally, you can also set =:prologue= (and other properties with
|
||||
long values) in the following way:
|
||||
|
||||
#+HEADER: :prologue "#lang racket\n(require (file \"~/Candies/prj/racket/dds/networks.rkt\"))"
|
||||
#+BEGIN_SRC racket :results output drawer
|
||||
(st '((a . 1)))
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:RESULTS:
|
||||
'#hash((a . 1))
|
||||
:END:
|
||||
|
||||
** Output formats for results of evaluation of code blocks
|
||||
[[https://orgmode.org/manual/Results-of-Evaluation.html#Results-of-Evaluation][This section]] of the Org manual describes various different formats
|
||||
for presenting the results of code blocks. I find the following
|
||||
three particularly useful as of [2020-02-22 Sat]: =output=, =list=,
|
||||
and =table=.
|
||||
|
||||
The =output= result format is the simplest and the most natural
|
||||
ones. It works as if the code block were inserted into a module
|
||||
which would then be evaluated.
|
||||
|
||||
#+BEGIN_SRC racket :results output drawer
|
||||
(println "This is the first line of output.")
|
||||
(println (+ 1 2))
|
||||
(println "This the third line of output.")
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:RESULTS:
|
||||
"This is the first line of output."
|
||||
3
|
||||
"This the third line of output."
|
||||
:END:
|
||||
|
||||
The =list= result format typesets the result of the last line in the
|
||||
code block as a list:
|
||||
#+BEGIN_SRC racket :results list
|
||||
'(1 "hello" (and x y))
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
- 1
|
||||
- "hello"
|
||||
- (and x y)
|
||||
|
||||
Note how nested lists are not recursively shown as nested Org-mode
|
||||
lists.
|
||||
|
||||
For some reason, the =list= output format does not work with the
|
||||
result drawer:
|
||||
#+BEGIN_SRC racket :results list drawer
|
||||
'(1 "hello" (and x y))
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:RESULTS:
|
||||
- (1 "\"hello\"" (and x y))
|
||||
:END:
|
||||
|
||||
Finally, the =table= result format typesets the output as a table:
|
||||
#+BEGIN_SRC racket :results table drawer
|
||||
'((a . #t) (b . #f))
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:RESULTS:
|
||||
| a | #t |
|
||||
| b | #f |
|
||||
:END:
|
||||
|
||||
This is clearly very useful for printing states (and hash tables,
|
||||
more generally):
|
||||
|
||||
#+BEGIN_SRC racket :results table drawer
|
||||
(st '((a . 1) (b . #f) (c . "hello")))
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:RESULTS:
|
||||
| a | 1 |
|
||||
| b | #f |
|
||||
| c | "hello" |
|
||||
:END:
|
||||
|
||||
*** A note about printing update function forms
|
||||
Automatic table typesetting may go in the way of readability for
|
||||
hash tables whose values are lists, as the following example shows:
|
||||
|
||||
#+BEGIN_SRC racket :results table drawer
|
||||
#hash((a . (and a b)) (b . (not b)))
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:RESULTS:
|
||||
| a | and | a | b |
|
||||
| b | not | b | |
|
||||
:END:
|
||||
|
||||
To tackle this issue, [[../utils.rkt][=dds/utils=]] provides
|
||||
=stringify-variable-mapping= (with the shortcut =sgfy=) which
|
||||
converts all the values of a given variable mapping to strings:
|
||||
|
||||
#+BEGIN_SRC racket :results table drawer
|
||||
(sgfy #hash((a . (and a b)) (b . (not b))))
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:RESULTS:
|
||||
| a | "(and a b)" |
|
||||
| b | "(not b)" |
|
||||
:END:
|
||||
|
||||
** Reading Org-mode tables<<tabread>>
|
||||
Org-mode allows supplying tables as arguments for code blocks.
|
||||
|
||||
#+NAME: test-table
|
||||
| a | "(and a b)" |
|
||||
| b | (or b (not a)) |
|
||||
|
||||
#+BEGIN_SRC elisp :var tab=test-table :results output drawer
|
||||
tab
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:RESULTS:
|
||||
:END:
|
||||
((a (and a b)) (b (or b (not a))))
|
||||
|
||||
Unfortunately, the same trick does not work with Racket directly,
|
||||
because Racket interprets the first elements in the parentheses as
|
||||
function applications:
|
||||
|
||||
#+BEGIN_SRC racket :results output drawer :var tab=test-table
|
||||
tab
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:RESULTS:
|
||||
application: not a procedure;
|
||||
expected a procedure that can be applied to arguments
|
||||
given: "a"
|
||||
arguments...:
|
||||
"(and a b)"
|
||||
context...:
|
||||
"/tmp/babel-qkvrRR/org-babel-c4wuju.rkt": [running body]
|
||||
temp37_0
|
||||
for-loop
|
||||
run-module-instance!125
|
||||
perform-require!78
|
||||
:END:
|
||||
|
||||
Fortunately, we can easily remedy this problem by creating a named
|
||||
parameterised Elisp source block which will explicitly convert the
|
||||
table to a string:
|
||||
|
||||
#+NAME: munch-table
|
||||
#+BEGIN_SRC elisp :results output drawer :var tab=test-table
|
||||
(prin1 tab)
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS: munch-table
|
||||
:RESULTS:
|
||||
(("a" "(and a b)") ("b" "(or b (not a))"))
|
||||
:END:
|
||||
|
||||
We can now correctly receive this table in a Racket source code
|
||||
block by threading it through =munch-table=:
|
||||
#+BEGIN_SRC racket :results output drawer :var tab=munch-table(tab=test-table)
|
||||
(println tab)
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:RESULTS:
|
||||
"((\"a\" \"(and a b)\") (\"b\" \"(or b (not a))\"))"
|
||||
:END:
|
||||
|
||||
[[../utils.rkt][=dds/utils=]] has several functions for parsing such strings, and
|
||||
notably =read-org-variable-mapping=, with the shortcut =unorg=:
|
||||
#+BEGIN_SRC racket :results output drawer :var tab=munch-table(tab=test-table)
|
||||
(unorg tab)
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:RESULTS:
|
||||
'#hash((a . (and a b)) (b . (or b (not a))))
|
||||
:END:
|
||||
|
||||
Of course, we can use =munch-table= to prepare any other table than
|
||||
=test-table= for use with Racket:
|
||||
|
||||
#+NAME: another-test-table
|
||||
| a | (not a) |
|
||||
| b | (and a c) |
|
||||
| c | (and a (not b)) |
|
||||
|
||||
#+BEGIN_SRC racket :results output drawer :var tab=munch-table(tab=another-test-table)
|
||||
(unorg tab)
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:RESULTS:
|
||||
'#hash((a . (not a)) (b . (and a c)) (c . (and a (not b))))
|
||||
:END:
|
||||
|
||||
** Inline graph visualisation with Graphviz
|
||||
Some functions in =dds= build graphs:
|
||||
|
||||
#+BEGIN_SRC racket :results output drawer :var bf=munch-table(another-test-table)
|
||||
(build-interaction-graph (unorg bf))
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:RESULTS:
|
||||
#<unweighted-graph>
|
||||
:END:
|
||||
|
||||
The =graph= library allows building a Graphviz description of the
|
||||
constructed graph. (Note that you have to install the =graph=
|
||||
library by running =raco pkg install graph= and require it. The
|
||||
long property line at the top of this file defining the prologue for
|
||||
racket source code blocks takes care of requiring =graph=.)
|
||||
|
||||
#+NAME: igraph
|
||||
#+BEGIN_SRC racket :results output drawer :var bf=munch-table(another-test-table)
|
||||
(display (graphviz (build-interaction-graph (unorg bf))))
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS: igraph
|
||||
:RESULTS:
|
||||
digraph G {
|
||||
node0 [label="c"];
|
||||
node1 [label="b"];
|
||||
node2 [label="a"];
|
||||
subgraph U {
|
||||
edge [dir=none];
|
||||
node0 -> node1;
|
||||
node2 -> node2;
|
||||
}
|
||||
subgraph D {
|
||||
node2 -> node0;
|
||||
node2 -> node1;
|
||||
}
|
||||
}
|
||||
:END:
|
||||
|
||||
You can have an inline drawing of this graph by calling the previous
|
||||
code block (=igraph=) via a noweb reference in Graphviz/DOT source
|
||||
block:
|
||||
|
||||
#+BEGIN_SRC dot :file dots/exampleBQNp7Z.svg :results raw drawer :cmd sfdp :noweb yes
|
||||
<<igraph()>>
|
||||
#+END_SRC
|
||||
|
||||
#+RESULTS:
|
||||
:RESULTS:
|
||||
[[file:dots/exampleBQNp7Z.svg]]
|
||||
:END:
|
||||
|
||||
Note that the =graph= library draws self-loops as undirected edges.
|
||||
It also draws double-sided edges as undirected edges (e.g., in the
|
||||
preceding graph, b depends on c and c depends on b).
|
||||
|
||||
* Local Variables :noexport:
|
||||
# Local Variables:
|
||||
# eval: (auto-fill-mode)
|
||||
# ispell-local-dictionary: "en"
|
||||
# org-link-file-path-type: relative
|
||||
# End:
|
Loading…
Reference in a new issue