Typed Racket + Org-mode + Org tables and lists

Hi,

I would like to use Typed Racket in Org-mode code blocks with ob-racket-mode and produce Org lists and tables. (Untyped) Racket code works out of the box:

#+BEGIN_SRC racket :results table drawer
'((a 1) (b 2))
#+END_SRC

produces this result

#+RESULTS:
:results:
| a | 1 |
| b | 2 |
:end:

Now I switch to Typed Racket in the following way:

#+BEGIN_SRC racket :results table drawer :lang typed/racket
'((a 1) (b 2))
#+END_SRC

and this breaks with the following error message:

/tmp/babel-9vcsBj/org-babel-p3WZz0.rkt:4:0: Type Checker: missing type for identifier;
consider using `require/typed' to import it
identifier: datum->table
from module: (file /home/scolobb/.emacs.d/elisp/emacs-ob-racket/ob-racket-runtime.rkt)
in: (ob-racket-begin-print-table (quote ((a 1) (b 2))))

It turns out indeed that the Racket part of ob-racket is written in #lang racket/base, and then something happens which seems to try to run that code in a Typed Racket context. I am currently trying to figure out what happens exactly.

I also tried to introduce a typed submodule in the following way:

#+BEGIN_SRC racket :results table drawer
(module a typed/racket
  '((a 1) (b 2)))
#+END_SRC

but this fails with the following message:

/tmp/babel-9vcsBj/org-babel-whnzhW.rkt:6:0: module: allowed only at the top level or in a module top-level
in: (module a typed/racket (quote ((a 1) (b 2))))
location...:
/tmp/babel-9vcsBj/org-babel-whnzhW.rkt:6:0

At this point, I would gladly take any pointers, hints, or ideas as to how to best proceed. I have been using Org Babel for ages, but I have never really opened the hood before now.

Have you seen installed languages like remora/dynamic on the #+begin_src line ? · Issue #4 · hasu/emacs-ob-racket · GitHub -- it seems in the same ballpark? If not, maybe you could file a fresh issue.


Caveats: I rarely use org-babel. I only have time to take a quick look through the ob-racket-mode source, which is unrelated to and doesn't use racket-mode.

Given the "template" system in the Elisp code, it's hard for me to grok what actual Racket program is being run. But I think your module work-around (good idea!) errors because your program text (among other things from the template?) ends up as body in ob-racket-begin-print-elisp or ob-racket-begin-print-table:

(define-syntax-rule
  (ob-racket-begin-print-table body ...)
  (display
   (datum->table
    (let ()
      body ...)))))

Ergo the error about module.


To run a wider range of Racket programs, maybe all this could work differently, more akin to Scribble sandbox evaluators? But that might have its own set of disadvantages. Also org-babel might not let you share one evaluator across multiple snippets as does Scribble. idk.

1 Like

Thank you very much for the pointers @greghendershott ! I actually started reading everything attentively, including the source code for ob-racket, which is why I still have no meaningful reaction.

Now, from reading the sources I have the impression that Tero Hasu the developer of ob-racket did think rather seriously about other #langs, so I expect to be able to find an incantation mixing header arguments and "templates" which would allow me to achieve the desired behavior.

I will definitely report back here as soon as I have anything!

After some time ( :smiley: ) , I am coming back with this pull request: [WIP] Typed racket by scolobb · Pull Request #10 · hasu/emacs-ob-racket · GitHub , in which I suggest adding a Typed Racket runtime for Ob-racket, and which can be used by running the following Elisp code in the Org buffer:

(setq-local ob-racket-locate-runtime-library-function
	    (lambda ()
	      "/absolute/path/to/ob-racket-runtime-typed.rkt"))

As I explain in more details in the top comment on the PR, I am not entirely happy with this solution, so feel free to go over to GitHub and leave comments and suggestions, or just chime in here!

2 Likes

Further good news for ob-racket and Typed Racket: it works transparently now!

Based on [WIP] Typed racket by scolobb · Pull Request #10 · hasu/emacs-ob-racket · GitHub , Tero Hasu implemented a transparent way to switch Racket runtimes responsible for converting Racket data structure to Elisp/Org-mode compatible ones, and this change is now in master: add basic support for multiple runtime libraries · hasu/emacs-ob-racket@948f05c · GitHub !

More concretely:

#+BEGIN_SRC racket :results table drawer :lang typed/racket
'((a 1) (b 2))
#+END_SRC
#+RESULTS:
:results:
| a | 1 |
| b | 2 |
:end:

You can also specify the #lang directly in the code block:

#+BEGIN_SRC racket :results table drawer
#lang typed/racket
'((a 1) (b 2))
#+END_SRC
#+RESULTS:
:results:
| a | 1 |
| b | 2 |
:end:

Enjoy!

1 Like