There were several tough things however. The first was error handling. Yes you can catch exceptions in native code and convert it to exceptions in the other language, but it's not straightforward to keep stacktraces. The second was circular references between runtimes. Since references across boundaries are global, garbage collector on either side could not reclaim circularly referenced objects. Although this could be resolved by manually breaking up the circle, it could be better to have weak references. (Or maybe other utilities, idk what would be more elegant.) The third was that js has no operator overloading, so I had to use .__add__() for example to call the python add operator.
One line example: https://github.com/swordfeng/pyjs/blob/master/test/jsobject.... It's a toy project I did years ago and not even compiling now. Also I was wondering if anyone really need to do things in this way, given there are bunch of popular and stable RPC libraries. But I was happy to learn something about underlying cpython and v8 from it.
I expect this wouldn't have worked in the long run as these methods are often just part of the protocol e.g. even `a == b` will try `type(a).__eq__(a, b)` then fall back to `type(b).__eq__(a)` (~~and then it'll do some weird stuff with type names IIRC~~[0]).
And most operators are not considered symmetric so the fallback is not the same as the initial (even `+` has `__add__` and `__radd__`, also `__radd__` might be called first depending on the relationship between type(a) and type(b)).
And then there's the "operations" which fallback to entirely different protocols e.g. `in` will first try to use `__contains__`, if that doesn't exist it uses `iter()` which tries to use `__iter__` but if that doesn't exist it falls back to calling `__getitem__` with non-negative sequential integer.
Which is why sometimes you define `__getitem__` for a pseudo-mapping convenience and then you get weird blowups that it's been called with `0` (you only ever expected string-keys). Because someone somewhere used `in` on your object and you hadn't defined `__iter__` let alone `__contains__`.
Good times.
[0] I misremembered: it's for ordering (not equality) in Python 2[1] `a < b` will first invoke `type(a).__lt__(a, b)`, then if that's not implemented fall back to `type(b).__ge__(a)`, and if that's not implemented either it'll fall back to a few hard-coded cases (e.g. None is smaller than everything) and finally to `(type(a).__name__, id(a)) < (type(b).__name__, id(b))`. That is the order of independent types with no ordering defined is the lexicographic order of their type names, and if they're of the same type it's their position in memory
[1] where there's always an ordering relationship between two objects, one of the things I'm most graceful Python 3 removed even if it's sometimes inconvenient
Any idea which of those RPC libraries could help achieve this? I'd love a Django model instance that could be used seamlessly in a JSX template.
All the Tcl runtime is in the "runtime" object, so like "runtime.puts('Hello World')" or "runtime.expr('2128')", etc
It was a lot of fun
Anyway, Tcl felt very much like an 80's interpreted language to me. It seemed like every data structure was built on top of strings, and every statement was being run through eval().
The current trick we're looking at is making this zero-copy when same-node, esp for GPU code, so happy to chat with folks about that!
https://nodejs.org/api/n-api.html
We also have a c++ wrapper: https://github.com/nodejs/node-addon-api
Generally if you want python/java interaction, we maintain a tool called javacpp that handles this, we even bundle cpython: https://github.com/bytedeco/javacpp-presets
GraalVM itself also depends on javacpp for a portion of its features (LLVM wrapper): https://github.com/oracle/graal/blob/315f5dcf69c2e73fd13a5f8...
I'd be happy to answer questions about the overlap of the 2. I can say I happily execute python scripts from our embedded python and even point the python execution at an anaconda distribution.
I don't recall now why I chose it over the much more popular python-shell. Sigh - the exploratory-spike log is sparse, and then "that all works, so why revisit low-commitment choices". I used it last year for a python helper, to offload some opencv and tensorflow optical tracking from electron.
(Both exist, and work, in javascript. But opencv had painfully subtle issues even with py3 vs py2, so I payed complexity to be closer to then mainstream center py2. And then moved tf over to work around chromium's excellent video latency and load (for passthrough AR) becoming much less so when also touched by the cpu.)