8

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 – Henri Menke Apr 17 '20 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 '20 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. – Tomáš Kruliš Apr 17 '20 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 '20 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 – Tomáš Kruliš Apr 17 '20 at 10:44
10

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 – Henri Menke Apr 17 '20 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. – Tomáš Kruliš Apr 17 '20 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. – Henri Menke Apr 17 '20 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? – Tomáš Kruliš Apr 17 '20 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. – Tomáš Kruliš Apr 17 '20 at 14:17

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.