Literate Programming with Raku
Different programming language communities have differing cultures. Some are more pragmatic, others more idealistic. Some place great emphasis on having code be thoroughly readable and understandable for anyone who joins an existing project, and some prefer writing out clear and in-depth documentation.
Raku, inheriting one of the best parts of Perl, has a community that writes great documentation.
What is Literate Programming?
Literate Programming is an alternate take on documentation. Instead of having the code be the central element and writing documentation around it, in Literate Programming we write a document that contains the essential parts of our program. In this way we integrate the code into our natural language in such a manner that the idea underlying the design is clear. In this way we also naturally start thinking explicitly about the operations our programs need to perform to fulfill the task we are setting out to undertake.
Literate programming is not to be confused with documentation generation; it’s not merely having a program that is well-documented with documentation lavishly surrounding the code and embedded into it, rather it’s having a document about the program in which the program itself is embedded. As Lewis Carroll had the Mad Hatter say in Alice in Wonderland:
You might just as well say that “I see what I eat” is the same thing as “I eat what I see”!
What is Org-mode?
Org-mode is a text-editing mode in the Emacs Lisp interpreter (which could arguably be called a text editor). When Org-mode is enabled one can edit text using a specific type of markup, called Org. Similar to Markdown, it supports basic text features like headers, basic text properties like bold or italic text, embedded hyperlinks, embedded code blocks, and so on.
However, due to the versatility of the Emacs platform Org-mode has been extended with a facility termed “Babel”, which allows authors to execute blocks of source code. Various languages are supported out of the box; unfortunately Raku, still being a rather young language despite being quite old, is not among those. To remedy that, I wrote a package called ob-raku that extends the Babel facilities to add Raku to the supported languages.
To use ob-raku in Emacs one will need to download the package (simple clone it from GitHub or download one of the release tarballs) and add it to their Emacs load path. This can either be done using the environment variable:
Or you can change the path in your configuration file (probably ~/.emacs or ~/.emacs.d/init.el):
(add-to-list 'load-path "/path/to/ob-raku")
After adding the path you can add Raku to the list of languages that Babel can use like this:
(org-babel-do-load-languages 'org-babel-load-languages '((c . t) (emacs-lisp . t) ; ... (raku . t)))
With Raku added to the list, you can create a Raku code block like this:
#+BEGIN_SRC raku "!dlroW ,olleH".flip #+END_SRC
You can evaluate the block by putting the cursor in or at the end of it and either using the menu bar, or typing C-c C-c (which is the Emacs notation for Ctrl+c Ctrl+c). The result of the evaluation will be added after the code block.
Unfortunately, the lack of session support for ob-raku means that functions declared in one block aren’t usable in other blocks. That said, the results of evaluating a block can be used as arguments to another block, to chain them together. So when editing a .org file we can write the following:
Let's make a list in Raku: #+NAME: nested-list #+BEGIN_SRC raku my @a = (("A", "B"), ("C", "D")) #+END_SRC We can also include results from other languages: #+NAME: elisp-list #+BEGIN_SRC emacs-lisp :results vector '(1 2) #+END_SRC And now we'll use the lists we just defined: #+NAME: crosser #+HEADER: :var a=nested-list() b=elisp-list() #+BEGIN_SRC raku my @crossed = @a X @b #+END_SRC
When you evaluate the crosser block Babel will evaluate the nested-list and elisp-list block, which both return lists, and assign them to the @a and @b variables. The resulting crossed list will be returned underneath the crosser block.
This post was drafted at the end of February 2020, before Daniel Sockwell wrote his excellent article on Literate Programming with Pod6. This post won’t be mentioning using Pod6 to do Literate Programming, but talk about an Emacs package I wrote to use Raku in Emacs Org-mode.
Raku REPL interaction in Emacs was still underway when this article was written, thanks to Matías Linares it has since solidified.
Conclusion and thanks
While the functionality of ob-raku is still limited, anyone who already uses it to write documents can now implement Raku code and thereby show reproducible data expressed in our lovely versatile language, and once session support lands Org-mode’s built in tangling facilities should bring true Literate Programming to the community.
Creating ob-raku would not have been possible without the work put in to raku-mode, so I would like to thank everyone involved in the project for their hard work. While our community is small, having people with passion work on improving the tools we use on a daily base makes our work much more enjoyable and thereby helps us keep going to make our little slice of heaven the best it can be.