[MRAB]
>> There's another question that hasn't been asked yet: what should locals()
>> and globals() return?
[Tim, "globals()" is obvious, "locals()" can be surprising now]
> ...
And here recording the results of some code spelunking Dicts don't
really have anything to do with how locals are
Steven D'Aprano wrote:
y = 1
def func():
x = 2
return x+y
Here, there's a local environment as well as an implicit global one.
Surely we don't want to call this a closure?
Python probably isn't the best choice of language for the
point you're making, because even top-level functions
[MRAB]
>>> Would/should it be possible to inject a name into a local scope? You can't
>>> inject into a function scope, and names in a function scope can be
>>> determined statically (they are allocated slots), so could the same kind of
>>> thing be done for names in a local scope?
...
[Steven
[MRAB]
>>> Imagine renaming the specified names that are declared 'local'
>>> throughout the nested portion:
>>>
>>> def f():
>>> a = 10
>>> local local_a:
>>> def showa():
>>> print("a is", local_a)
>>> showa() # Raises NameError in showa because nothing bound
On 2018-05-01 19:12, Tim Peters wrote:
[MRAB]
> Imagine renaming the specified names that are declared 'local' throughout
> the nested portion:
>
> def f():
> a = 10
> local local_a:
> def showa():
> print("a is", local_a)
> showa() # Raises NameError in showa
[MRAB]
> By "inject" I mean putting a name into a namespace:
>
> import my_module
> my_module.foo = 'FOO'
>
> You can't insert a name into a function's body to make a new local variable.
So you do mean at runtime, I think. Then as before, you can do that
with module and the builtin
On 2018-05-01 16:23, Steven D'Aprano wrote:
On Mon, Apr 30, 2018 at 08:52:13PM -0500, Tim Peters wrote:
> Would/should it be possible to inject a name into a local scope? You can't
> inject into a function scope, and names in a function scope can be
> determined statically (they are allocated
On Tue, May 01, 2018 at 09:26:09PM +1200, Greg Ewing wrote:
> Steven D'Aprano wrote:
> >So what was the closure? If the surrounding function was still running,
> >there was no need to capture the running environment in a closure?
>
> You seem to be interpreting the word "closure" a bit
>
On 2018-05-01 04:40, Tim Peters wrote:
[MRAB]
>> Any binding that's not specified as local is bound in the parent scope:
[Tim]
> Reverse-engineering the example following, is this a fair way of
> making that more precise?
>
> Given a binding-target name N in scope S, N is bound in scope T,
On 2018-05-01 02:52, Tim Peters wrote:
[MRAB ]
> ...
> The intention is that only the specified names are local.
>
> After all, what's the point of specifying names after the 'local' if _any_
> binding in the local scope was local?
Don't look at me ;-) In the
[Tim]
> ...
> Here's an example where I don't know what the consequences of "the
> rules" should be:
>
> def f():
> a = 10
> local a:
> def showa():
> print("a is", a)
> showa() # 10
> a = 20
> showa() # 20
> a = 30
> showa() # 10
>
>
On Mon, Apr 30, 2018 at 08:52:13PM -0500, Tim Peters wrote:
> > Would/should it be possible to inject a name into a local scope? You can't
> > inject into a function scope, and names in a function scope can be
> > determined statically (they are allocated slots), so could the same kind of
> >
Steven D'Aprano wrote:
So what was the closure? If the surrounding function was still running,
there was no need to capture the running environment in a closure?
You seem to be interpreting the word "closure" a bit
differently from most people. It doesn't imply anything
about whether a
On Tue, May 01, 2018 at 06:06:06PM +1200, Greg Ewing wrote:
> Steven D'Aprano wrote:
> >Pascal, for example, had lexical scoping back in the 1970s, but
> >no closures.
>
> Well, it kind of had a limited form of closure. You could pass
> a procedure or function *in* to another procedure or
Steven D'Aprano wrote:
Pascal, for example, had lexical scoping back in the 1970s, but
no closures.
Well, it kind of had a limited form of closure. You could pass
a procedure or function *in* to another procedure or function
as a parameter, but there was no way to return one or pass it
out in
[MRAB]
>> Any binding that's not specified as local is bound in the parent scope:
[Tim]
> Reverse-engineering the example following, is this a fair way of
> making that more precise?
>
> Given a binding-target name N in scope S, N is bound in scope T, where
> T is the closest-containing scope
[MRAB ]
> ...
> The intention is that only the specified names are local.
>
> After all, what's the point of specifying names after the 'local' if _any_
> binding in the local scope was local?
Don't look at me ;-) In the absence of use cases, I don't know which
Tim Peters writes:
> Meaning "wonderfully clear" to the compiler, not necessarily to you
> ;-)
Is the compiler African or European (perhaps even Dutch)?
___
Python-ideas mailing list
Python-ideas@python.org
On 2018-04-30 21:41, Tim Peters wrote:
[MRAB ]
> I think it should be lexically scoped.
That's certainly arguable, but that's why I like real-code driven
design: abstract arguments never end, and often yield a dubious
in-real-life outcome after one side is worn out
[MRAB ]
> I think it should be lexically scoped.
That's certainly arguable, but that's why I like real-code driven
design: abstract arguments never end, and often yield a dubious
in-real-life outcome after one side is worn out and the other side
"wins" by attrition
[Tim, still trying to define `iseven` in one statement]
> even = (lambda n: n == 0 or odd(n-1))
> odd = (lambda n: False if n == 0 else even(n-1))
> iseven = lambda n: even(n)
...
> [and the last attempt failed because a LOAD_GLOBAL was generated
>instead of a more-general
On 2018-04-30 03:49, Tim Peters wrote:
[Soni L. ]
That ain't shadow. That is dynamic scoping.
I don't believe either term is technically accurate, but don't really care.
Shadowing is something different:
def f():
a = 42
def g():
print(a)
local a:
On Sun, Apr 29, 2018 at 01:36:31PM +1000, Chris Angelico wrote:
[...]
> > While I started off with Python 1.5, I wasn't part of the discussions
> > about nested scopes. But I'm astonished that you say that nested scopes
> > were controversial. *Closures* I would completely believe, but mere
> >
[Tim, on differences among Scheme-ish `let`, `let*`, `letrec` binding]
> ...
>
> You can play, if you like, with trying to define the `iseven` lambda
> here in one line by nesting lambdas to define `even` and `odd` as
> default arguments:
>
> even = (lambda n: n == 0 or odd(n-1))
> odd =
On Sat, Apr 28, 2018 at 11:20:52PM -0500, Tim Peters wrote:
> [Tim]
> >> Enormously harder to implement than binding expressions, and the
> >> latter (to my eyes) capture many high-value use cases "good enough".
>
> [Steven D'Aprano ]
> > And yet you're suggesting an
I really liked the syntax that mimicked lambda even if I find it verbose :
a = local x=1, y=2: x + y + 3
Even if I still prefer the postfix syntax :
a = x + 3 where x = 2
About scheme "let" vs "let*", the paralel in Python is :
a, b, c = 5, a+1, 2 # let syntax
a = 5; b = a+1; c = 2 # let*
[Soni L. ]
> That ain't shadow. That is dynamic scoping.
I don't believe either term is technically accurate, but don't really care.
> Shadowing is something different:
>
> def f():
> a = 42
> def g():
> print(a)
> local a:
> a = 43
>
On Sun, Apr 29, 2018 at 9:28 PM, Tim Peters wrote:
> [David Mertz ]
> > Ooops. My proof [of] anti-concept has a flaw. It only "shadows" names
> that
> > already exist. Presumably that's the wrong idea, but it's easy enough to
> > change if desired.
>
>
[David Mertz ]
> Ooops. My proof on anti-concept has a flaw. It only "shadows" names that
> already exist. Presumably that's the wrong idea, but it's easy enough to
> change if desired.
Even in the very early days when Python's runtime was more
relentlessly simple-minded than
On 04/29/2018 01:20 PM, Tim Peters wrote:
So, e.g.,
"""
a = 42
def showa():
print(a)
def run():
global a
local a: # assuming this existed
a = 43
showa()
showa()
"""
would print 43 and then 42. Which makes "local a:" sound senseless on
the face of it
Ooops. My proof on anti-concept has a flaw. It only "shadows" names that
already exist. Presumably that's the wrong idea, but it's easy enough to
change if desired.
On Sun, Apr 29, 2018 at 5:24 PM, Paul Moore wrote:
> On 29 April 2018 at 21:20, Tim Peters
On 29 April 2018 at 21:20, Tim Peters wrote:
> As covered most recently in an exchange with Tim Delaney, best I can
> tell absolutely nobody has wanted that. By "sublocal scope" they
> don't mean a full-fledged new scope at all, but a kind of limited
> "shadowing" of a
On Mon, Apr 30, 2018 at 6:45 AM, Tim Peters wrote:
> [Chris Angelico ]
>> So maybe the effective semantics should be:
>>
>> >>> (lambda a=3: (lambda b=a+1: (a, b))())()
>> (3, 4)
>
> Almost, but by that point the idea that this is already "easily
> spelled"
[Tim]
Then `c` is 12, but `a` is still 1 and `b` is still 2. Same thing in the
end:
c = local(a=3, b=4, a*b)
[Nikolaus Rath ]
>>> I think this can be done already with slighly different syntax:
>>>
>>> c = (lambda a=3, b=4: a*b)()
>>>
>>> The trailing ()
This doesn't address the fact no one actually needs it. But if we WANTED a
sublocal() context manager, we could spell it something like this:
In [42]: @contextmanager
...: def sublocal(**kws):
...: _locals = locals().copy()
...: _globals = globals().copy()
...: for k,
On Sun, Apr 29, 2018 at 7:22 PM, Mikhail V wrote:
> On Sun, Apr 29, 2018 at 3:30 AM, Tim Peters wrote:
>
>> Time to note another subtlety: people don't _really_ want "a new
>> scope" in Python. If they did, then _every_ name appearing in a
> If
[Ethan Furman ]
> If we need a sublocal scope, I think the most Pythonic* route to have it
> would be:
>
> with sublocal():
> blah blah
>
> which would act just like local/global does now:
>
> - any assignment creates a new variable
> - unless that variable
On Mon, Apr 30, 2018 at 5:55 AM, Tim Peters wrote:
> [Tim]
>>> Then `c` is 12, but `a` is still 1 and `b` is still 2. Same thing in the
>>> end:
>>>
>>> c = local(a=3, b=4, a*b)
>
> [Nikolaus Rath ]
>> I think this can be done already with slighly
[Tim]
>> Then `c` is 12, but `a` is still 1 and `b` is still 2. Same thing in the
>> end:
>>
>> c = local(a=3, b=4, a*b)
[Nikolaus Rath ]
> I think this can be done already with slighly different syntax:
>
> c = (lambda a=3, b=4: a*b)()
>
> The trailing () is a little ugly,
On 04/28/2018 10:16 AM, Tim Peters wrote:
... but do realize that since PEP 572 dropped any
notion of sublocal scopes, that recurring issue remains wholly
unaddressed regardless.
If we need a sublocal scope, I think the most Pythonic* route to have it would
be:
with sublocal():
On 2018-04-29 04:17 PM, Nikolaus Rath wrote:
On Apr 27 2018, Tim Peters
wrote:
Then `c` is 12, but `a` is still 1 and `b` is still 2. Same thing in the end:
c = local(a=3, b=4, a*b)
I think this can be done already with slighly
On Apr 27 2018, Tim Peters
wrote:
> Then `c` is 12, but `a` is still 1 and `b` is still 2. Same thing in the end:
>
> c = local(a=3, b=4, a*b)
I think this can be done already with slighly different syntax:
c = (lambda a=3, b=4: a*b)()
The
On 2018-04-29 18:01, Tim Peters wrote:
[Tim]
>> ...
>> This is the kind of code about which there have been background
>> complaints "forever":
>>
>> m1 = regexp1.match(line)
>> m2 = regexp2.match(iine)
>> if m1 and m2:
>> do all sorts of stuff with m1 and/or m2,
>>
2018-04-29 17:52 GMT+03:00 MRAB :
>
>
>> How about these:
>
> local m1, m2:
> m1 = regexp1.match(line)
> m2 = regexp2.match(line):
> if m1 and m2:
> ...
>
Is it possible to do the same thing, but with the help of `with`
On 04/27/2018 07:37 PM, Tim Peters wrote:
Idea: introduce a "local" pseudo-function to capture the idea of
initialized names with limited scope.
Note: the thing I'm most interested in isn't debates, but in whether
this would be of real use in real code.
I keep going back and forth on the
[Tim]
>> ...
>> This is the kind of code about which there have been background
>> complaints "forever":
>>
>> m1 = regexp1.match(line)
>> m2 = regexp2.match(iine)
>> if m1 and m2:
>> do all sorts of stuff with m1 and/or m2,
>> including perhaps modifying local
On Sun, Apr 29, 2018 at 3:30 AM, Tim Peters wrote:
>
> """
> Time to note another subtlety: people don't _really_ want "a new
> scope" in Python. If they did, then _every_ name appearing in a
> binding context (assignment statement target, `for` target, ...) for
> the
On 2018-04-29 07:57, Tim Peters wrote:
[Tim Delaney ]
My big concern here involves the:
if local(m = re.match(regexp, line)):
print(m.group(0))
example. The entire block needs to be implicitly local for that to work
-
what happens if I assign a new name in
[Tim Delaney ]
>>> My big concern here involves the:
>>>
>>> if local(m = re.match(regexp, line)):
>>> print(m.group(0))
>>>
>>> example. The entire block needs to be implicitly local for that to work
>>> -
>>> what happens if I assign a new name in that block?
Tim] Peters wrote:
>> The points to using function-call-like syntax were already covered
>> ("nothing syntactically new to learn there",
[Greg Ewing]
[> The trouble is that one usually expects "nothing syntactically
> new" to imply "nothing semantically new" as well, which is very
> far from the
Tim Peters wrote:
(ABC had
no lexical scoping either - nor, if I recall correctly, even textual
nesting of its flavor of functions).
If Python hadn't allowed textual nesting either, folks
might have been content to leave it that way. But having
textual nesting without lexical scoping was just
On Sun, 29 Apr 2018 at 10:30, Tim Peters wrote:
> [Tim Delaney ]
> > My big concern here involves the:
> >
>
> > if local(m = re.match(regexp, line)):
> > print(m.group(0))
> >
> > example. The entire block needs to be implicitly local
Tim Peters wrote:
The points to using function-call-like syntax were already covered
("nothing syntactically new to learn there",
The trouble is that one usually expects "nothing syntactically
new" to imply "nothing semantically new" as well, which is very
far from the case here. So I think
On 28/04/2018 04:34, Yury Selivanov wrote:
> Hi Tim,
>
> This is interesting. Even "as is" I prefer this to PEP 572. Below are some
> comments and a slightly different idea inspired by yours (sorry!)
>
> On Fri, Apr 27, 2018 at 10:41 PM Tim Peters wrote:
> [..]
>> As an
[Tim]
>> Enormously harder to implement than binding expressions, and the
>> latter (to my eyes) capture many high-value use cases "good enough".
[Steven D'Aprano ]
> And yet you're suggesting an alternative which is harder and more
> confusing.
I am? I said at the start
On Sun, Apr 29, 2018 at 12:50 PM, Steven D'Aprano wrote:
> On Sat, Apr 28, 2018 at 12:16:16PM -0500, Tim Peters wrote:
>> [Steven D'Aprano ]
>> > Chris' PEP 572 started off with the concept that binding expressions
>> > would create a "sub-local" scope,
I'm pretty sure the debate about braces defining scope in Python has
long-since ended...
--
Ryan (ライアン)
Yoko Shimomura, ryo (supercell/EGOIST), Hiroyuki Sawano >> everyone else
https://refi64.com/
On April 28, 2018 9:37:57 PM Ken Hilton wrote:
> local { m =
On Sat, Apr 28, 2018 at 12:16:16PM -0500, Tim Peters wrote:
> [Steven D'Aprano ]
> > Chris' PEP 572 started off with the concept that binding expressions
> > would create a "sub-local" scope, below function locals. After some
> > debate on Python-Ideas, Chris, Nick and Guido
> local { m = re.match(regexp, line)
>if m:
>print(m.group(0))
> }
Or how about making "local" a pseudo-statement of sorts?
local (m=re.match(exp, string)) {
if m:
print(m.group(0))
}
The grammar would be as follows:
local_stmt
To all of the following, I was talking about the syntax. Which
includes that all existing Python-aware editors and IDEs already know
how to format it intelligibly. It would be nice if they also colored
"local" (or "let") as a keyword, though.
For the rest, of course I'm already aware of the
Tim Peters wrote:
To the compiler, it's approximately nothing like "a
function call".
It's nothing like a function call to the user, either,
except in the most superficial of ways.
- The explicit parentheses make it impossible to misunderstand where
the expression begins or ends.
Except
let[x](EXPR)
x == EXPR
let[x](a=1)
x == 1
let[x](a=1, EXPR)
x == EXPR
let[x, y](a=1, EXPR)
x == 1
y == EXPR
let[x, y](a=1, b=2, EXPR)
x == 2
y == EXPR
z = let[x, y](a=1, EXPR)
x == 1
y == EXPR
z == (1, EXPR)
Anybody seeing how the above might be useful, and address some of the
concerns I've
[Tim Delaney ]
> My big concern here involves the:
>
> if local(m = re.match(regexp, line)):
> print(m.group(0))
>
> example. The entire block needs to be implicitly local for that to work -
> what happens if I assign a new name in that block?
I really don't know
On Sun, Apr 29, 2018 at 06:20:14AM +1000, Chris Angelico wrote:
> On Sun, Apr 29, 2018 at 6:04 AM, Ed Kellett wrote:
> > What if the names persist until the end of the statement?
[...]
> Oh, you mean exactly like PEP 572 used to advocate for? :)
Indeed. It was a bad
On Sat, 28 Apr 2018 at 12:41, Tim Peters wrote:
My big concern here involves the:
if local(m = re.match(regexp, line)):
print(m.group(0))
example. The entire block needs to be implicitly local for that to work -
what happens if I assign a new name in that block?
[Chris Angelico ]
> I'm concerned that there are, in effect, two quite different uses of
> the exact same syntax.
Yes, the construct implements a profoundly different meaning of
"scope" depending on the context it appears in.
> 1) In an arbitrary expression, local() creates a
On 2018-04-28 21:40, Tim Peters wrote:
> [Ed Kellett ]
>> How about if you just can't have an expression in a local()?
>
> See the quadratic equation example in the original post. When
> working with expressions, the entire point of the construct is to
> define
[Ed Kellett ]
> How about if you just can't have an expression in a local()?
See the quadratic equation example in the original post. When working
with expressions, the entire point of the construct is to define
(sub)local names for use in a result expression.
>
On Sun, Apr 29, 2018 at 6:04 AM, Ed Kellett wrote:
> On 2018-04-28 18:36, Chris Angelico wrote:
>> This makes reasonable sense. The parentheses completely enclose the
>> local scope. It's compiler magic, and you cannot explain it as a
>> function call, but it makes
On 2018-04-28 18:16, Tim Peters wrote:
> [Steven D'Aprano ]
>> But the biggest problem is that this re-introduces exactly the same
>> awful C mistake that := was chosen to avoid. Which of the following two
>> contains the typo?
>>
>> local(spam=expression, eggs=expression,
On 2018-04-28 18:36, Chris Angelico wrote:
> This makes reasonable sense. The parentheses completely enclose the
> local scope. It's compiler magic, and you cannot explain it as a
> function call, but it makes intuitive sense. But the same thing inside
> the if header itself would be much weirder.
[Steven D'Aprano ]
> Chris' PEP 572 started off with the concept that binding expressions
> would create a "sub-local" scope, below function locals. After some
> debate on Python-Ideas, Chris, Nick and Guido took the discussion off
> list and decided to drop the sub-local
>$(a=7, $(a=a+1, a*2))
I suspect you ALREADY have bash installed on your computer, you don't need
Python to emulate it.
On Sat, Apr 28, 2018 at 6:22 AM, Zero Piraeus wrote:
> :
>
> On 28 April 2018 at 07:07, Tim Peters wrote:
> > [...] For that
On 2018-04-27 11:37 PM, Tim Peters wrote:
A brain dump, inspired by various use cases that came up during the
binding expression discussions.
Idea: introduce a "local" pseudo-function to capture the idea of
initialized names with limited scope.
As an expression, it's
"local" "("
I have to say, this idea feels really nice to me. It's far easier to read
than := and separates the assignments and the result expression nicely.
Others have brought up the same problem of = vs ==. IMO a solution could be
to make a requirement that the last argument is NOT an assignment. In
On Sat, Apr 28, 2018 at 8:22 PM, Zero Piraeus wrote:
> I think I finally worked out why I have such a violent reaction to :=
> in the end, by the way: it's because it reminds me of Javascript's
> "===" (not the meaning, but the fact that it exists).
Out of morbid curiosity,
:
On 28 April 2018 at 07:07, Tim Peters wrote:
> [...] For that matter, I'd be fine too with shortening it to "let". In
> fact, I prefer that! Thanks :-)
If you really wanted to overcome objections that this looks too much
like a function, you could spell it "$". I'm not
On Fri, Apr 27, 2018 at 09:37:53PM -0500, Tim Peters wrote:
> A brain dump, inspired by various use cases that came up during the
> binding expression discussions.
>
> Idea: introduce a "local" pseudo-function to capture the idea of
> initialized names with limited scope.
[...]
Chris' PEP 572
On 28 April 2018 at 03:37, Tim Peters wrote:
> Idea: introduce a "local" pseudo-function to capture the idea of
> initialized names with limited scope.
This looks disturbingly good to me. I say "disturbingly" because the
amount of magic involved in that "function call" is
On Sat, Apr 28, 2018 at 2:07 AM Tim Peters wrote:
[...]
> Speaking of which, "sublocal" would be a more accurate name, and less
> likely to conflict with existing code names, but after people got over
> the shock to their sense of purity, they'd appreciate typing the
>
Hi Tim,
This is interesting. Even "as is" I prefer this to PEP 572. Below are some
comments and a slightly different idea inspired by yours (sorry!)
On Fri, Apr 27, 2018 at 10:41 PM Tim Peters wrote:
[..]
> As an expression, it's
> "local" "(" arguments ")"
> -
A brain dump, inspired by various use cases that came up during the
binding expression discussions.
Idea: introduce a "local" pseudo-function to capture the idea of
initialized names with limited scope.
As an expression, it's
"local" "(" arguments ")"
- Because it "looks like" a function
82 matches
Mail list logo