[juliacall] Invoking functions with names not allowed by Python

I’d like to make a Python wrapper for a Julia package that implements methods for Base operators like + and *, among others. The wrapper class should use juliacall to create the object and then simply pass method calls through.

For example, let me create a Foo type in Julia that implements length:

import juliacall
jl = juliacall.newmodule("PyFoo")
jl.seval("struct Foo; a; end; Base.length(::Foo) = 1")

class JuliaFoo:
    def __init__(self, x):
        self.julia = jl.Foo(x)
        self.x = x
    def length(self):
        return jl.length(self.julia)

Then I can do JuliaFoo(5).length() all day long. But if I want to define addition, I don’t know how to refer to + within the Julia module:

import juliacall
jl = juliacall.newmodule("PyFoo")
jl.seval("struct Foo; a; end; Base.:+(foo::Foo, x) = foo.a + x")

class JuliaFoo:
    def __init__(self, x):
        self.julia = jl.Foo(x)
        self.x = x
    def __add__(self, y):
        return jl.+(self.julia, y)     # NOT ALLOWED

What’s the right way to do this?

What’s weird is that I can see lots of unicode when I autocomplete on jl.+Tab, but can’t refer to all of them in the Python REPL:

>>> jl.÷
  File "<stdin>", line 1
    jl.÷
       ^
SyntaxError: invalid character '÷' (U+00F7)
>>> jl.π
Julia: π = 3.1415926535897...
>>> jl.√
  File "<stdin>", line 1
    jl.√
       ^
SyntaxError: invalid character '√' (U+221A)

I know that Python is limited to “letter-like” unicode characters, but somehow those things are defined.

You can do this:

>>> from juliacall import Main as jl
>>> julia_add = getattr(jl, "+")
>>> julia_add(1, 2)
3
>>> getattr(jl, "+")(1, 2)
3

With Python in general (not just with juliacall), you cannot use the normal dot syntax to access attributes with special characters that are illegal for identifiers.

2 Likes