I've been trying to port a vector math library to transcrypt and I've bumped into an issue with emulating iterable types.
I've got a Vector class with an inner iterable. Here's a simplified version of the core:
class Vector:
def __init__(self, *values):
self.values = values
def __iter__(self):
for item in self.values:
yield item
def __add__(self, other):
return Vector( *(x + y for x, y in zip(self, other)))
In pure python (Vector(1,2,3) + Vector(3,4,5))
returns Vector(4,6,8)
as you'd expect. But after transcryption, the same code fails -- in Javascript it appears that zip()
is expecting a Javascript map()
function on its iterable objects.
I can work around it in this case by explicitly targeting the underlying storage, which -- since it's created with a *args -- seems to have the required method:
def __add__(self, other):
pairwise = zip(self.values, other.values)
return Vector( *(itertools.starmap(lambda a, b: a + b, pairwise)))
but coupling that to the inner container feels rickety to me and I assume theres overhead for creating the iterator and the starmap.
So -- what's the right way to work around this? Can I add a map()
to the class? And if so, what's the right signature? The underlying JS seems to rely on JS scoping behavior... which scares me...
The point is that
zip
has not yet been adapted for iterators. A simple workaround is converting the args ofzip
to lists. The following code works:This will print:
Sorry for the late answer, have been a bit thinly spread the past few months. Adapting zip for iterators I found quite complicated, that's why it wasn't done yet.
Come to think of it, converting the params to lists could be done automagically. I will add that (issue #369), despite the (tiny) overhead by the runtime test, because it better matches expected behavior.
It is in release 3.6.44 and your code should now work correctly without alterations (using the -e 6 switch to activate iterators).