Re: Another try at Python's selfishness
Donn Cave wrote: Quoth [EMAIL PROTECTED]: | Still see no problem. Of course, it goes without saying that | Python 2.4 doesn't work this way, but given that it's theoretically | possible for f(a) to be resolved similarly to a.f, then I really | do not see what you're seeing here. The kwargs parameter appears | irrelevant from where I'm sitting. | | Then either you didn't understand my answers, or I didn't understand | your idea. Could you summarize how exactly f(x,y=z) should be | resolved, i.e. where it should look for f? a.f == f(a) So, if the compiler recognizes the tokens a.f, it should treat them as if it found the tokens f(a). But that wouldn't do what you want. You want it to do something different if it found the tokens f(a). I would agree that I didn't understand your answers, but they weren't really answers so much as questions, along the lines of ``well then, how would this work?'' I seem to have missed what you were driving at, but maybe if you were to just came out and explain the point? You do know what a rethorical question is? The first point is: Python has global functions, as well as methods. If f(a) should look up f inside a first, that would shadow any global or local f. That's bad, because python is dynamically typed, and you sometimes down' know what a is. Things like open(filename) or tuple(a,b,c) could behave completely unexpected, if filename had an open or a a tuple attribute. The other point is: Python supports named arguments. The algorithm to put positional and named arguments into the right parameters is rather tricky, and it _must_ know the function that's being called to work. So, you simply can't make function lookup depend on the parameters, it's a hen-egg problem. Of course the whole business is kind of a joke, since there is no way anyone in their right mind would wish to change Python's notation for such trivial reasons, but there actually are languages that resolve functions based on argument types. Overloading in C++ is somewhat like this, Haskell's typeclass mechanism, and there is a ``multiple dispatch'' model that I have no experience with but is not without its supporters. Yes, but both C++ and Haskell are statically typed, and neither supports named arguments. (We're talking about one function operating on one object, so I don't see what multiple dispatch has to do with this) -- http://mail.python.org/mailman/listinfo/python-list
Re: Another try at Python's selfishness
That usage (self is second parameter to B.test) is bound to cause trouble in general, but in this case doesn't have any effect I can see. The function call test would be resolved from its first parameter, instance of A, and that function would return 1. One of us is missing something here, could be me. Probably my example wasn't clear, let's try another: class A: def test(a, **kwargs): return 1 class B: def test(b, **kwargs): return 2 test(a=A(), b=B()) self isn't a keyword, so nothing should forbid this code. What is the interpreter to do if it stumbles across this test call? I mean, named-argument lookup is a tricky thing even if you do know what function you're calling. If this would depend on one of the parameters, I think it would become completely unintelligible. (you can think of more complex examples yourself) That's exactly the problem, it doesn't read from left to right, because we swap back and forth between function(parameter and parameter.function notation. That's because they're doing two different things: object.method() does an attribute lookup, while function(parameter) looks for the function in the current scope. -- http://mail.python.org/mailman/listinfo/python-list
Re: Another try at Python's selfishness
Yes, that's what I had in mind when I said it could be made recursion-safe. It's still not thread-safe, but I think that could be done too, using thread-local-variables instead of globals. class TestB: @memberFunction def do(x): z = __ # lambda's shouldn't directly reference '__' x.do(lambda : z) Yes, that's what I meant when I said it wasn't lambda-safe. That means a completely legal and (in my code) common expression can behave totally unexpected. Would be a no-go for me. But I think it gets worse: class TestA: @memberFunction def do(): yield 1 yield 2 yield __ class TestB: @memberFunction def bar(): for x in TestA().do(): print x TestB().bar() Doesn't behave as expected, and the only way I can see to fix it would be to declare a local function inside TestA's do function... -- http://mail.python.org/mailman/listinfo/python-list
Re: Another try at Python's selfishness
First of all, you are using a really poor example of a method, since it doesn't use any attributes of the Foo instance. Agreed. I tried to post a short example, and it obviously was to short to make my point clear. lets take a longer one. Current syntax: class Pair: def __init__(self, a,b): self.a = a self.b = b def sum(self): return self.a + self.b def product (this): return this.a + this.b My alternative syntax suggestion would be this one: class Pair: def self.__init__(a,b): self.a = a self.b = b def self.sum(): return self.a + self.b def this.product (): return this.a + this.b You are really giving self a magic meaning with your suggestion which isn't needed at all. No. I hope this is clearer in the example above. self shouldn't be a keyword. It's a special kind of argument now, so why shouldn't we explicitly _declare_ that it's a special kind of argument? (as explicit is better than implicit) So far, the existence of x.y somewhere in Python always implied that x was already introduced explicitly in the program, Yes, but y(x) also implies that x and y have been introduced explicitly before, unless it's in a def statement. The def statement always introduces new variables. and you suggest that we violate that both in the def self.x-row, and inside the methods when we access attributes. def x(self): declares two new identifiers, x and self Why shouldn't def self.x(): declare two new identifiers (x and self), too? Attribute acces wouldn't change. -- http://mail.python.org/mailman/listinfo/python-list
Re: Another try at Python's selfishness
I still see newbie-friendliness as a MAJOR plus for Python -- it increases the chance that users of your software will become contributors. Yes, I 100% agree to that point! But the point is, the current situation is not newbie-friendly (I can tell, I am a newbie): I declare a method with 3 parameters but when I call it I only pass 2 parameters. That's confusing. If I declare a member variable, I write: self.x = ValueForX, why can't I be equally explicit for declaring member functions? -- http://mail.python.org/mailman/listinfo/python-list
Re: Another try at Python's selfishness
You could try running it to see: class A: ... def test(a, **kwargs): return 1 ... class B: ... def test(b, **kwargs): return 2 ... test(a=A(), b=B()) Traceback (most recent call last): File stdin, line 1, in ? NameError: name 'test' is not defined Oops! You have defined a name test in two namespaces, the class A and the class B, but there is no name test in the global namespace you are trying to run it in. Since namespaces are critical to Python, your test code is a problem that just cannot happen in Python. It is a non-issue. Python will not get confused between the two definitions of test. I've been answering to Donn Cave's suggestion. Read it, and you will understand what I mean. As near as I can tell, your original complaint might be solved simply: it seems to me that you are concerned about that extraneous self parameter for methods that don't need it: No, I wasn't talking about functions that don't use the self parameter. I rarely ever have such functions. I just tried to make the example as short as possible. -- http://mail.python.org/mailman/listinfo/python-list
Re: Another try at Python's selfishness
... Unfortunately, none of this suggests that it's reasonable to have def x.y(z): ... mean the same as def y(x, z): ... Actually, it shouldn't. The idea was, that def x.y(z): ... (explicitly) introduces an unbound method. That's not introducing a new conect to python, it's just making the difference between an unbound method and a not-bindable function explicit. Currently, def(x,y): ... can mean two different things: In the context of a class, it introduces an unbound method, in global or local contexts it introduces a function. I don't want to have a new syntax for that, I want two different syntaxes for these two different meanings. and I have no idea of how it would generalize to def x.y.z(t): ... Nor do I. Is that a problem? -- http://mail.python.org/mailman/listinfo/python-list
Re: Another try at Python's selfishness
Still see no problem. Of course, it goes without saying that Python 2.4 doesn't work this way, but given that it's theoretically possible for f(a) to be resolved similarly to a.f, then I really do not see what you're seeing here. The kwargs parameter appears irrelevant from where I'm sitting. Then either you didn't understand my answers, or I didn't understand your idea. Could you summarize how exactly f(x,y=z) should be resolved, i.e. where it should look for f? -- http://mail.python.org/mailman/listinfo/python-list
Another try at Python's selfishness
Having read previous discussions on python-dev I think I'm not the only Python programmer who doesn't particularly like python's self parameter: class Foo: def bar(self, a,b): return a+b Foo().bar(1,2) = 3 The main reason (at least for me) is that there's simply too much magic in it. Why does the expression left of the '.' get promoted to the first parameter? It even goes further: Foo.bar(Foo(), 1,2) works, but: Foo.bar(1,2,3) doesn't, just because of the magical first parameter in a member function. But: Foo.__dict[bar]__(1,2,3) Does work. The point is, I _do_ think it's a good idea to explicitly write self.SomeMember for member-access, so I thought: why can't we be equally explicit about member function declaration? Wouldn't it be nice if I could write (say, in Python 3k, or maybe later): class Foo: def self.bar(a,b): return a+b Foo().bar(1,2) = 3 That way, the declaration would match the invocation (at least syntactically), and the magic-feeling is gone. In the long run, the old-style syntax (i.e. if there's no '.' in the method name) could be used for static methods. What do you think? -- http://mail.python.org/mailman/listinfo/python-list
Re: Another try at Python's selfishness
write(sys.stdin, split(read(open(file, 'r')))[0]) So, if I got you right, the interpreter would have to interpret this line like this: 1. Evaluate the first parameter of the first function (sys.stdin) 2. Look up the attribute write in this object 3. evaluate the first parameter of the split function - 4. evaluate the first parameter of the read function - 5. evaluate file (I guess this is a local string variable?) 6. try attribute lookup open on the string 7. fail - call the global open function 8. lookup read in that object, call it 9. attribute lookup split on the returned object 10. call __getitem__(0) 11. pass the parameters to the write function from (1) Is this correct? My main problems are that you have to guess at step 6/7, and that the order of evaluation makes me a little dizzy ;-) Also, member functions seem to shadow global ones, what if I wanted to use some global split function I've written myself instead of the string's one. If I was mean, I'd ask you what this one does: class A: def test(self, this): return 1 class B: def test(this, self): return 2 test(self=A(), this=B()) The current call syntax at least can be read from left-to-right, and you always know whether you call a member function or a global one. -- http://mail.python.org/mailman/listinfo/python-list
Re: Another try at Python's selfishness
Definitely looks interesting. I'd like it more if it was more explicit, but still, it does look nice. I guess you could make it recursion-safe if you saved/restored the global __ variable before/after calling the actual function, and probably there's a way to make it thread-safe, too. But how would you make it generator-safe? Also, wouldn't lambda's you pass around from object to object be bound to use the wrong instance? How would you fix this code: class TestA: @memberFunction def do(f): print f() class TestB: @memberFunction def do(x): x.do(lambda : __) TestB().do(TestA()) # should print out TestB, does print out TestA There really should be something like a wiki for selfishness-proposals with pros and cons, so I could have looked at some before thinking about my own one... -- http://mail.python.org/mailman/listinfo/python-list