On Nov 5, 2004, at 9:40 AM, Leopold Toetsch wrote:

Jeff Clites <[EMAIL PROTECTED]> wrote:

a) As Sam says, in Python "y**z" is just shorthand for
"y.__pow__(z)"--they will compile down to exactly the same thing
(required for Python to behave correctly).

I don't think so (and you can replace with add, sub, ... FWIW). All these
binops compile to Parrot opcodes.

I'm saying that, by Python semantics they do the same thing--it's an open question how they should compile, that's what we're discussing. It is true that in the "real" Python they do compile to different Python ops (probably for historical reasons), but semantically they are identical. And importantly, not only do they produce the same results, but also there's never a case in which one works and the other produces an error.


These call the MMD dispatcher. Now
depending on the type of left and right, we e.g. call into a function
living in classes/*.pmc that does the Right Thing.

A plain PMC does the binop (if it "can" do it). If it's a an object
derived from a PMC it either delegates to the PMC or, if provided by the
user to the __pow__ function. If it's an object it does a full method
lookup for that object ...

In Python, semantically you know that you'll end up doing a method call (or, behaving as though you had), so it's very roundabout to do a method call by using an op which you know will fall back to doing a method call. Clearer just to do the method call.


And currently, PerlInts used in Python code would handle "a + b", but fail for "a.__add__(b)" (since that method isn't defined, currently). That breaks an invariant of Python--"a + b" should work if-and-only-if "a.__add__(b)" would, and should product the same result. Compiling to ops, this isn't guaranteed, and currently in fact doesn't happen. Real Python behaves as though infix operators are just an alternate syntax for certain method calls. And Ruby explicitly defines them this way--infix notation is just a syntax trick. (Note: not true for *all* operators, but at least for the mathematical infix operators.)

... Since __pow__ isn't
"special", we don't need anything to support it that we wouldn't need
for any other arbitrary method, say "y.elbowCanOpener(z)".

No. One is builtin and one isn't. These are really different. The only common thing is that the former can be overridden, while the latter is always provided by user code.

I wouldn't describe that at "can be overridden". If I define my own class, __pow__ is implemented on that class if-and-only-if I define it, just like any other method. I'm not overriding any default behavior--if I don't define it, it's just not there for my class.


The only thing that's special is that there are certain built-in classes, and some of them implement __pow__, but that's not really anything special about __pow__.

So I don't think an op really gives us what we want.

This sentence would obviously be true for all binops then. It isn't.

Yes, I think it's true for most of our PMC ops.

And even the ops we currently have are broken semantically. Consider "a = b + c" in Python. This can't compile to add_p_p_p, because for that op to work, you have to already have an existing object in the first P register specified. But in Python, "a" is going to hold the result of "b + c", which in general will be a new object and could be of any type, and has nothing to do with what's already in "a". I don't seem to have any way to add 2 PMCs, and have as the result a third PMC, whose type is not known at compile-time.

So yes, I am pointing out what I think is a larger design problem in Parrot--it's not specific to "pow" at all. And I think that we should not define PMC ops just because corresponding I or N ops exist. I think we should create PMC-based ops only if one of the following criteria are met: (a) there's no other reasonable way to provide some needed functionality, (b) there is some significant performance benefit to providing it as an op, or (c) it's needed to provide some interpreter functionality like "invoke", but I think that this case is already covered by (a) and (b). Using methods when possible would let us get rid of most of the PMC ops, including things such as "pow" which make no sense for most PMC types, and leave us with a smaller set that makes more sense across PMC types.

JEff



Reply via email to