3

For context, I was inspired to try to configure emacs to execute Mathematica source blocks in org files after watching this video wherein someone demonstrates the use of another CAS, SageMath, in emacs org mode. I would use SageMath instead of Mathematica since I can just install ob-sagemath from MELPA, but the problem is I'm using macOS Big Sur and SageMath doesn't support my operating system.

I read this article from 2014 in which the author talks about creating support for mathematica in org mode and I've copied his source code into /.emacs.d/ob/ob-mathematica.el

(require 'ob)
(require 'ob-ref)
(require 'ob-comint)
(require 'ob-eval)
;; Optionally require mma.el for font lock, etc
(require 'mma nil 'noerror)
(add-to-list 'org-src-lang-modes '("mathematica" . "mma"))

(defvar org-babel-tangle-lang-exts)
(add-to-list 'org-babel-tangle-lang-exts '("mathematica" . "m"))

(defvar org-babel-default-header-args:mathematica '())

(defvar org-babel-mathematica-command "MathematicaScript -script"
  "Name of the command for executing Mathematica code.")

(defun org-babel-expand-body:mathematica (body params)
  "Expand BODY according to PARAMS, return the expanded body."
  (let ((vars (mapcar #'cdr (org-babel-get-header params :var))))
    (concat
     (mapconcat ;; define any variables
      (lambda (pair)
    (format "%s=%s;"
        (car pair)
        (org-babel-mathematica-var-to-mathematica (cdr pair))))
      vars "\n") "\nPrint[\n" body "\n]\n")))

(defun org-babel-execute:mathematica (body params)
  "Execute a block of Mathematica code with org-babel.  This function is
called by `org-babel-execute-src-block'"
  (let* ((result-params (cdr (assoc :result-params params)))
     (full-body (org-babel-expand-body:mathematica body params))
     (tmp-script-file (org-babel-temp-file "mathematica-")))
    ;; actually execute the source-code block 
    (with-temp-file tmp-script-file (insert full-body))
    ;; (with-temp-file "/tmp/dbg" (insert full-body))
    ((lambda (raw)
       (if (or (member "code" result-params)
           (member "pp" result-params)
           (and (member "output" result-params)
            (not (member "table" result-params))))
       raw
     (org-babel-script-escape (org-babel-trim raw))))
    (org-babel-eval (concat org-babel-mathematica-command " " tmp-script-file) ""))))

(defun org-babel-prep-session:mathematica (session params)
  "This function does nothing so far"
  (error "Currently no support for sessions"))

(defun org-babel-prep-session:mathematica (session body params)
  "This function does nothing so far"
  (error "Currently no support for sessions"))

(defun org-babel-mathematica-var-to-mathematica (var)
  "Convert an elisp value to a Mathematica variable.
Convert an elisp value, VAR, into a string of Mathematica source code
specifying a variable of the same value."
  (if (listp var)
      (concat "{" (mapconcat #'org-babel-mathematica-var-to-mathematica var ", ") "}")
    (format "%S" var)))

(provide 'ob-mathematica)

I then put the following in my .emacs file:

;; ...
(add-to-list 'load-path "/Users/duncanbritt/.emacs.d/ob/")
(load "/Users/duncanbritt/.emacs.d/ob/ob-mathematica.el")

(org-babel-do-load-languages
 'org-babel-load-languages
 '(
;; ...
   (mathematica . t)
   ))
;; ...

When I try to run mathematica source blocks in org mode, such as

#+begin_SRC mathematica
  1 + 1
#+end_SRC mathematica

I get the following message in the mini-buffer: Symbol's function definition is void: org-babel-get-header, which I assume references a line in my ob-mathematica.el file. As I understand it, this occurs because org-babel-get-header was removed in 0d000f5 (babel: small change in API., 2015-10-29). (By the way, the solution in the linked post is not applicable in my case. The poster was trying to execute shell scripts and was able to resolve the issue by changing (sh . t) to (shell . t) in their emacs configuration. This won't work for me because I'm trying to execute mathematica code using a custom .el file, since there isn't an official emacs package that I can use to evaluate mathematica code in org files in emacs.)

I'm not familiar with emacs lisp. My question is, how can I update this code to use current emacs API's, such that the above error is resolved?

4
  • 1
  • And an exact duplicate of emacs.stackexchange.com/q/37692. Please search first, to see if what you want to ask has already been asked (and perhaps answered). Thx.
    – Drew
    Feb 12, 2023 at 16:59
  • @Drew The proposed solution in the "exact duplicate" you've linked to, which I'd already seen, isn't applicable in my case. Feb 12, 2023 at 17:11
  • 1. Then say why that's the case - in the question itself. Otherwise, it looks like a duplicate to me. 2. Just because the duplicate doesn't have answers that you like doesn't mean that the question isn't a duplicate. If you really want to pose a somewhat different question then do so - edit your question to make it different.
    – Drew
    Feb 12, 2023 at 18:06

2 Answers 2

2

Let me start with mentioning that you are using an 'old' ob-mathematica.el. ob-mathematica.el used to be in org-contrib, which, according to this commit, was moved to a separate repository at https://git.sr.ht/~bzg/org-contrib. Subsequently, there we find that ob-mathematica.el has been removed from org-contrib. I don't know how to search the history on sourcehut, so I have cloned the repo and searched it locally. In that way I have located this commit, which mentions that ob-mathematica.el now lives on its own repository at https://github.com/tririver/ob-mathematica/.

Therefore, I would suggest that you might want to start from that version.

However, I have been looking into this myself also, and I have found that it is not straightforward to implement support for graphics (e.g. plots) because the Mathematica shell does not simply output graphics data. If you do not need graphics, then I think the ob-wolfram.el code from here should work fine (although for some reason I removed font-lock support via mma.el). I am not sure where I have got that ob-wolfram.el file from, but probably (I just don't remember), I have renamed and updated ob-mathematica.el myself, when I wanted to add support for 'sessions'. Probably, I have stopped trying to implement sessions, because I had found a nicer working solution, which was to use the WolframLanguageForJupyter kernel i.c.w. the emacs-jupyter package, which already supported graphics and sessions. Unfortunately, Wolfram Jupyter functionality broke here when I updated Mathematica (and I did not quickly find how to fix it), so that I can not test it here and give further explanations. But it was working fine before the update, and I would strongly advise you to check it out if you'd like to have support for sessions and graphics (although it should be quite straightforward to add support for sessions to ob-mathemematice/wolfram.el, it is less straightforward to add support for graphics).

Additionally, I remember that jupyter returned html, which I rendered via a solution posted here.

1
  • 2
    By using your ob-wolfram.el code and changing my 'org-babel-load-languages to say (wolfram . t) instead of (mathematica . t), and using #+BEGIN_SRC wolfram, it works beautifully! Thank you! I will look into your suggestion about WolframLanguageForJupyter kernal. Feb 14, 2023 at 2:50
1

If you want to try fixing the code you posted (rather than going for a solution along the lines of @dalanicolai's answer), here's an untested fix: change the let line below:

(defun org-babel-expand-body:mathematica (body params)
  "Expand BODY according to PARAMS, return the expanded body."
  (let ((vars (mapcar #'cdr (org-babel-get-header params :var))))
    ...

to

  ...
  (let ((vars (org-babel--get-vars params)))
    ...

That should resolve the Symbol's function definition is void: org-babel-get-header error, but you may run into other errors later on - I have not checked the rest of the code you posted.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.