Janus: py_call(1 + 2, Sum)

How do I call a python primitive like plus?

7 ?- use_module(library(janus)).
true.

8 ?- py_call(print("Hello World!\n")).
Hello World!

true.

9 ?- py_call(sys:getsizeof([1,2,3]), Size).
Size = 80.

10 ?- py_call(1 + 2, Sum).
ERROR: python_builtin `+' does not exist

Most of these things also have some function that typically starts with __. I can’t find it here though. The other alternative is to write a function add() and use that. Typically though, you do not want to call small Python steps from Prolog. Just add a Python function that does what you need at a bit higher granularity and call that is typically faster and easier to read. Note that te SWI-Prolog version of Janus provides py_module/2 to add (small) Python snippets in your Prolog code, so you can keep the helper source at the most logical place (i.e., either inside the Prolog code or in a Python module you load explicitly).

Choosing the right level (typically high) of granularity is key to readable and fast cooperation between languages. This advice also holds for C, C++, JavaScript, …

I think add is actually a “method” of a numeric object, like this:

>>> a = 1
>>> a
1
>>> a.__add__(2)
3

Is there any way to access this from swipl? My use case is not addition, but symbolic computing with sympy, discussed in a parallel thread.

Not urgent, though.

I’d assume this should then work if a is a property of the current module that is set to a numerical value.

?- py_call(a:'__add__'(2), X).
X = 3.

The magic methods are documented here: operator — Standard operators as functions — Python 3.13.2 documentation

1 Like
?- py_call(operator:add(1,2), X).
% Interactive session; added `.` to Python `sys.path`
X = 3.

Great, thanks a lot

The entire example, including the assignment of a variable in Python:

27 ?- py_call(globals():'__setitem__'('a', 10)).
true.

28 ?- py_call(globals():'__getitem__'('a'), A), py_call(operator:add(A, 2), X).
A = 10,
X = 12.

I didn’t find a simple shortcut of (=)/2 in janus, had to use globals():__setitem__

So, now we can “simplify” algebraic expressions with janus:

14 ?- py_import(sympy, []).
15 ?- py_call(sympy:'Symbol'(x), X), py_call(operator:add(X, X), X2), py_pp(X2).
2*x
@(none)
X = <py_Symbol>(0000029b4b455940),
X2 = <py_Mul>(0000029b4cea7000).

Note the 2*x. The remaining challenge is to get 2*x back from the py_Mul blob in sympy.

Update: