Using Scheme with Babel
As I mentioned in my Blogging and Babel post, Babel supports many languages that produce things other than pictures. Naturally, I wanted to try it out with Scheme. Here's a toy problem that demonstrates some of the things you can do.
Suppose we have some input arguments in a table
1 | 2 | 3 | 4 | 5 |
and we want to calculate the values of various functions of those arguments. We start with the definition of the input table and a Scheme source code block:
#+tblname: input |1|2|3|4|5| #+source: func-tab #+begin_src scheme :var args=input :exports results (define fib (lambda (n) (let fs ((n n) (a 0) (b 1)) (if (zero? n) a (fs (1- n) b (+ a b)))))) (map (lambda (n) (list n (* n n) (expt 2 n) (fib n))) (car args)) #+end_src
Babel delivers tables to Scheme as a list of rows so the input to the
code block is ((1 2 3 4 5))
. Likewise, if we want a table as output
we should return a list of rows. That should help you understand what
the code is doing. As you can see, the map produces a list of rows
where each row is (n n2 2n fibn). All of the functions except fib
are built in, but I included fib
to show that you can define
functions in the code block if you need to.
Notice that we named the input table with the #+tblname: input
line
just before the table. Similarly, we named the code block with the
#+source: func-tab
line; we'll use that name a bit later.
When we run the func-tab
code block by typing C-c C-c
with the
point in the block, we get the output table:
1 | 1 | 2 | 1 |
2 | 4 | 4 | 1 |
3 | 9 | 8 | 2 |
4 | 16 | 16 | 3 |
5 | 25 | 32 | 5 |
The table gives the correct results but suffers from the fact that it
doesn't have a heading telling what each column is. We can fix that by
pushing the list ("n" "n^2" "2^n" "fib_n")
onto the front of the
result of the map function in the func-tab
code block but then we
end up with
n | n2 | 2n | fibn |
1 | 1 | 2 | 1 |
2 | 4 | 4 | 1 |
3 | 9 | 8 | 2 |
4 | 16 | 16 | 3 |
5 | 25 | 32 | 5 |
which is better but still not what we want. The problem is that there
is no hline
under the headings so when we export the table to html
no <th> tag is generated and we can't use CSS to format a nice looking
table. What we want should look like
| n | n^2 | 2^n | fib_n | |---+-----+-----+-------| | 1 | 1 | 2 | 1 | | 2 | 4 | 4 | 1 | | 3 | 9 | 8 | 2 | | 4 | 16 | 16 | 3 | | 5 | 25 | 32 | 5 |
in Emacs. There's no documentation on how to do that but by trawling
through the Org-mode mailing list I found some hints. At least in
elisp and Scheme you can represent the hline
by including the symbol
hline
as a row where you want it to appear. Thus we want to push
'("n" "n^2" "2^n" "fib_n") 'hline
onto the front of the result of the map in the func-tab
block. We
could do that by adding the code to the func-tab
block but I want to
demonstrate something else instead. In general, if we want to post
process output from a block, we can merely call the block from our
post processing code—that's why we named the func-tab
block.
In our case we merely want to push a couple of new rows onto the
result of the func-tab
block but we could do any processing at
all. To see how that works, we define a new block to do the
processing:
#+begin_src scheme :var tab=func-tab :exports results (define cons2 (lambda (a b c) (cons a (cons b c)))) (cons2 '("n" "n^2" "2^n" "fib_n") 'hline tab) #+end_src
Notice how we set our input, tab
, to be func-tab
which causes this
block to use the output of the func-tab
block. Now the neat part is
that when we get ready to export to HTML we evaluate only this last
block. This, in turn, will cause the evaluation of func-tab
but no
intermediate table will be produced so we get only the final desired
result. If for some reason we want the intermediate results too, we
merely evaluate the func-tab
block directly.
Another nice feature of this method is that the blocks can be written
in different languages. In fact, the final code block was written in
elisp until I discovered that the same hline
trick worked in Scheme.
When we evaluate the last block and export to HTML we get our final result. I've added at little CSS sugar to show how we can improve the output when we have an actual <th> … </th> heading.
n | n2 | 2n | fibn |
---|---|---|---|
1 | 1 | 2 | 1 |
2 | 4 | 4 | 1 |
3 | 9 | 8 | 2 |
4 | 16 | 16 | 3 |
5 | 25 | 32 | 5 |
No comments:
Post a Comment