Reputation: 21
I am attempting to improve a Bash to Python translator.
Bash allows ++
and --
while Python does not. Many people have suggested that ++x
can be rewritten as x += 1
. But this ignores the requirement that one be able to recover the resulting value of x
before or after incrementing / decrementing as part of a potentially complex bash expression eg:
x=$(( ++y + z--)).
I can find no way of converting the above to a python expression, because it appears python does not allow side effects such as assignment within an expression. A fall back would be to write a pre/post function that took a variable or string as input, and altered its external item so passed to the function. But I can't work out how to have a function alter its input parameter variables.
If I knew that the item being operated on was always an atomic value, I might be able to alter it by mapping its string name to the dictionary to recover this value and so modify it. But ++
has to work with anything bash might throw at it: eg ++y[1]
.
Is there any way of avoiding having to take such complex bash expressions containing assignments, and break them into separate python steps that build up the overall computation performed in bash, statement by statement. This would be pretty ugly.
I just need to implement call by reference somehow in python.
Upvotes: 1
Views: 157
Reputation: 241671
If you really want the functionality, it would be easy enough to create a Box
(MutableCell) type which supported mutating operators like preincrement and postincrement. But it would also be a lot of overhead, particularly since you would have to translate ((i=j))
into i = Box(j.unbox())
(or i.reset(j.unbox())
if you knew i
already existed.
Roughly speaking, it would look like this, except with a lot more checking for string vs. number, and appropriate logic in such cases.
class Box(object):
__slots__ = ["value"]
def __init__(self, value=None):
self.value = value
def unbox(self):
return self.value
def reset(self, value=None):
self.value = value
return value
def preincrement(self,inc=1):
self.value += inc
return self.value
def postincrement(self,inc=1):
tmp = self.value
self.value += inc
return tmp
Then you can translate, for example, x[i++] = --z + (t += 2) * u
(Yuk!) into:
x[i.postincrement()] = ( Box(z.preincrement(-1)
+ t.preincrement(2) * u.unbox())
Or you could use x[i.postincrement()].reset( ... )
if you had previously created x
as a defaultdict(Box)
.
But it's really hard to believe that it is worth the overhead.
Upvotes: 1