# Janus: accessing elements of python tuples and arrays

**URL:** <https://swi-prolog.discourse.group/t/janus-accessing-elements-of-python-tuples-and-arrays/7745>\
**Category:** General\
**Created:** [August 29, 2024, 12:47pm UTC](https://swi-prolog.discourse.group/t/janus-accessing-elements-of-python-tuples-and-arrays/7745 "2024-08-29T12:47:25Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![stassa.p](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/stassa.p/32/712_2.png) [@stassa.p](https://swi-prolog.discourse.group/u/stassa.p)\
**Post date:** [August 29, 2024, 12:47pm UTC](https://swi-prolog.discourse.group/t/janus-accessing-elements-of-python-tuples-and-arrays/7745/1 "2024-08-29T12:47:25Z")

</div>

I’ve unpacked some values from a Python tuple like this:

```prolog
14 ?- py_call($Ss:next_step(),_Obs,[py_object]), _Obs =.. [-,T,Pos,Occ,Cov,Cts].
T = 789.0,
Pos = <py_ndarray>(0000018ff1d0f9f0),
Occ = <py_ndarray>(0000018ff1c86910),
Cov = <py_list>(0000018ff2e062c0),
Cts = <py_ndarray>(0000018ff3c47090),
Ss = <py_SurveySimulationGrid>(0000018fc8f17d60).

```

Pos is a 2d array of zeroes with a single 1 and I want to get the coordinates of the 1. I’m trying to do this with numpy `where()` but:

```prolog
17 ?- py_call($Ss:next_step(),_Obs,[py_object]), _Obs =.. [-,T,Pos,Occ,Cov,Cts], py_call(numpy:where(Pos == 1),XY).
ERROR: Domain error: `py_term' expected, found `<py_ndarray>(0000018ff2dfcb10)==1'
ERROR: In:
ERROR: [13] janus:py_call(numpy:where(...),_5007164)
ERROR: [11] toplevel_call(user:user: ...) at c:/program files/swipl/boot/toplevel.pl:1318
ERROR:
ERROR: Note: some frames are missing due to last-call optimization.
ERROR: Re-run your program in debug mode (:- debug.) to get more detail.
^ Exception: (4) setup_call_cleanup('$toplevel':notrace(call_repl_loop_hook(begin, 0)), '$toplevel':'$query_loop'(0), '$toplevel':notrace(call_repl_loop_hook(end, 0))) ? abort
% Execution Aborted

```

More generally I have no idea how to access the elements of tuples and arrays positionally, in Janus. For example that’s why I’m unpacking `_Obs` above with univ (also because it has ‘-’ as a functor and I want to get to the tuple values).

Suppose I try to do it like this, as I would normally in Python:

```prolog
17 ?- py_call($Ss:next_step(),_Obs,[py_object]), _Obs =.. [-,T,Pos,Occ,Cov,Cts], py_call(Pos[1][1],El)
.
ERROR: Syntax error: Operator expected
ERROR: py_call($Ss:next_step(),_Obs,[py_object]), _Obs =.. [-,T,Pos,Occ,Cov,Cts], py_call(Po
ERROR: **here**
ERROR: s[1][1],El) .

```

That’s not allowed. But then how do I access a tuple or array elements by index?

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [August 29, 2024, 2:39pm UTC](https://swi-prolog.discourse.group/t/janus-accessing-elements-of-python-tuples-and-arrays/7745/2 "2024-08-29T14:39:42Z")

</div>

In both cases, the root of the problem is that we can only evaluate functions (or methods, but these are basically the same). I’m not sure about the nympy:where() case. The `Pos == 1` should be a _condition_, but I do not know what that is in Python/numpy speak.

Getting an array element is written in Python as `a[i]`, but that is just syntactic sugar for `a. __getitem__ (i)` and we can call that from Prolog.

In general, I think you should write a Python function to get the data into a shape that you want from Prolog. That also holds the other way around.

Possibly we should consider a better interface over numpy. For example:

```prolog
?- py_call(numpy:array([1,2,3]), X, [py_object]).
X = <py_ndarray>(0xfffec0192610).

?- py_call($X:' __getitem__'(2), V).
V = <py_int64>(0xfffec0161410),
X = <py_ndarray>(0xfffec0192610).

```

Now I still need some method to get to the actual integer. I was thinking about adding a method, e.g., ` __prolog__ ()` to a Python object that would do the conversion to a meaningful Prolog object. But, `py_int64` is a class to which we cannot add methods (forgot the Python name for that) and there is no point in subclassing as numpy simply creates instances of `py_int64`.

The alternative is possibly some Prolog definition that tells the system how to represent these values?

---

<div class="post-metadata">

**Author:** ![stassa.p](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/stassa.p/32/712_2.png) [@stassa.p](https://swi-prolog.discourse.group/u/stassa.p)\
**Post date:** [August 29, 2024, 2:47pm UTC](https://swi-prolog.discourse.group/t/janus-accessing-elements-of-python-tuples-and-arrays/7745/3 "2024-08-29T14:47:14Z")

</div>

> [@jan](#):
>
> Getting an array element is written in Python as `a[i]`, but that is just syntactic sugar for `a. __getitem__ (i)` and we can call that from Prolog.

Ah, thanks. I was looking all over the place for this information but I couldn’t find it.

> [@jan](#):
>
> In general, I think you should write a Python function to get the data into a shape that you want from Prolog. That also holds the other way around.

That’s how I’m doing it for now, but that means I have to maintain a separate Python file to go along with my Prolog file and it’s not the end of the world but I was hoping to avoid that. On the other hand, writing Python in Python is more natural than trying to fit everything in `py_call()` and similar so that’s OK.

> [@jan](#):
>
> The alternative is possibly some Prolog definition that tells the system how to represent these values?

Possibly. I wonder if it’s just a matter of waiting for good practices to arise in the community. For the time being if I search online for some hints on how to use Janus I only find a few comments on this server (a couple by myself) and the official documentation. I’m hoping that eventually more user generated content will start to appear from folks who know both Python and Prolog well. Then I can stop bothering the server with silly questions 🙂

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [August 29, 2024, 3:56pm UTC](https://swi-prolog.discourse.group/t/janus-accessing-elements-of-python-tuples-and-arrays/7745/4 "2024-08-29T15:56:49Z")

</div>

> [@stassa.p](#):
>
> That’s how I’m doing it for now, but that means I have to maintain a separate Python file to go along with my Prolog file and it’s not the end of the world but I was hoping to avoid that.

There is py\_module/2 for that purpose. That keeps the code nicely together.

> [@stassa.p](#):
>
> Possibly. I wonder if it’s just a matter of waiting for good practices to arise in the community.

Janus is still quite new. It takes time to get mature and problems like these are the way to get there. For quite some Python libraries it all works nicely. For others it looks clumsy. numpy is one of these ☹ One way out is of course to write a Prolog friendly layer on top. If numpy is the real target we should probably consider a native binding to numpy as that most likely a lot faster. For the record, I wrote such a thing for ROS2 (the robotics protocol). The Prolog interface is a lot faster than the Python binding and thus even more so then Prolog → Python → ROS. It is more work though ☹

---

<div class="post-metadata">

**Author:** ![stassa.p](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/stassa.p/32/712_2.png) [@stassa.p](https://swi-prolog.discourse.group/u/stassa.p)\
**Post date:** [August 29, 2024, 4:12pm UTC](https://swi-prolog.discourse.group/t/janus-accessing-elements-of-python-tuples-and-arrays/7745/5 "2024-08-29T16:12:10Z")

</div>

> [@jan](#):
>
> There is [py\_module/2](https://www.swi-prolog.org/pldoc/doc_for?object=py_module/2) for that purpose. That keeps the code nicely together.

Thanks! I need to explore the Janus interface better.

> [@jan](#):
>
> Janus is still quite new. It takes time to get mature and problems like these are the way to get there.

I think as long as it is possible to call a Python file from Prolog there is no reason to complain that Janus doesn’t have specific syntax for all Python libraries. After all what will you do, anticipate every future library? I think Janus is already extremely useful the way it is now. Chatter from the ILP community tells me that’s not just me who thinks so!

The ROS2 interface is really interesting to me because I work with some roboticists and they use it extensively, as expected. I can tell that it is a lot of work though so if my PIs are in a hurry for me to use it I can always tell them to spare some of our funding to sponsor the project 🙂

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [August 29, 2024, 5:14pm UTC](https://swi-prolog.discourse.group/t/janus-accessing-elements-of-python-tuples-and-arrays/7745/6 "2024-08-29T17:14:16Z")

</div>

> [@stassa.p](#):
>
> I can always tell them to spare some of our funding to sponsor the project

It is a bit sleeping project as the funding stopped, but I’m happy to revive it if there is new funding.

---

<div class="post-metadata">

**Author:** ![stassa.p](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/stassa.p/32/712_2.png) [@stassa.p](https://swi-prolog.discourse.group/u/stassa.p)\
**Post date:** [August 29, 2024, 6:16pm UTC](https://swi-prolog.discourse.group/t/janus-accessing-elements-of-python-tuples-and-arrays/7745/7 "2024-08-29T18:16:46Z")

</div>

I’m not promising anything but if we end up using it I’ll certainly make a point of suggesting it.

---

<div class="post-metadata">

**Author:** ![anon419083](https://avatars.discourse-cdn.com/v4/letter/a/53a042/32.png) [@anon419083](https://swi-prolog.discourse.group/u/anon419083)\
**Post date:** [August 30, 2024, 6:13am UTC](https://swi-prolog.discourse.group/t/janus-accessing-elements-of-python-tuples-and-arrays/7745/8 "2024-08-30T06:13:59Z")

</div>

> [@stassa.p](#):
>
> More generally I have no idea how to access the elements of tuples and arrays positionally, in Janus

Thanks. I didn’t know Python had arrays as data types. But I also read they are not built-in (like lists, dictionaries, tuples, …): one has to import them from “specialized” modules (like numpy) before working with them
