Org-Mode Babel Support for Racket
This Emacs module enables support for the Racket programming language in Emacs’ Org-mode Babel. This allows executing Racket code blocks directly from Org mode, embedding the results of those code blocks in your Org files, and even chaining the result from one code block into another code block. See the Babel intro for more details on what’s possible.
Example Usage
This example shows how to add a code block implementing the classic recursive
factorial. With point inside the code block, press C-c C-c to execute the
block. The result will be inserted immediately beneath it.
#+BEGIN_SRC racket :var input=10
(define (factorial n)
(if (= n 1)
1
(* n (factorial (sub1 n)))))
(factorial input)
#+END_SRC
#+RESULTS:
: 3628800
This example shows how you can use custom languages. To run this you will need Beautiful Racket installed.
#+BEGIN_SRC racket :results output
#lang reader stacker-demo/stacker
4
8
+
3
,,*
#+END_SRC
#+RESULTS:
: 36
Custom Languages
To best implement and test a custom language we have to be able to emit the
language implementation in a known location next to its usage. We can do
this by naming a block and then referencing via the :adjacent-file header.
#+name: stacker-reader-expander.rkt
#+begin_src racket :eval no :noweb strip-export :tangle
#lang br/quicklang
(define (read-syntax path port)
(define src-lines (port->lines port))
(define src-datums (format-datums '(handle ~a) src-lines))
(define module-datum `(module stacker-mod "./stacker-reader-expander.rkt"
,@src-datums))
(datum->syntax #f module-datum))
(provide read-syntax)
(define-macro (stacker-module-begin HANDLE-EXPR ...)
#'(#%module-begin
HANDLE-EXPR ...
(display (first stack))))
(provide (rename-out [stacker-module-begin #%module-begin]))
(define stack empty)
(define (pop-stack!)
(define item (first stack))
(set! stack (rest stack))
item)
(define (push-stack! item)
(set! stack (cons item stack)))
(define (handle [x #f])
(when x
(cond
[(number? x) (push-stack! x)]
[(or (equal? + x)
(equal? * x))
(define op-result (x (pop-stack!) (pop-stack!)))
(push-stack! op-result)])))
(provide handle + *)
#+end_src
This will now work!
#+begin_src racket :adjacent-file stacker-reader-expander.rkt
#lang reader "./stacker-reader-expander.rkt"
4
8
+
3
*
#+end_src
#+RESULTS:
: 36
Supported Header Arguments
- :results
- Can be set to either
valueoroutput. If set tovalue, the code block will be wrapped in a (let …) form, and only the result of the form will recorded. If set tooutput, the code block will be run as a script, and all standard output will be recorded. Defaults tovalue. - :var
- Allows defining a variable for use in the block. If using the
valueoutput type, the variable will be passed to the wrapping function as an argument. Otherwise, it will be defined at the top level of the script using a(define ...)form. - :require
DEPRECATEDAllows you to use require statements. Because the way:results valueworks is by wrapping everything in alet, you cannot normally use arequirestatement (these have to be top-level). To help,:require racket/datewill generate(require racket/date)outside theletblock. Multiplerequirestatements can be used and they may or may not be quoted. While not strictly necessary for:results output, will work anyways to keep with the convention.- :adjacent-file
- Should be the name of another (presumably Racket) block
in the same document. This block source will be expanded and emitted
adjacent to the main file during execution. This is especially useful for
implementing languages in one block and testing them in another. Note that
at the moment, multiple
:adjacent-fileblocks are not supported. You can however pass a white-space-separated list to this argument eg:adjacent-file foo1.rkt foo2.rktwhere there are blocks named bothfoo1.rktandfoo2.rktin the same document.
Installation
- Install
ob-racket.elin your Emacs load path - Add the following to your
.emacs.dfile:
;; Enable Racket in Org-mode Babel
(org-babel-do-load-languages
'org-babel-load-languages
'((racket . t)))- If your Racket interpreter is installed in a non-standard location (anywhere
other than
/usr/bin/racket), also add the following to your.emacs.dfile:
;; Set path to racket interpreter
(setq org-babel-command:racket "/path/goes/here")Author
Chris Vig (chris@invictus.so)