use "as" for block scope support

New submission from HaiYun Yan <lyricconch@gmail.com>: just like mozilla javascript "let" extension https://developer.mozilla.org/en/new_in_javascript_1.7#Block_scope_with_let_... according function args can have the default value let_stmt is unnecessary for python. ============example 1=========== f = None with open(...) as f: assert hasattr(f, "read") f = 1 assert f == 1 assert f is None ==========example 2============== try: e = None 1/0 except ZeroDivisionError as e: assert isinstance(e, ZeroDivisionError) except ... as e: # the same as except: but has the exception instance store to e assert isinstance(e, BaseException) else: assert e is None finally: assert e is None assert e is None ===========example 3============== while SEQ.next_availd() as tid: assert bool(tid) is True assert "tid" not in dir() ===========example 4============== assert "zero" not in dir() A = (id(None) % 1 as zero) zero + 5 assert A == 5 assert "zero" not in dir() ======example 5================== K = 1 A = (K+1 as K, K+2 as Q) K*Q assert A == 6 # (1+1) * (1+2) assert K==1 ============example 6=============== K = 1 A = (K+1 as K) (K+2 as K) K * K assert A == 16 # ((1+1) + 2) * ((1+1) + 2) assert K == 1

I *think* you're proposing that the variable named in the "as" clause should go out of scope when the blog ends. We already do a similar thing with "except ... as ...", but I don't see how we can do this without breaking backwards compatibility. I also don't think there is a particularly good reason to do (we did have a good reason in the case of except). Finally, with has lot of special semantics, you couldn't just use "with 2+2 as four: ...". --Guido On Mon, Jul 25, 2011 at 4:52 AM, 海韵 <lyricconch@gmail.com> wrote:
-- --Guido van Rossum (python.org/~guido)

On Mon, Jul 25, 2011 at 4:52 AM, 海韵 <lyricconch@gmail.com> wrote:
With some headscratching, I can figure out these examples. What I can't figure out is why you would possibly want to write code like this. It certainly doesn't enhance readability, and it wouldn't enhance performance or expressiveness of the language either. If you want to propose improvements to the language it should do at least one of those things. -1 as -1 --- Bruce Follow me: http://www.twitter.com/Vroo http://www.vroospeak.com

Dupilcate K is used only for describe the scope rule. Advantage: 1. the same grammer, the same behave "t" of """(x+y as t, x-y as s) t * s + s + t""" is only valid in the expression which require just as "e" of """except ... as e""" only live in the suite which it belongs 2. readability includes laconic a = (x+y as t, x-y as s) t * s + s + t it doesnt break thinking. from left to right, people finish thinking inplace. temp var will not keep in memory, people can forget them since they are not valid outside the expression. everything is clean. t, s = x+y, x-y a = t * s + s + t in this case, thinking is break and temp var keep in memory, people should take some care about it (for example, in nested loop) 3. this enchant the "lambda" syntax list.sort(key = lambda p: (sqrt(p.x**2+p.y**2) as r) r**2+ A*r + B) 2011/7/25 Bruce Leban <bruce@leapyear.org>:

On Mon, Jul 25, 2011 at 9:50 AM, 海韵 <lyricconch@gmail.com> wrote:
(x + y) * (x - y) + 2 * x is IMHO more readable - especially note the absence of y in the third term.
3. this enchant the "lambda" syntax list.sort(key = lambda p: (sqrt(p.x**2+p.y**2) as r) r**2+ A*r + B)
I don't know what "enchant" means here, but you can do this if you want: list.sort(key = lambda p: (lambda r: r**2 + A*r + B) (sqrt(p.x**2+p.y**2))) I'm not recommending that as I think it would be more readable to name that function so that it would be more clear why you're using that function as the sort key. But, to me, this example does not justify new syntax. --- Bruce

1. but what about ( t * s + t / s )? temp var always keep in memory. (should not reduce ( t + s ) to ( 2 * x ) since x, y may not a number. any operator here should be conside as independent function. ) 2. you got an extra lambda, that means: In runtime: lambda = MAKE_FUNCTION/MAKE_CLOSURE = PyFunction_New lambda call = CALL_FUNCTION = PyFrame_New + PyEval_EvalFrameEx all of them are heavy, (you can check the source code) but: as = PyCell_New as enter = SETUP_FINALLY = PyFrame_BlockSetup as leave = END_FINALLY = PyFrame_BlockPop which is much much much more more more cheaper than above. 3. try convert this to the lambda form as mention: R= lambda x, y: (x+y as t, x-y as s)(t * s as u, t/s as v)(u << v as p, u>>v as q) p ** q 2011/7/26 Bruce Leban <bruce@leapyear.org>:

海韵 wrote:
What about it? The temporary variables will go out of scope when the function exists, and be garbage collected, the same as every other local variable.
Sounds like premature optimization to me. I would like to see actual, real-world code where the performance bottleneck is setting up functions.
I wouldn't even *try* to convert that to a lambda. That is ugly, unmaintainable code. To understand it, I had to first write it out in block form: def R(x, y): with x+y as t, x-y as s: with t*s as u, t/s as v: with u << v as p, u >> v as q return p**q which is much simpler to read and maintain when written like this: def R(x, y): t, s = x+y, x-y u, v = t*s, t/s p, q = u << v, u >> v return p**q I consider this proposal to encourage excess and unnecessary encapsulation of variables. Not every expression needs to be it's own block. -- Steven

2011/7/26 Steven D'Aprano <steve@pearwood.info>: p, q = u<<v, u>>v A =p**q is it really ugly? why i feel pretty = =? Stage: first time we read <1> <2> <1> evaluation from left to right all the time. add -> as -> sub -> as -> enter -> mul -> as -> div -> as -> enter -> shl -> as -> shr -> as -> enter -> pow -> leaveall -> return note that in most case there are no dupilcate NAMEs. so enter can be igorn. just keep moving temporary things cleanup by leaveall.... no need to care about context, no one can read them, and they affect nothing <2> evaluation step by step and direction change every time add -> sub <- assign \/ mul -> div <- assign \/ shl -> shr -> assign \/ pow return should take some mind of context. it's possible that somewhere read the temporary var Stage: not the first time <1> calcing A; that is all, move next; <2> calc t,s; calc u,v; calc p,q; calc A; move next; step1-3 is useless.
<2>

As a 'Joe Developer', someone not a computer scientist but your 'average user', I'm going to have to step in and agree that the proposed syntax is *much* harder to read. I could follow Steven's code but the other code comes across as obfuscated. On Mon, Jul 25, 2011 at 5:24 PM, 海韵 <lyricconch@gmail.com> wrote:
-- 'Knowledge is Power' Daniel Greenfeld http://pydanny.blogspot.com http://cartwheelweb.com

On 7/25/2011 12:50 PM, 海韵 wrote:
2. readability includes laconic a = (x+y as t, x-y as s) t * s + s + t
t, s = x+y, x-y a = t * s + s + t
in this case, thinking is break and temp var keep in memory, people should take some care about it (for example, in nested loop)
I prefer this. Temporary names are almost never a problem. In a nested loop, the names are reused and the objects detached for gc.
3. this enchant the "lambda" syntax list.sort(key = lambda p: (sqrt(p.x**2+p.y**2) as r) r**2+ A*r + B)
I would rather delete lambda rather than enhance it. lambda expressions that refer to names other than the parameters are a constant source of confusion. To me, Python's mixed expression and statement syntax is a feature, not a wart to be avoided, as this suggestion aims to do. -- Terry Jan Reedy

I *think* you're proposing that the variable named in the "as" clause should go out of scope when the blog ends. We already do a similar thing with "except ... as ...", but I don't see how we can do this without breaking backwards compatibility. I also don't think there is a particularly good reason to do (we did have a good reason in the case of except). Finally, with has lot of special semantics, you couldn't just use "with 2+2 as four: ...". --Guido On Mon, Jul 25, 2011 at 4:52 AM, 海韵 <lyricconch@gmail.com> wrote:
-- --Guido van Rossum (python.org/~guido)

On Mon, Jul 25, 2011 at 4:52 AM, 海韵 <lyricconch@gmail.com> wrote:
With some headscratching, I can figure out these examples. What I can't figure out is why you would possibly want to write code like this. It certainly doesn't enhance readability, and it wouldn't enhance performance or expressiveness of the language either. If you want to propose improvements to the language it should do at least one of those things. -1 as -1 --- Bruce Follow me: http://www.twitter.com/Vroo http://www.vroospeak.com

Dupilcate K is used only for describe the scope rule. Advantage: 1. the same grammer, the same behave "t" of """(x+y as t, x-y as s) t * s + s + t""" is only valid in the expression which require just as "e" of """except ... as e""" only live in the suite which it belongs 2. readability includes laconic a = (x+y as t, x-y as s) t * s + s + t it doesnt break thinking. from left to right, people finish thinking inplace. temp var will not keep in memory, people can forget them since they are not valid outside the expression. everything is clean. t, s = x+y, x-y a = t * s + s + t in this case, thinking is break and temp var keep in memory, people should take some care about it (for example, in nested loop) 3. this enchant the "lambda" syntax list.sort(key = lambda p: (sqrt(p.x**2+p.y**2) as r) r**2+ A*r + B) 2011/7/25 Bruce Leban <bruce@leapyear.org>:

On Mon, Jul 25, 2011 at 9:50 AM, 海韵 <lyricconch@gmail.com> wrote:
(x + y) * (x - y) + 2 * x is IMHO more readable - especially note the absence of y in the third term.
3. this enchant the "lambda" syntax list.sort(key = lambda p: (sqrt(p.x**2+p.y**2) as r) r**2+ A*r + B)
I don't know what "enchant" means here, but you can do this if you want: list.sort(key = lambda p: (lambda r: r**2 + A*r + B) (sqrt(p.x**2+p.y**2))) I'm not recommending that as I think it would be more readable to name that function so that it would be more clear why you're using that function as the sort key. But, to me, this example does not justify new syntax. --- Bruce

1. but what about ( t * s + t / s )? temp var always keep in memory. (should not reduce ( t + s ) to ( 2 * x ) since x, y may not a number. any operator here should be conside as independent function. ) 2. you got an extra lambda, that means: In runtime: lambda = MAKE_FUNCTION/MAKE_CLOSURE = PyFunction_New lambda call = CALL_FUNCTION = PyFrame_New + PyEval_EvalFrameEx all of them are heavy, (you can check the source code) but: as = PyCell_New as enter = SETUP_FINALLY = PyFrame_BlockSetup as leave = END_FINALLY = PyFrame_BlockPop which is much much much more more more cheaper than above. 3. try convert this to the lambda form as mention: R= lambda x, y: (x+y as t, x-y as s)(t * s as u, t/s as v)(u << v as p, u>>v as q) p ** q 2011/7/26 Bruce Leban <bruce@leapyear.org>:

海韵 wrote:
What about it? The temporary variables will go out of scope when the function exists, and be garbage collected, the same as every other local variable.
Sounds like premature optimization to me. I would like to see actual, real-world code where the performance bottleneck is setting up functions.
I wouldn't even *try* to convert that to a lambda. That is ugly, unmaintainable code. To understand it, I had to first write it out in block form: def R(x, y): with x+y as t, x-y as s: with t*s as u, t/s as v: with u << v as p, u >> v as q return p**q which is much simpler to read and maintain when written like this: def R(x, y): t, s = x+y, x-y u, v = t*s, t/s p, q = u << v, u >> v return p**q I consider this proposal to encourage excess and unnecessary encapsulation of variables. Not every expression needs to be it's own block. -- Steven

2011/7/26 Steven D'Aprano <steve@pearwood.info>: p, q = u<<v, u>>v A =p**q is it really ugly? why i feel pretty = =? Stage: first time we read <1> <2> <1> evaluation from left to right all the time. add -> as -> sub -> as -> enter -> mul -> as -> div -> as -> enter -> shl -> as -> shr -> as -> enter -> pow -> leaveall -> return note that in most case there are no dupilcate NAMEs. so enter can be igorn. just keep moving temporary things cleanup by leaveall.... no need to care about context, no one can read them, and they affect nothing <2> evaluation step by step and direction change every time add -> sub <- assign \/ mul -> div <- assign \/ shl -> shr -> assign \/ pow return should take some mind of context. it's possible that somewhere read the temporary var Stage: not the first time <1> calcing A; that is all, move next; <2> calc t,s; calc u,v; calc p,q; calc A; move next; step1-3 is useless.
<2>

As a 'Joe Developer', someone not a computer scientist but your 'average user', I'm going to have to step in and agree that the proposed syntax is *much* harder to read. I could follow Steven's code but the other code comes across as obfuscated. On Mon, Jul 25, 2011 at 5:24 PM, 海韵 <lyricconch@gmail.com> wrote:
-- 'Knowledge is Power' Daniel Greenfeld http://pydanny.blogspot.com http://cartwheelweb.com

On 7/25/2011 12:50 PM, 海韵 wrote:
2. readability includes laconic a = (x+y as t, x-y as s) t * s + s + t
t, s = x+y, x-y a = t * s + s + t
in this case, thinking is break and temp var keep in memory, people should take some care about it (for example, in nested loop)
I prefer this. Temporary names are almost never a problem. In a nested loop, the names are reused and the objects detached for gc.
3. this enchant the "lambda" syntax list.sort(key = lambda p: (sqrt(p.x**2+p.y**2) as r) r**2+ A*r + B)
I would rather delete lambda rather than enhance it. lambda expressions that refer to names other than the parameters are a constant source of confusion. To me, Python's mixed expression and statement syntax is a feature, not a wart to be avoided, as this suggestion aims to do. -- Terry Jan Reedy
participants (6)
-
Bruce Leban
-
Daniel Greenfeld
-
Guido van Rossum
-
Steven D'Aprano
-
Terry Reedy
-
海韵