# How can I convert a Lisp expression to a LaTeX math expression?

How can I convert a lisp expression to LaTeX math expression.

From simple things like (- 3 2 1) which should be converted to 3 - 2 - 1, to relatively complex things like: (* 1 2 (/ 2 3))1 \times 2 \times \frac{2}{3}, or (somefunc 1 2)somefunc(1,2), and so on.

Even being able to use some variables instead of numbers and convert them would be nice.

I type Lisp expressions in Emacs a lot, because I can just evaluate that there and get the output. That means I don't have to actually run a calculator or a terminal elsewhere. But I'd like to put valid LaTeX math expressions into the reports, and instead of typing again.

Is there any package that can help with that, or do I have to write the Elisp with a parser myself?

I found https://alejandrogallo.github.io/listex/ which seems to be for writing LaTeX in Lisp. I do not want to write LaTeX in Lisp. I want to convert already written valid Lisp expressions to LaTeX math expressions.

EDIT: Based on the accepted answer I ended up making a whole minor mode centering around this functionality.

• Is your question about LaTeX expressions in general or just LaTeX math expressions. Please clarify the question for this.
– Drew
Feb 2 at 19:59
• It's about latex math expressions. Also about the elisp tag info, the solution to this depends on parsing elisp expressions, so I considered it specific to elisp, I hope that tag is fine. Feb 2 at 20:16
• No, tag elisp is not about using Elisp to do something. It's about Elisp as a particular Lisp dialect.
– Drew
Feb 2 at 21:34

Here is a toy function:

(defvar lisp2latex-need-parens nil)
(defun lisp2latex (form)
(pcase form
((+ . ,args)
(let ((ret (let ((lisp2latex-need-parens nil))
(mapconcat #'lisp2latex args " + "))))
(if lisp2latex-need-parens
(concat "(" ret ")")
ret)))
((- ,a1 . ,args)
(let ((ret
(if args
(format "%s - %s" (lisp2latex a1)
(let ((lisp2latex-need-parens t))
(mapconcat #'lisp2latex args " - ")))
(format "- %s" (lisp2latex a1)))))
(if lisp2latex-need-parens
(concat "(" ret ")")
ret)))
((* . ,args)
(let ((lisp2latex-need-parens t))
(mapconcat #'lisp2latex args " \\times ")))
((/ ,a1 . ,args)
(if args
(format "\\frac{%s}{%s}" (lisp2latex a1)
(lisp2latex (cons '* args)))
(format "\\frac1{%s}" (lisp2latex a1))))
((,func . ,args)
(format "%s(%s)" func (mapconcat #'lisp2latex args ",")))
(_ (prin1-to-string form))))

(lisp2latex '(* (/ (log 4 64)) (/ 3 (+ 4 6) 8)))
"\\frac1{log(4,64)} \\times \\frac{3}{(4 + 6) \\times 8}"


It probably adds too many parens...

• That's like super fast, I can't believe how fast you did it, also it seems to work if I add other functions in the pcase, like ((setq . ,args) (mapconcat #'lisp2latex args " = ")). Feb 2 at 20:14
• I think your setq clause is wrong for more than 1 assignment.
– sds
Feb 2 at 20:16
• I was also thinking that, but for now I just wanted to see if I could add any functions there. If it works then, can you modify the default expression to print function(arg1,arg2, ...) format instead of (function arg1 arg2 ...) format? Feb 2 at 20:18
• I tried (_ (format "%s%s" (car form) (cdr form))) for the last one, and it does convert (sin 1) to sin(1) form, but again it doesn't work for multiple arguments. I tried (mapconcat #'lisp2latex (list (cdr form)) ", ") for second %s but it didn't work at all. Feb 3 at 2:48
• what's wrong with my current version?
– sds
Feb 3 at 2:49