9

according to https://towardsdatascience.com/5-ways-julia-is-better-than-python-334cc66d64ae it says (under item 2) the following

  Julia code is universally executable in R, Latex, Python, and C.

I googled a little bit and could not find an example of how to do this. of course one would need to have Julia itself installed on one's PC in addition to TexLive.

I am not talking about listing Julia code in Latex of course. Or about using Latex inside Julia.

The above says Julia code executable in Latex, which for me, means one can write some Julia function and call it from Latex and get the result back. Same as using Lua from Lualatex now. And the same when calling Python from Latex.

At least this is how I read the above.

If so, could we have a very small example of how to do this?

For starter, here is a MWE I wrote sometime ago about using Python in Latex

\documentclass[11pt]{article}%
  \usepackage{pythontex}
  \usepackage[T1]{fontenc}
  \usepackage[utf8]{inputenc}
  \begin{document}
  \begin{pyconsole}
  x = 987.27
  x = x**2
  \end{pyconsole}

  The variable is $x=\pycon{x}$
  \end{document}

Which needs to be compiled like this:

  pdflatex foo.tex
  /usr/local/texlive/2019/bin/x86_64-linux/pythontex  foo.tex
  pdflatex foo.tex

How to do something similar to the above for Julia?

5
  • Is LuaTeX possible? See also tex.stackexchange.com/q/504230/10995 Apr 17, 2020 at 6:44
  • @HenriMenke yes ofcourse. When I said inside Latex, I meant in any way. I actually myself just use LuaTex only.
    – Nasser
    Apr 17, 2020 at 6:45
  • Well, if I read it correctly, the article also talks about the need to have a wrapper for that. Which you have identified as pythontex. I dont use Julia, just Python and R; sadly never had rason to look at it. Apr 17, 2020 at 7:13
  • @TomášKruliš Yes, I would expect there is a need for a package/wrapper of some sort for Julia as well. The package pythontex I used in the example, is needed when calling Python from Latex.
    – Nasser
    Apr 17, 2020 at 7:15
  • 1
    It also has support for Julia. I dont exactly know to which extend, but I would expect to actually full extend; since R support in pythontex is "basic"; but actally everything works :D Apr 17, 2020 at 10:44

2 Answers 2

11

Julia has a C-API which you can use in LuaTeX via FFI. It requires some boilerplate code where you repeat some function prototypes from the API and some wrappers to convert between C types and Lua types. This is actually pretty painless. Save this file as julia.lua in the same directory as your document.

julia.lua

local ffi = require("ffi")
local JULIA = ffi.load("julia", true)

ffi.cdef [[
// Types
typedef struct _jl_value_t jl_value_t;

// Initialization
void jl_init__threading(void);
void jl_init_with_image__threading(const char *julia_bindir,
                                   const char *image_relative_path);

// Execution and conversion
jl_value_t *jl_eval_string(const char*);
const char *jl_string_ptr(jl_value_t *);
const char *jl_typeof_str(jl_value_t *);
]]

local julia_initialized = false

local julia = {}

function julia.init(rpath)
    -- Initialize the Julia interpreter (singleton)
    if not julia_initialized then
        if rpath then
            JULIA.jl_init_with_image__threading(rpath, "sys.so")
        else
            JULIA.jl_init__threading()
        end
        julia_initialized = true
    end
end

function julia.run(expr)
    assert(julia_initialized)
    JULIA.jl_eval_string(expr)
end

function julia.eval(expr)
    assert(julia_initialized)
    local jlval, cstr, str
    jlval = JULIA.jl_eval_string(expr)
    -- First check that the datatype
    if jlval ~= ffi.NULL then
        cstr = JULIA.jl_typeof_str(jlval)
    else
        return nil
    end
    if cstr ~= ffi.NULL then
        str = ffi.string(cstr)
    else
        return nil
    end
    -- if the datatype is string, convert to Lua string
    if str == "String" then
        cstr = JULIA.jl_string_ptr(jlval)
    else
        return nil
    end
    if cstr ~= ffi.NULL then
        str = ffi.string(cstr)
    else
        return nil
    end
    return str
end

return julia

You can now use this module in your document via require("julia"). It provides three functions:

  1. julia.init(rpath) This function has to be called once before the other functions to initialize the interpreter. Depending on your installation it might be necessary to provide the runtime path of Julia as the argument rpath (see also Calling Julia from Lua). In my installation this is not necessary and I can just omit the argument.

  2. julia.run(expr) Just runs expr.

  3. julia.eval(expr) This also runs the expression expr but attempts convert the last value of expr to string and returns it.

The Julia code you pass to this should be error-free, because there is not checking for errors on the Julia level. I don't know whether interpreter just bails if it sees an error, but this would also crash your document compilation.

Here I wrap the julia.eval function into some TeX-specific argument scanning and printing and assign it to a macro called \directjulia which can be used similar to \directlua. The big bonus of this over things like pythontex is that everything is fully expandable. You have to process the document with --shell-escape.

\documentclass{article}
\usepackage{luacode}
\begin{luacode*}
julia = require("julia")
julia.init()

local t = lua.get_functions_table()
t[#t + 1] = function()
    local expr = token.scan_string()
    local str = julia.eval(expr)
    if str then
        tex.sprint(str)
    end
end
token.set_lua("directjulia", #t, "global")
\end{luacode*}
\begin{document}

\begin{luacode*}
julia.run[===[
x = [1 2 3]'
A = [1 0 1; 0 1 1; 1 1 0]

y = x'*A*x
]===]
\end{luacode*}

\edef\value{\directjulia{string(y[1])}}

\texttt{\meaning\value}

\end{document}
8
  • 4
    I also have a Gist on GitHub with boilerplate for a couple of other scripting languages: gist.github.com/hmenke/2d57a3aa1d3d59a265f935dd4b384c36 Apr 17, 2020 at 8:01
  • At the gist page on top, theres written about LuaJIT. So does this require LuaJIT compiler, or is only current LuaTeX sufficient? Thank you for clarification. Apr 17, 2020 at 10:49
  • @TomášKruliš The FFI is originally a feature of LuaJIT and is not present in PUC-Rio Lua. However, a FFI that is compatible with the one from LuaJIT is embedded in LuaTeX. Apr 17, 2020 at 11:07
  • 1
    Trying to running your solution with 64bit LuaLaTeX and current Julia win64 instalation I am getting error: a:2: could not load library julia stack traceback: [C]: in function 'FFISUPPORTED' ./julia.lua:2: in main chunk [C]: in function 'require' [\directlua]:1: in main chunk. \luacode@dbg@exec ...code@maybe@printdbg {#1} #1 } l.36 \end{luacode*}. I have julia.lua in project directory. I have fresh installs of Julia and TeXlive 2020 in my PATH. What I could be doing wrong? Are there any other JUlia modules that I have to have? Apr 17, 2020 at 13:59
  • My error message is simillar to this: tex.stackexchange.com/questions/515624/… This was resolved by adding additional module. I dont know how to apply that solution here. I am on Win10. Apr 17, 2020 at 14:17
1

PythonTeX officially supports Julia almost out of the box. You only need to explicitly say that you want to use Julia, just to avoid naming conflicts. Here an MWE.

\documentclass{article}

\usepackage[usefamily={julia,jl}]{pythontex}

\begin{document}
    \begin{jlcode} % Or {juliacode}
        α = 23.15;
        α² = α^2;
    \end{jlcode}

    % To print it to LaTeX, `print()` directly from Julia or use `\jl` or `\julia`:
    $ \alpha^2 = \jl{α²} $!
\end{document}

And compile with (or any engine):

xelatex document.tex
pythontex document.tex
xelatex document.tex

I think it's not necessary to say you need Julia installed and accessible from your system. Unfortunately, for this reason, it'll not work on Overleaf.

Read the docs to see more details.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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