Re: [Python-ideas] PEP-3150

On Wed, Apr 13, 2011 at 3:48 PM, Nick Coghlan <ncoghlan@gmail.com> wrote:
On Thu, Apr 14, 2011 at 8:33 AM, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
So, in the case of def decorator(f): return decorated given: "Docstring A..." def decorated(*args, **kwargs): "Docstring B..." do something... it would be docstring A that gets put on the decorated function, not docstring B? I guess I can kind of see the reasoning there, but it seems a little weird. Also, this case (and the general issue of callbacks, thunks, etc.) seems to be crying out for a special convenience syntax to save a level indenting. But would that just add needlessly to the complexity of the language? -- Carl

On Thu, Apr 14, 2011 at 3:46 PM, Carl M. Johnson <cmjohnson.mailinglist@gmail.com> wrote:
Yep, but if it was designed that way from the start, people simply wouldn't include the inner docstring. I'm not completely sold on this particular idea as yet, but it's one I'll explore further in the next update of the PEP.
Given that PEP 3150 itself is already highly vulnerable to that last accusation, I'm going to go with "Yes" :) Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

Carl M. Johnson wrote:
That seems like a contrived example. If you wanted the function to have Docstring B, why did you give the given block a docstring of its own in the first place?
In this particular case (i.e. a function that does nothing but define and return another function) I'd like to be able to write def decorator(f)(*args, **kwargs): do something... but that's a subject for another hotly-debated PEP! -- Greg

On Wed, Apr 13, 2011 at 10:06 PM, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
Interesting, but could that be extended to support making a throwaway key function for sorted? With given it's obviously sorted_list = sorted(original_list, key=keyfunc) given: def keyfunc(item): item = item.replace(" ", "") item = item.lowercase() ... return item but I can't see how that your proposal could be expanded beyond the one use case of decorator making, and today it's already possible to make a simple decorator decorator that injects f as the first arg: class MetaDec: def __init__(self, dec): self.dec = dec def __call__(self, f): def callme(*args, **kwargs): return self.dec(f, *args, **kwargs) return callme @MetaDec def logger(f, *args, **kwargs): print("Logging...") return f(*args, **kwargs) @logger def foo(): print("Foo!") I think the recipe for something like this is already in the docs somewhere... Obviously, a built-in syntax for simple decorators might have some savings in efficiency, but I would be surprised if it were especially noteworthy, since decoration typically happens many fewer times than function invocation. Hmm, as I look at the given syntax here again, I find that I don't mind the extra level of indention. Also, you can add another docstring to clarify things a bit: sorted_list = sorted(original_list, key=keyfunc) given: "A list of widgets sorted by removing whitespace and lowercasing..." def keyfunc(item): ...
help(sorted_list) "A list of widgets sorted by removing whitespace and lowercasing..."

On Thu, Apr 14, 2011 at 9:47 PM, Carl M. Johnson <cmjohnson.mailinglist@gmail.com> wrote:
Alas, it isn't going to be quite that simple:
I don't see adding an extra pointer slot that will rarely be used to the mutable builtins flying, and obviously the immutable types can't reasonably accept a docstring that may vary by instance without completely destroying their caching strategies. Making the docstring available as a __doc__ variable in the given namespace could potentially work, but I'm not sure the idea offers much over an ordinary triple-quoted string variable at that point. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

1. I don't like the special-cased docstring, but I suppose I could simply opt to not use it myself. 2. I actually do like the added indentation; for me, a big point with the given-statement is the readability, and the indentation hints at the block's "secondary" nature and guides you toward the "primary" statement. One idea is to allow combining given and def: orderly = sorted(disorderly, key=getscore) given def getscore(item): return item.score -- Dag

On 14 Apr 2011, at 16:00, dag.odenhall@gmail.com wrote:
orderly = sorted(disorderly, key=getscore) given def getscore(item): return item.score
To me, this is not as readable as: orderly = sorted(disorderly, key=getscore) given: def getscore(item): return item.score Also, the related following is a good argument IMHO to allow expression statements before "given" mylist.sort(key=getscore) given: def getscore(item): return item.score If they were disallowed, I bet we would get "idioms" like: _ = mylist.sort(key=getscore) given: def getscore(item): return item.score -- Arnaud

On 14 April 2011 18:34, Arnaud Delobelle <arnodel@gmail.com> wrote:
I agree, I disliked the idea myself. There might be situations where it'd be handy but I'm not convinced. If you need it because the code is already indented several levels, it is likely that you won't fit the "given def" on the same line anyway. If the function body is just one statement you can inline it: orderly = sorted(disorderly, key=getscore) given: def getscore(item): return item.score If the function is larger and you're already deeply indented you should probably refactor the code anyway.
Certainly agree - I didn't know it was proposed to limit it to assignment?

dag.odenhall@gmail.com wrote:
I think I would actually prefer the 3-line version. There's too much important stuff going on way over on the right there. But here's another idea: orderly = sorted(disorderly, key = score) given: score(item) = item.score -- Greg

On Thu, Apr 14, 2011 at 3:46 PM, Carl M. Johnson <cmjohnson.mailinglist@gmail.com> wrote:
Yep, but if it was designed that way from the start, people simply wouldn't include the inner docstring. I'm not completely sold on this particular idea as yet, but it's one I'll explore further in the next update of the PEP.
Given that PEP 3150 itself is already highly vulnerable to that last accusation, I'm going to go with "Yes" :) Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

Carl M. Johnson wrote:
That seems like a contrived example. If you wanted the function to have Docstring B, why did you give the given block a docstring of its own in the first place?
In this particular case (i.e. a function that does nothing but define and return another function) I'd like to be able to write def decorator(f)(*args, **kwargs): do something... but that's a subject for another hotly-debated PEP! -- Greg

On Wed, Apr 13, 2011 at 10:06 PM, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
Interesting, but could that be extended to support making a throwaway key function for sorted? With given it's obviously sorted_list = sorted(original_list, key=keyfunc) given: def keyfunc(item): item = item.replace(" ", "") item = item.lowercase() ... return item but I can't see how that your proposal could be expanded beyond the one use case of decorator making, and today it's already possible to make a simple decorator decorator that injects f as the first arg: class MetaDec: def __init__(self, dec): self.dec = dec def __call__(self, f): def callme(*args, **kwargs): return self.dec(f, *args, **kwargs) return callme @MetaDec def logger(f, *args, **kwargs): print("Logging...") return f(*args, **kwargs) @logger def foo(): print("Foo!") I think the recipe for something like this is already in the docs somewhere... Obviously, a built-in syntax for simple decorators might have some savings in efficiency, but I would be surprised if it were especially noteworthy, since decoration typically happens many fewer times than function invocation. Hmm, as I look at the given syntax here again, I find that I don't mind the extra level of indention. Also, you can add another docstring to clarify things a bit: sorted_list = sorted(original_list, key=keyfunc) given: "A list of widgets sorted by removing whitespace and lowercasing..." def keyfunc(item): ...
help(sorted_list) "A list of widgets sorted by removing whitespace and lowercasing..."

On Thu, Apr 14, 2011 at 9:47 PM, Carl M. Johnson <cmjohnson.mailinglist@gmail.com> wrote:
Alas, it isn't going to be quite that simple:
I don't see adding an extra pointer slot that will rarely be used to the mutable builtins flying, and obviously the immutable types can't reasonably accept a docstring that may vary by instance without completely destroying their caching strategies. Making the docstring available as a __doc__ variable in the given namespace could potentially work, but I'm not sure the idea offers much over an ordinary triple-quoted string variable at that point. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

1. I don't like the special-cased docstring, but I suppose I could simply opt to not use it myself. 2. I actually do like the added indentation; for me, a big point with the given-statement is the readability, and the indentation hints at the block's "secondary" nature and guides you toward the "primary" statement. One idea is to allow combining given and def: orderly = sorted(disorderly, key=getscore) given def getscore(item): return item.score -- Dag

On 14 Apr 2011, at 16:00, dag.odenhall@gmail.com wrote:
orderly = sorted(disorderly, key=getscore) given def getscore(item): return item.score
To me, this is not as readable as: orderly = sorted(disorderly, key=getscore) given: def getscore(item): return item.score Also, the related following is a good argument IMHO to allow expression statements before "given" mylist.sort(key=getscore) given: def getscore(item): return item.score If they were disallowed, I bet we would get "idioms" like: _ = mylist.sort(key=getscore) given: def getscore(item): return item.score -- Arnaud

On 14 April 2011 18:34, Arnaud Delobelle <arnodel@gmail.com> wrote:
I agree, I disliked the idea myself. There might be situations where it'd be handy but I'm not convinced. If you need it because the code is already indented several levels, it is likely that you won't fit the "given def" on the same line anyway. If the function body is just one statement you can inline it: orderly = sorted(disorderly, key=getscore) given: def getscore(item): return item.score If the function is larger and you're already deeply indented you should probably refactor the code anyway.
Certainly agree - I didn't know it was proposed to limit it to assignment?

dag.odenhall@gmail.com wrote:
I think I would actually prefer the 3-line version. There's too much important stuff going on way over on the right there. But here's another idea: orderly = sorted(disorderly, key = score) given: score(item) = item.score -- Greg
participants (5)
-
Arnaud Delobelle
-
Carl M. Johnson
-
dag.odenhall@gmail.com
-
Greg Ewing
-
Nick Coghlan