Re: [Python-ideas] Crazy idea: allow keywords as names in certain positions

2018-05-13 Thread Nick Coghlan
On 13 May 2018 at 14:19, Guido van Rossum  wrote:

> As anyone still following the inline assignment discussion knows, a
> problem with designing new syntax is that it's hard to introduce new
> keywords into the language, since all the nice words seem to be used as
> method names in popular packages. (E.g. we can't use 'where' because
> there's numpy.where
> ,
> and we can't use 'given' because it's used in Hypothesis
> .)
>
> The idea I had (not for the first time :-) is that in many syntactic
> positions we could just treat keywords as names, and that would free up
> these keywords.
>

While I think the "restricted use" idea would be confusing, I do like the
idea of separating out "postfix keywords", which can't start a statement or
expression, and hence can be used *unambiguously* as names everywhere that
names are allowed.

Adding such a capability is essential to proposing a keyword based approach
to inline assignments, and would technically also allow "and", "or", "is",
and "as" to be freed up for use as names.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] "given" vs ":=" in list comprehensions

2018-05-13 Thread Nick Coghlan
On 12 May 2018 at 20:34, Andre Roberge  wrote:

> Sorry for chiming in so late; I was lurking using google groups and had to
> subscribe to post - hence this new thread.
>
> I gather that *where* has been discarded as a possible new keywords given
> its use as a function in numpy (https://docs.scipy.org/doc/
> numpy-1.14.0/reference/generated/numpy.where.html) ...  Still, I will
> include it below for completeness (and as I think it reads better than the
> other choices)
>

The same grammar adjustment that I believe will allow "given" to be used as
both a postfix keyword and as a regular name would also work for "where".
However, "where" still has the problem of semantically conflicting with
SQL's use of it to introduce a filter clause, whereas Hypothesis uses
"given" to bind names to values (just a little more indirectly than would
be the case for assignment expressions)

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Tim Peters
[Steven D'Aprano ]
>>> ...
>>> average = 0
>>> smooth_signal = [(average := (1-decay)*average + decay*x) for x in signal]
>>> assert average == smooth_signal[-1]

[Tim]
>> The scope issues are logically independent of assignment-expression
>> spelling, but it's a pretty safe guess Nick is opposed to that example
>> ever "just working" regardless of spelling, while PEP 572 doesn't
>> currently support it anyway.


[Nick Coghlan ]
> I'm personally fine with that example working

"Just working" meant "exactly as written".  "Regardless of spelling"
meant whether binding is spelled via ":=", "given", "as", "where",
"let ... in ...' "->", ..


> if there's an explicit nonlocal declaration on "average" in the nested
> scope - it's Guido that objected to requiring the explicit scoping
> declaration to access that behaviour.

I suspect, but don't know, that Guido would like that example to "just
work" because it _looks like_ it should "just work".  There's no
visible function involved, and _needing_ to add scope declarations to
make it work is pretty much inexplicable unless the user first learns
more than most users "should" need to learn about how it's
implemented.

If so, no technical argument will change his mind - and especially not
one based on "but the implementation today doesn't do that already".
Recall that Python had no lexically nested scoping at first?  If he
wanted to _make_ users learn about nested lexical scopes to use Python
features that don't _appear_ to use it, Python would have had it from
the start ;-)

I'd be happy enough with needing an explicit declaration too, but am
_happiest_ with what I'm guessing Guido's view is.


> For the implicit version, my request is that any PEP proposing the idea of
> parent local scoping be held to the standard of *actually drafting the patch
> for the language specification*,

Of course.


> rather than handwaving away the hard problems that it creates
> (i.e. what to do at class scope,

I finally looked at class scope and quickly decided it makes no sense
there (a comprehension at class scope has no access to the class
scope, so "same scope in the comprehension as in its immediately
containing block" is incoherent in that case).


> what to do when multiple generators expressions reference the same
> nonlocal name,

Then, as you said, they access the same nonlocal name.  What of it?
What if two generator functions reference (or even rebind) the same
nonlocal name?  What's unclear about that?

If you were happy with explicit scope declarations, then exactly the
same thing would happen as if the user were forced to explicitly
declare the scopes chosen for them.


> what to do with nested comprehensions,

Again, if you were happy with explicit scope declarations, then
exactly the same ...

Where are the docs explaining how nested comprehensions work today?  I
haven't seen any.  If any such exist, I'd bet nothing about them needs
to be changed.  If none such exist, I don't see a need to write any
just for this PEP.  How do nested expressions of any kind work?  Same
thing.

The only thing the suggestion changes is the scope of assignment
expression targets in synthetic functions created to implement
comprehensions.  That has nothing at all to do with the possibility of
nesting, or with the structure of nesting.  Why do you think it does -
or might?


> how to expand comprehensions using this kind of scoping to their statement
> form in a context independent way).

I've already explained why I view that as a non-issue (making a
tedious manual process a relative handful of users undertake once in
their life for self-education purposes slightly less tedious has
approximately no value to me - and, to the contrary, the "context
dependent" bits they may have to learn would make it _more_
educational).  If that's a show-stopper for you, so be it.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Nick Coghlan
On 12 May 2018 at 14:13, Tim Peters  wrote:

> Just clarifying a fine point here:
>
> [Steven D'Aprano ]
> > ...
> > average = 0
> > smooth_signal = [(average := (1-decay)*average + decay*x) for x in
> signal]
> > assert average == smooth_signal[-1]
> >
> The scope issues are logically independent of assignment-expression
> spelling, but it's a pretty safe guess Nick is opposed to that example
> ever "just working" regardless of spelling, while PEP 572 doesn't
> currently support it anyway.


I'm personally fine with that example working if there's an explicit
nonlocal declaration on "average" in the nested scope - it's Guido that
objected to requiring the explicit scoping declaration to access that
behaviour.

For the implicit version, my request is that any PEP proposing the idea of
parent local scoping be held to the standard of *actually drafting the
patch for the language specification*, rather than handwaving away the hard
problems that it creates (i.e. what to do at class scope, what to do when
multiple generators expressions reference the same nonlocal name, what to
do with nested comprehensions, how to expand comprehensions using this kind
of scoping to their statement form in a context independent way).

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Nick Coghlan
On 11 May 2018 at 12:45, Tim Peters  wrote:

> [Nick Coghlan]
> > I've been thinking about this problem, and I think for the If/elif/while
> > cases it's actually possible to allow the "binding is the same as the
> > condition" case to be simplified to:
> >
> > if command =  pattern.match(the_string):
> > ...
> > elif command =  other_pattern.match(the_string):
> > ...
> >
> > while data = read_data():
>
> Unless there's some weird font problem on my machine, that looks like
> a single "equals sign".  In which case we'd be reproducing C's
> miserable confusion about whether:
>
> if (i = 1)
>
> was a too-hastily-typed spelling of the intended:
>
> if (i == 1)
>
> or whether they were thinking "equals" and typed "=" by mistake.
>
> If so, that would get an instant -1 from any number of core devs, who
> have vivid painful memories of being burned by that in C.  That's not
> just speculation - it came up a number of times in the PEP 572
> threads.
>

I was one of those core devs, and would personally prefer to require that
folks spell the inline binding completely unambiguously as "if i given i =
1:".

However, if the repetition of "i" is considered a deal breaker relative to
":=" (even though the status quo already requires repetition of the target
name in the condition), then I'd prefer to add this shorthand (which folks
can then opt to prohibit in favour of the more explicit form in their style
guides) over adding the cognitive complexity of deciding when to use "i =
1" and when to use "i := 1".

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Crazy idea: allow keywords as names in certain positions

2018-05-13 Thread Greg Ewing

Rob Cliffe via Python-ideas wrote:
If you forbid redefining keywords, you remove the whole point of this 
proposal:


I mean the keywords that are in the language as of now.
There will never be a need to redefine those, since no
current code uses them as names.

--
Greg
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] A comprehension scope issue in PEP 572

2018-05-13 Thread Nick Coghlan
On 13 May 2018 at 20:00, Tim Peters  wrote:

> [Tim]
> >> - If the target is not local to any function enclosing F, and is not
> >> declared `global` in the block containing F, then the target is bound
> >> in the block containing F.
>
> [also Tim]
> > FYI, that's still not right, ...
> > I suspect that the above should be reworded to the simpler:
> >
> > - If the target is not  declared `global` or `nonlocal` in the block
> >   containing F, then the target is bound in the block containing F.
> > ...
>
> I'm satisfied that captures the intent - but now it's misleadingly
> wordy.  It should be the briefer:
>
> - The target is bound in the block containing F.
>
> Other text (in section 4.2.2) already covers the intended meanings for
> when a `global` or `nonlocal` declaration appears in the block too.
>
> And then it's short enough again that the bullet list isn't really
> helpful anymore.  So, putting that all together:
>
> """
> An assignment expression binds the target, except in a function F
> synthesized to implement a list comprehension or generator expression
> (see XXX).  In the latter case[1], the target is bound in the block
> containing F, and errors may be detected:  If the target also appears
> as an identifier target of a `for` loop header in F, a `SyntaxError`
> exception is raised.  If the block containing F is a class block, a
> `SyntaxError` exception is raised.
>
> Footnote:
> [1] The intent is that runtime binding of the target occurs as if the
> binding were performed in the block containing F.  Because that
> necessarily makes the target not local in F, it's an error if the
> target also appears in a `for` loop header, which is a local binding
> for the same target.  If the containing block is a class block, F has
> no access to that block's scope, so it doesn't make sense to consider
> the containing block.  The target is bound in the containing block,
> where it inherits that block's `global` or `nonlocal` declaration if
> one exists, else establishes that the target is local to that block.
> """
>

This is getting pretty close to being precise enough to be at least
potentially implementable (thanks!), but there are still two cases that
would need to be covered:

- what happens inside a lambda expression?
- what happens inside another comprehension or generator expression?

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Peter O'Connor
 *Correction: Above code should read:

outputs = []
state = initial_state
for inp in inputs:
out, state = my_update_func(inp, state)
outputs.append(out)


On Sun, May 13, 2018 at 11:21 AM, Peter O'Connor  wrote:

>   target := expr
>   expr as target
>   expr -> target
>   target given target = expr
>   let target = expr
>  : target expr ;
>
>
> Although in general "target:=exp" seems the most palatable of these to me,
> there is one nice benefit to the "given" syntax:
>
> Suppose you have a comprehension wherein you want to pass forward an
> internal "state" between iterations, but not return it as the output:
>
> In today's python, you'd to:
>
> outputs = []
> state = initial_state
> for inp in inputs:
> out, state = my_update_func(state)
> outputs.append(state)
>
> This could not be neatly compacted into:
>
> state = initial_state
> outputs = [out given out, state = my_update_func(inp, state) for inp
> in inputs]
>
> Or maybe:
>
> outputs = [out given out, state = my_update_func(inp, state) for inp
> in inputs given state=initial_state]
>
> Though I agree for the much more common case of assigning a value inline
> "x given x=y" seems messily redundant.
>
>
>
> On Sat, May 12, 2018 at 10:37 PM, Stephen J. Turnbull <
> turnbull.stephen...@u.tsukuba.ac.jp> wrote:
>
>> David Mertz writes:
>>
>>  > Only the BDFL has a vote with non-zero weight.
>>
>> "Infinitesimal" != "zero".
>>
>> Pedantically yours,
>>
>> ___
>> Python-ideas mailing list
>> Python-ideas@python.org
>> https://mail.python.org/mailman/listinfo/python-ideas
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
>
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Peter O'Connor
  target := expr
  expr as target
  expr -> target
  target given target = expr
  let target = expr
 : target expr ;


Although in general "target:=exp" seems the most palatable of these to me,
there is one nice benefit to the "given" syntax:

Suppose you have a comprehension wherein you want to pass forward an
internal "state" between iterations, but not return it as the output:

In today's python, you'd to:

outputs = []
state = initial_state
for inp in inputs:
out, state = my_update_func(state)
outputs.append(state)

This could not be neatly compacted into:

state = initial_state
outputs = [out given out, state = my_update_func(inp, state) for inp in
inputs]

Or maybe:

outputs = [out given out, state = my_update_func(inp, state) for inp in
inputs given state=initial_state]

Though I agree for the much more common case of assigning a value inline "x
given x=y" seems messily redundant.



On Sat, May 12, 2018 at 10:37 PM, Stephen J. Turnbull <
turnbull.stephen...@u.tsukuba.ac.jp> wrote:

> David Mertz writes:
>
>  > Only the BDFL has a vote with non-zero weight.
>
> "Infinitesimal" != "zero".
>
> Pedantically yours,
>
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] "given" vs ":=" in list comprehensions

2018-05-13 Thread Mark Dickinson
On Sun, May 13, 2018 at 1:34 AM, Andre Roberge 
wrote:

> First example: single temporary assignment, done four different ways.
>
> 1) using :=
>
> real_roots = [ (-b/(2*a) + (D:= sqrt( (b/(2*a))**2 - c/a), -b/(2*a) - D)
>  for a in range(10)
>  for b in range(10)
>  for c in range(10)
>  if D >= 0]
>

Unless PEP 572 is doing something horribly magical, this doesn't look as
though it should work at all, so it may not be a good target for
comparisons with other syntax possibilities. I'd expect that the `D` name
lookup in the `if D >= 0` clause would occur before the (D := ...)
assignment in the target expression, resulting in an UnboundLocalError. (I
tried to check out Chris's reference implementation branch to verify, but
the compilation failed with a traceback.)

And a random mathematical nitpick: as a non-NaN result of a square root
operation, D will always satisfy D >= 0; for this use-case we want to check
the *argument* to the `sqrt` call for nonnegativity, rather than the
*result*. So I think the target statement for the comparison with other
syntaxes should look something like this instead:

real_roots = [
(-b/(2*a) + sqrt(D), -b/(2*a) - sqrt(D))
for a in range(1, 10)  # start at 1 to avoid division by zero
for b in range(10)
for c in range(10)
if (D := (b/(2*a))**2 - c/a) >= 0
]

Or possibly like this, using an extra assignment expression to avoid the
repeated computation of the square root:

real_roots = [
(-b/(2*a) + (s := sqrt(D)), -b/(2*a) - s)
for a in range(1, 10)
for b in range(10)
for c in range(10)
if (D := (b/(2*a))**2 - c/a) >= 0
]

Similar order-of-evaluation issues apply to example (8), and to the other
examples based on hypothetical syntax, depending on exactly how that syntax
is hypothesised to work.

-- 
Mark
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Sven R. Kunze

On 13.05.2018 11:23, Peter O'Connor wrote:

 *Correction: Above code should read:

    outputs = []
state = initial_state
for inp in inputs:
out, state = my_update_func(inp, state)
outputs.append(out)



Question still stands if this type of code needs compaction in the first 
place?


List comprehensions usually have some sort of declarative touch (set 
builder notation).


Even though, striving for a more compacted version, I tend to think that 
using a declarative version of it doesn't serve it well in the long term.



We recently came across the following code snippet in our source base 
(1st answer of 
https://stackoverflow.com/questions/480214/how-do-you-remove-duplicates-from-a-list-whilst-preserving-order). 
It was absolutely not comprehensible.



Your example is inherently imperative because the internal state changes 
from iteration to iteration; something unusual for set builder notation.



Regards,
Sven
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Eric V. Smith

On 5/13/18 1:05 AM, Chris Angelico wrote:

On Sun, May 13, 2018 at 2:58 PM, Cameron Simpson  wrote:

On 13May2018 14:23, Chris Angelico  wrote:


On Sun, May 13, 2018 at 2:05 PM, Cameron Simpson  wrote:


Could someone point me to a post which nicely describes the rationale
behind
its rejection?  I'm sure there's one in the many in this discussion but
I've
not found it yet.




https://www.python.org/dev/peps/pep-0572/#special-casing-conditional-statements
https://www.python.org/dev/peps/pep-0572/#alternative-spellings

I'm not sure which version you're looking at, so there's the rejections of
both.



I meant the latter, but I'd already looked at that part of the PEP and found
its explaination... unfulfilling. It says:

 EXPR as NAME:

   stuff = [[f(x) as y, x/y] for x in range(5)]

 Since EXPR as NAME already has meaning in except and with statements (with
 different semantics), this would create unnecessary confusion or require
 special-casing (eg to forbid assignment within the headers of these
 statements).

All you need to disambiguate, say:

 with expr as expr_as as with_as:

is to require parentheses for (expr as exp_as) if someone wanted that
complications (assuming that is even necessary - it seems unambiguous to my
eye already, unless the token lookahead requirement in Python's grammar
prevents that.

So I'd hoped for a post to the list discussing this aspect and outlining why
it was considered unsatisfactory.


There were a large number of posts, so I can't really point to one of
them. The problem isn't the double-as case that you describe; it's
that these two are ALMOST identical:

with expr as target:
with (expr as target):

In fact, they are functionally identical for many situations - "with
(open(...) as target):" is exactly the same as the form without the
parens. It'd make for data-dependent bugs, which are a really REALLY
bad idea.


A little more detail:

The first one is partially:

target = expr.__enter__()

The second one is partially:

target = expr

For many objects, obj.__enter__() just returns obj, it often looks like 
these two statements do the same thing, but they do not. Chris's 
concern, which I share, is that users wouldn't know why these are 
different, and why the second on works for some objects but not others.


I agree the PEP could use more detail in explaining this particular issue.

Eric
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Steven D'Aprano
On Sat, May 12, 2018 at 07:36:33PM -0400, Juancarlo Añez wrote:

> Python already uses "in", which is used in other languages to introduce
> context.

Fortunately, we don't have to come up with syntax that works with other 
languages, only Python.


> The statement structure of "with...as" seems desirable

But it's not a statement, its an expression.


> just asking for a word that is not "with" or "given".

How about "antidisestablishmentarianism"? That's unlikely to be used in 
many programs, so we could make it a keyword.

*wink*

I jest, of course. But I don't think "with" reads well, and given 
doesn't really work for me either *as prose*.

In my experience mathematicians put the given *before* the statement:

   Given a, b, c three sides of a triangle, then

   Area = sqrt(s*(s-a)*(s-b)*(s-c))

   where s = (a + b + c)/2 is the semi-perimeter of the triangle.

For the record, that is almost exactly what I wrote for a student 
earlier today, and its not just me, it is very similar to the wording 
used on both Wolfram Mathworld and Wikipedia's pages on Heron's Formula.

http://mathworld.wolfram.com/HeronsFormula.html

https://en.wikipedia.org/wiki/Heron%27s_formula


Putting "given" after the expression is backwards.



-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Steven D'Aprano
On Sun, May 13, 2018 at 10:53:50AM +1000, Cameron Simpson wrote:

> For myself, I'm not a fan of a narrow scope. I'd be happy with an inline 
> assignment landing in the function scope (or whatever the current innermost 
> scope is). Like normal assignments. In how many other places does Python 
> adopt a narrower scope than the function/method/class/module?

None except for comprehensions and generators. And may it stay that way 
:-)


> I'm going to digress into an explaination of this issue in Go here because 
> I want to highlight my dislike of easy accidental shadowing, which is a 
> problem in many areas, and I think that conflating inline assignment with 
> an implied narrow scope in Python would make this worse.
[...]


Thanks Cameron! This is a really good practical example of why narrow 
scopes should be avoided.



-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Steven D'Aprano
On Sat, May 12, 2018 at 08:27:53PM -0400, Juancarlo Añez wrote:
> > if (diff := x - x_base) and (g := gcd(diff, n)) > 1:
> >  return g
> >
> >
> I don't see the advantage in that succinctness:
> 
> g = special_gcd(x - x_base, n)
> 
> if g:
> 
> return g
> 
> 
> The code bases I work on constantly move towards having the next guy grok
> what's going on just by reading the code.

That's an excellent point. What's "special_gcd" and how does it differ 
from normal gcd? How am I supposed to grok that just from reading the 
code above?

Do I have to dig into the source of special_gcd to understand it?

What happens if the normal gcd would return zero? Is that going to lead 
to a bug?



> It could also be:
> 
> if special_gcd(x - x_base, n) as g:
> return g

No it can't, because "as" is not an option.




-- 
Steven
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Greg Ewing

Steven D'Aprano wrote:

In my experience mathematicians put the given *before* the statement:

   Given a, b, c three sides of a triangle, then

   Area = sqrt(s*(s-a)*(s-b)*(s-c))

   where s = (a + b + c)/2 is the semi-perimeter of the triangle.


I agree, and "where" would be my first choice, but...
given... that "where" is not available, "given" seems
like the next best choice. At least it doesn't sound
blatantly wrong in that position.

--
Greg
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Rob Cliffe via Python-ideas



On 12/05/2018 23:52, Neil Girdhar wrote:



On Sat, May 12, 2018 at 5:54 PM Cameron Simpson > wrote:


On 06May2018 02:00, Nick Coghlan > wrote:
>On 5 May 2018 at 13:36, Tim Peters > wrote:
>> If only one trailing "given" clause can be given per `if` test
>> expression, presumably I couldn't do that without trickery.
>
>I was actually thinking that if we did want to allow multiple
assignments,
>and we limited targets to single names, we could just use a comma
as a
>separator:
>
>    if diff and g > 1 given diff = x - x_base, g = gcd(diff, n):
>        return g
>
>Similar to import statements, optional parentheses could be
included in the
>grammar, allowing the name bindings to be split across multiple
lines:
>
>    if diff and g > 1 given (
>        diff = x - x_base,
>        g = gcd(diff, n),
>    ):
>        return g

I'm well behind, but... this! This turns "given" into a +0.8 for me.

That's really nice. It reads clearly too.

I was hitherto in the "expression as name" camp, which I gather is
already
rejected.


I love given, but that's the one thing I don't like.  I prefer this:
    if (diff and g > 1
            given diff = x - x_base
            given g = gcd(diff, n)):
        return g

I don't like the consecutive "given"s.  Reading it aloud in English 
suggests to me that the second "given" should be evaluated before the 
first, which I'm sure is not the intention.
(Just as I think that multiple for-loops inside a comprehension sound 
the wrong way round. :-( But that ship has sailed.)

Rob Cliffe
—just like for and if subexpressions.   Doing this can also open up 
weirdness if someone tries to roll something like:


a = f(),  # Make a tuple of length 1

into a given statement.  Now, where do you up the parentheses?

given (
    a = (f(),),
    b = whatever?
)

Seems weird.


Cheers,
Cameron Simpson >
___
Python-ideas mailing list
Python-ideas@python.org 
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

-- 


---
You received this message because you are subscribed to a topic in
the Google Groups "python-ideas" group.
To unsubscribe from this topic, visit
https://groups.google.com/d/topic/python-ideas/CFuqwmE8s-E/unsubscribe.
To unsubscribe from this group and all its topics, send an email
to python-ideas+unsubscr...@googlegroups.com
.
For more options, visit https://groups.google.com/d/optout.


 
	Virus-free. www.avg.com 
 



<#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>


___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] A comprehension scope issue in PEP 572

2018-05-13 Thread Chris Angelico
On Sun, May 13, 2018 at 5:17 PM, Ethan Furman  wrote:
> On 05/12/2018 11:41 PM, Tim Peters wrote:
>>
>> [Tim, suggests changes to the Reference Manual's 4.2.1]
>>>
>>> """
>>> An assignment expression binds the target, except in a function F
>>> synthesized to implement a list comprehension or generator expression
>>> (see XXX).  In the latter case, if the target is not in F's
>>> environment (see section 4.2.2) , the target is bound in the block
>>> containing F.
>>> """
>>
>>
>> Let me try that again ;-)  The notion of "environment" includes the
>> global scope, but that's not really wanted here.   "Environment" has
>> more of a runtime flavor anyway.  And since nobody will tell me
>> anything about class scope, I read the docs myself ;-)
>>
>> And that's a problem, I think!  If a comprehension C is in class scope
>> S, apparently the class locals are _not_ in C's environment.  Since C
>> doesn't even have read access to S's locals, it seems to me bizarre
>> that ":=" could _create_ a local in S.
>
>
> Python 3.7.0b3+ (heads/bpo-33217-dirty:28c1790, Apr  5 2018, 13:10:10)
> [GCC 4.8.2] on linux
> Type "help", "copyright", "credits" or "license" for more information.
> --> class C:
> ...   huh = 7
> ...   hah = [i for i in range(huh)]
> ...
> --> C.hah
> [0, 1, 2, 3, 4, 5, 6]
>
> Same results clear back to 3.3 (the oldest version of 3 I have).  Are the
> docs wrong?

>>> class C:
... huh = 7
... hah = [i for _ in [0] for i in range(huh)]
...
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 3, in C
  File "", line 3, in 
NameError: name 'huh' is not defined

The outermost iterable is a special case. Otherwise, you can't
reference anything.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] A comprehension scope issue in PEP 572

2018-05-13 Thread Ethan Furman

On 05/12/2018 11:41 PM, Tim Peters wrote:

[Tim, suggests changes to the Reference Manual's 4.2.1]

"""
An assignment expression binds the target, except in a function F
synthesized to implement a list comprehension or generator expression
(see XXX).  In the latter case, if the target is not in F's
environment (see section 4.2.2) , the target is bound in the block
containing F.
"""


Let me try that again ;-)  The notion of "environment" includes the
global scope, but that's not really wanted here.   "Environment" has
more of a runtime flavor anyway.  And since nobody will tell me
anything about class scope, I read the docs myself ;-)

And that's a problem, I think!  If a comprehension C is in class scope
S, apparently the class locals are _not_ in C's environment.  Since C
doesn't even have read access to S's locals, it seems to me bizarre
that ":=" could _create_ a local in S.


Python 3.7.0b3+ (heads/bpo-33217-dirty:28c1790, Apr  5 2018, 13:10:10)
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
--> class C:
...   huh = 7
...   hah = [i for i in range(huh)]
...
--> C.hah
[0, 1, 2, 3, 4, 5, 6]

Same results clear back to 3.3 (the oldest version of 3 I have).  Are the docs 
wrong?

Or maybe they just refer to functions:

--> class C:
...   huh = 7
...   hah = [i for i in range(huh)]
...   heh = lambda: [i for i in range(huh)]
...
--> C.hah
[0, 1, 2, 3, 4, 5, 6]
--> C.heh()
Traceback (most recent call last):
  File "test_class_comp.py", line 7, in 
print(C.heh())
  File "test_class_comp.py", line 4, in 
heh = lambda: [i for i in range(huh)]
NameError: global name 'huh' is not defined

So a class-scope comprehension assignment expression should behave as you 
originally specified.

--
~Ethan~
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] A comprehension scope issue in PEP 572

2018-05-13 Thread Tim Peters
[Tim, suggests changes to the Reference Manual's 4.2.1]
> """
> An assignment expression binds the target, except in a function F
> synthesized to implement a list comprehension or generator expression
> (see XXX).  In the latter case, if the target is not in F's
> environment (see section 4.2.2) , the target is bound in the block
> containing F.
> """

Let me try that again ;-)  The notion of "environment" includes the
global scope, but that's not really wanted here.   "Environment" has
more of a runtime flavor anyway.  And since nobody will tell me
anything about class scope, I read the docs myself ;-)

And that's a problem, I think!  If a comprehension C is in class scope
S, apparently the class locals are _not_ in C's environment.  Since C
doesn't even have read access to S's locals, it seems to me bizarre
that ":=" could _create_ a local in S.

Since I personally couldn't care less about running comprehensions of
any kind at class scope, I propose to make `:=` a SyntaxError if
someone tries to use a comprehension with ':=' at class scope (of
course they may be able to use ":=" in nested comprehensions anyway -
not that anyone would).

If someone objects to that, fine, you figure it out ;-)  So here's another stab.

"""
An assignment expression binds the target, except in a function F
synthesized to implement a list comprehension or generator expression
(see XXX).  In the latter case[1]:

- If the target also appears as an identifier target of a `for` loop
header in F, a `SyntaxError` exception is raised.

- If the block containing F is a class block, a `SyntaxError`
exception is raised.

- If the target is not local to any function enclosing F, and is not
declared `global` in the block containing F, then the target is bound
in the block containing F.

Footnote:
[1] The intent is that runtime binding of the target occurs as if the
binding were performed in the block containing F.  Because that
necessarily makes the target not local in F, it's an error if the
target also appears in a `for` loop header, which is a local binding
for the same target.  If the containing block is a class block, F has
no access to that block's scope, so it doesn't make sense to consider
the containing block.  If the target is already known to the
containing block, the target inherits its scope resolution from the
containing block.  Else the target is established as local to the
containing block.
"""

I realize the docs don't generally use bullet lists.  Convert to
WallOfText if you must.  The material in the footnote would usually go
in a "Rationale" doc instead, but we don't have one of those, and I
think the intent is too hard to deduce without that info.


And repeating the other point, to keep a self-contained account:

> Earlier, for now-necessary disambiguation, I expect that in
>
> ... targets that are identifiers if occurring in an assignment, ...
>
> " statement" should be inserted before the comma.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Crazy idea: allow keywords as names in certain positions

2018-05-13 Thread Guido van Rossum
As anyone still following the inline assignment discussion knows, a problem
with designing new syntax is that it's hard to introduce new keywords into
the language, since all the nice words seem to be used as method names in
popular packages. (E.g. we can't use 'where' because there's numpy.where
,
and we can't use 'given' because it's used in Hypothesis
.)

The idea I had (not for the first time :-) is that in many syntactic
positions we could just treat keywords as names, and that would free up
these keywords.

For example, we could allow keywords after 'def' and after a period, and
then the following would become legal:

class C:
def and(self, other):
return ...

a = C()
b = C()
print(a.and(b))

This does not create syntactic ambiguities because after 'def' and after a
period the grammar *always* requires a NAME.

There are other positions where we could perhaps allow this, e.g. in a
decorator, immediately after '@' (the only keyword that's *syntactically*
legal here is 'not', though I'm not sure it would ever be useful).

Of course this would still not help for names of functions that might be
imported directly (do people write 'from numpy import where'?). And it
would probably cause certain typos be harder to diagnose.

I should also mention that this was inspired from some messages where Tim
Peters berated the fashion of using "reserved words", waxing nostalgically
about the old days of Fortran (sorry, FORTRAN), which doesn't (didn't?)
have reserved words at all (nor significant whitespace, apart from the
"start in column 7" rule).

Anyway, just throwing this out. Please tear it apart!

-- 
--Guido van Rossum (python.org/~guido)
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Brendan Barnwell

On 2018-05-13 04:23, Steven D'Aprano wrote:

In my experience mathematicians put the given *before* the statement:

Given a, b, c three sides of a triangle, then

Area = sqrt(s*(s-a)*(s-b)*(s-c))

where s = (a + b + c)/2 is the semi-perimeter of the triangle.

For the record, that is almost exactly what I wrote for a student
earlier today, and its not just me, it is very similar to the wording
used on both Wolfram Mathworld and Wikipedia's pages on Heron's Formula.

http://mathworld.wolfram.com/HeronsFormula.html

https://en.wikipedia.org/wiki/Heron%27s_formula


Putting "given" after the expression is backwards.


	Yes, but that's because we're ruling out the use of "where".  At this 
point I would be fine with "snicklefritz" as the keyword.  The point is 
that I want to put SOMETHING after the expression, and this is not at 
all unusual.  See for instance Wikipedia pages on the Reimann zeta 
function 
(https://en.wikipedia.org/wiki/Riemann_zeta_function#Definition), 
gravitation equation 
(https://en.wikipedia.org/wiki/Gravity#Newton%27s_theory_of_gravitation), and 
compound interest 
(https://en.wikipedia.org/wiki/Compound_interest#Mathematics_of_interest_rate_on_loans). 
 If we have to use the word "given" even though the word mathematicians 
would use in that position is "where", that's not such a big deal.


--
Brendan Barnwell
"Do not follow where the path may lead.  Go, instead, where there is no 
path, and leave a trail."

   --author unknown
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Crazy idea: allow keywords as names in certain positions

2018-05-13 Thread Chris Angelico
On Mon, May 14, 2018 at 4:19 AM, Guido van Rossum  wrote:
> The idea I had (not for the first time :-) is that in many syntactic
> positions we could just treat keywords as names, and that would free up
> these keywords.
> ...
> I should also mention that this was inspired from some messages where Tim
> Peters berated the fashion of using "reserved words", waxing nostalgically
> about the old days of Fortran (sorry, FORTRAN), which doesn't (didn't?) have
> reserved words at all (nor significant whitespace, apart from the "start in
> column 7" rule).

I spent most of the 1990s coding in REXX, which has exactly zero
reserved words. You can write code like this:

if = 1
then = "spam"
else = "ham"

if if then then
else else

do = 5
do do
print("Doobee doobee doo"
end

The problem is that you can go a long way down the road of using a
particular name, only to find that suddenly you can't use it in some
particular context. Common words like "if" and "do" are basically
never going to get reused (so there's no benefit over having actual
keywords), but with less common words (which would include the
proposed "where" for binding expressions), it's entirely possible to
get badly bitten.

So the question is: Is it better to be able to use a keyword as an
identifier for a while, and then run into trouble later, or would you
prefer to be told straight away "no, sorry, pick a different name"?

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Crazy idea: allow keywords as names in certain positions

2018-05-13 Thread Brendan Barnwell

On 2018-05-13 11:19, Guido van Rossum wrote:

As anyone still following the inline assignment discussion knows, a
problem with designing new syntax is that it's hard to introduce new
keywords into the language, since all the nice words seem to be used as
method names in popular packages. (E.g. we can't use 'where' because
there's numpy.where
,
and we can't use 'given' because it's used in Hypothesis
.)

The idea I had (not for the first time :-) is that in many syntactic
positions we could just treat keywords as names, and that would free up
these keywords.

For example, we could allow keywords after 'def' and after a period, and
then the following would become legal:

class C:
 def and(self, other):
 return ...

a = C()
b = C()
print(a.and(b))

This does not create syntactic ambiguities because after 'def' and after
a period the grammar *always* requires a NAME.

There are other positions where we could perhaps allow this, e.g. in a
decorator, immediately after '@' (the only keyword that's
*syntactically* legal here is 'not', though I'm not sure it would ever
be useful).

Of course this would still not help for names of functions that might be
imported directly (do people write 'from numpy import where'?). And it
would probably cause certain typos be harder to diagnose.


Spooky!  :-)

	People definitely do write "from numpy import where".  You can see 
examples just by googling for that string.  And that's only finding the 
cases where "where" is the first thing in the from clause; there are 
probably many more where it's something like "from numpy import array, 
sin, cos, where".


	I think this kind of special casing would be really confusing though. 
It would mean that these two would work (and do the same thing):


import np
np.array(...)

from np import array
array(...)

And this would work:

import np
np.where(...)

But then this would fail:

from np import where
where(...)

	That would be really puzzling.  Plus, we'd still have the problem of 
backwards compatibility.  Before the new "where" keyword was introduced, 
the last example WOULD work, but then afterwards you'd have to change it 
to look like the third example.  This might induce wary programmers to 
hide all names behind a period (that is, find a way to do "foo.bar" 
instead of just "bar" whenever possible) in order to guard against 
future keywordization of those names.


	The other thing is that I suspect use of such a privilege would explode 
due to the attractiveness of the reserved words.  That is, many 
libraries would start defining things named "and", "or", "with", "is", 
"in", etc., because the names are so nice and short and are useful in so 
many situations.  So there'd be nowhere to hide from the deluge of names 
shadowing keywords.


--
Brendan Barnwell
"Do not follow where the path may lead.  Go, instead, where there is no 
path, and leave a trail."

   --author unknown
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Matt Arcidy
On Sun, May 13, 2018, 11:28 Brendan Barnwell  wrote:

> On 2018-05-13 04:23, Steven D'Aprano wrote:
> > In my experience mathematicians put the given *before* the statement:
> >
> > Given a, b, c three sides of a triangle, then
> >
> > Area = sqrt(s*(s-a)*(s-b)*(s-c))
> >
> > where s = (a + b + c)/2 is the semi-perimeter of the triangle.
> >
> > For the record, that is almost exactly what I wrote for a student
> > earlier today, and its not just me, it is very similar to the wording
> > used on both Wolfram Mathworld and Wikipedia's pages on Heron's Formula.
> >
> > http://mathworld.wolfram.com/HeronsFormula.html
> >
> > https://en.wikipedia.org/wiki/Heron%27s_formula
> >
> >
> > Putting "given" after the expression is backwards.
>
> Yes, but that's because we're ruling out the use of "where".  At
> this
> point I would be fine with "snicklefritz" as the keyword.  The point is
> that I want to put SOMETHING after the expression, and this is not at
> all unusual.  See for instance Wikipedia pages on the Reimann zeta
> function
> (https://en.wikipedia.org/wiki/Riemann_zeta_function#Definition),
> gravitation equation
> (https://en.wikipedia.org/wiki/Gravity#Newton%27s_theory_of_gravitation),
> and
> compound interest
> (
> https://en.wikipedia.org/wiki/Compound_interest#Mathematics_of_interest_rate_on_loans).
>
>   If we have to use the word "given" even though the word mathematicians
> would use in that position is "where", that's not such a big deal.
>

it is a big deal.  postfix requires more cognitive load, we will have no
idea up front what's going on except for trivial exames.  more givens, more
cognitive load.

if you think spending that is fine for you, I can't argue, but to say it
doesn't matter isn't correct.

2.exames which get far worse for complex cases.  left for the for can be as
complex.as.you wish.
1:
[ x + y for t in range(10)  ... ]

2:
x = 10
y = 20
[ x + y for t in range(10) ...]

up till you read ... you have no idea there even will be a substitution.
The lower is even worse, you think you know, but then have to redo the
whole problem with new information.

also :
mathematicians don't just put the _word_ "given", they put givens, things
that are known or assumed to be true.  Axioms and definitions, where
definitions assign names to values.  This is for formal arguements.
reassigning values is handled in post fix occasionally once it is clear
what x and y are.  but that's not what we are talking about if the name
doesn't exist already.

again, you want to use given, that's fine, but the math argument is wrong,
as is the "it doesn't matter" argument, assuming the current neurological
model for working memory continues to hold.

 Maybe the difference is small, especially after familiarity sets in, but
that doesn't mean the difference in load isn't there.  it will only
increase for more complex statements with more givens.

>
> --
> Brendan Barnwell
> "Do not follow where the path may lead.  Go, instead, where there is no
> path, and leave a trail."
> --author unknown
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Crazy idea: allow keywords as names in certain positions

2018-05-13 Thread Elias Tarhini
Apologies for my initial response. Looks like I failed to expand the
initial email fully, which would have shown me the following :)

> Of course this would still not help for names of functions that might be
imported directly (do people write 'from numpy import where'?).

-- I do think the *import keyword as keyword_* concept has merit, however.

(This would also be a simple retroactive solution to the asyncio.async
problem, wouldn't it?)

On Sun, May 13, 2018, 11:45 AM Chris Angelico  wrote:

> On Mon, May 14, 2018 at 4:19 AM, Guido van Rossum 
> wrote:
> > The idea I had (not for the first time :-) is that in many syntactic
> > positions we could just treat keywords as names, and that would free up
> > these keywords.
> > ...
> > I should also mention that this was inspired from some messages where Tim
> > Peters berated the fashion of using "reserved words", waxing
> nostalgically
> > about the old days of Fortran (sorry, FORTRAN), which doesn't (didn't?)
> have
> > reserved words at all (nor significant whitespace, apart from the "start
> in
> > column 7" rule).
>
> I spent most of the 1990s coding in REXX, which has exactly zero
> reserved words. You can write code like this:
>
> if = 1
> then = "spam"
> else = "ham"
>
> if if then then
> else else
>
> do = 5
> do do
> print("Doobee doobee doo"
> end
>
> The problem is that you can go a long way down the road of using a
> particular name, only to find that suddenly you can't use it in some
> particular context. Common words like "if" and "do" are basically
> never going to get reused (so there's no benefit over having actual
> keywords), but with less common words (which would include the
> proposed "where" for binding expressions), it's entirely possible to
> get badly bitten.
>
> So the question is: Is it better to be able to use a keyword as an
> identifier for a while, and then run into trouble later, or would you
> prefer to be told straight away "no, sorry, pick a different name"?
>
> ChrisA
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Crazy idea: allow keywords as names in certain positions

2018-05-13 Thread Nathan Schneider
Care would have to be taken in the grammar to avoid syntactic ambiguity.
For example:

x = 1
def not(x):
...

if not - x: # Is this 'not' the keyword or the identifier? not (-x), or not
minus x?
...

Nathan

On Sun, May 13, 2018 at 2:20 PM Guido van Rossum  wrote:

> As anyone still following the inline assignment discussion knows, a
> problem with designing new syntax is that it's hard to introduce new
> keywords into the language, since all the nice words seem to be used as
> method names in popular packages. (E.g. we can't use 'where' because
> there's numpy.where
> ,
> and we can't use 'given' because it's used in Hypothesis
> .)
>
> The idea I had (not for the first time :-) is that in many syntactic
> positions we could just treat keywords as names, and that would free up
> these keywords.
>
> For example, we could allow keywords after 'def' and after a period, and
> then the following would become legal:
>
> class C:
> def and(self, other):
> return ...
>
> a = C()
> b = C()
> print(a.and(b))
>
> This does not create syntactic ambiguities because after 'def' and after a
> period the grammar *always* requires a NAME.
>
> There are other positions where we could perhaps allow this, e.g. in a
> decorator, immediately after '@' (the only keyword that's *syntactically*
> legal here is 'not', though I'm not sure it would ever be useful).
>
> Of course this would still not help for names of functions that might be
> imported directly (do people write 'from numpy import where'?). And it
> would probably cause certain typos be harder to diagnose.
>
> I should also mention that this was inspired from some messages where Tim
> Peters berated the fashion of using "reserved words", waxing nostalgically
> about the old days of Fortran (sorry, FORTRAN), which doesn't (didn't?)
> have reserved words at all (nor significant whitespace, apart from the
> "start in column 7" rule).
>
> Anyway, just throwing this out. Please tear it apart!
>
> --
> --Guido van Rossum (python.org/~guido)
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Neil Girdhar
On Sun, May 13, 2018 at 2:54 PM Matt Arcidy  wrote:

>
>
> On Sun, May 13, 2018, 11:28 Brendan Barnwell 
> wrote:
>
>> On 2018-05-13 04:23, Steven D'Aprano wrote:
>> > In my experience mathematicians put the given *before* the statement:
>> >
>> > Given a, b, c three sides of a triangle, then
>> >
>> > Area = sqrt(s*(s-a)*(s-b)*(s-c))
>> >
>> > where s = (a + b + c)/2 is the semi-perimeter of the triangle.
>> >
>> > For the record, that is almost exactly what I wrote for a student
>> > earlier today, and its not just me, it is very similar to the wording
>> > used on both Wolfram Mathworld and Wikipedia's pages on Heron's Formula.
>> >
>> > http://mathworld.wolfram.com/HeronsFormula.html
>> >
>> > https://en.wikipedia.org/wiki/Heron%27s_formula
>> >
>> >
>> > Putting "given" after the expression is backwards.
>>
>
I usually read the vertical bar "given" in

set-builder notation:  {x | 10 < x < 100, x is prime}

Conditional probabilities, expectations, entropy, etc.: P(X | Y), E(X| Y),
H(X | Y),

And, the so-called "evaluation bar":
https://math.stackexchange.com/questions/52651/what-is-the-name-of-the-vertical-bar-in-x21-vert-x-4-or-left-left

In words, I agree that where is probably better in text because writing
"given the gravitational constant G" puts the subject last, unlike "where G
is the gravitational constant".  However, the given proposal for Python is
putting the subject first: "given x = y".


>> Yes, but that's because we're ruling out the use of "where".  At
>> this
>> point I would be fine with "snicklefritz" as the keyword.  The point is
>> that I want to put SOMETHING after the expression, and this is not at
>> all unusual.  See for instance Wikipedia pages on the Reimann zeta
>> function
>> (https://en.wikipedia.org/wiki/Riemann_zeta_function#Definition),
>> gravitation equation
>> (https://en.wikipedia.org/wiki/Gravity#Newton%27s_theory_of_gravitation),
>> and
>> compound interest
>> (
>> https://en.wikipedia.org/wiki/Compound_interest#Mathematics_of_interest_rate_on_loans).
>>
>>   If we have to use the word "given" even though the word mathematicians
>> would use in that position is "where", that's not such a big deal.
>>
>
> it is a big deal.  postfix requires more cognitive load, we will have no
> idea up front what's going on except for trivial exames.  more givens, more
> cognitive load.
>
> if you think spending that is fine for you, I can't argue, but to say it
> doesn't matter isn't correct.
>
> 2.exames which get far worse for complex cases.  left for the for can be
> as complex.as.you wish.
> 1:
> [ x + y for t in range(10)  ... ]
>
> 2:
> x = 10
> y = 20
> [ x + y for t in range(10) ...]
>
> up till you read ... you have no idea there even will be a substitution.
> The lower is even worse, you think you know, but then have to redo the
> whole problem with new information.
>
> also :
> mathematicians don't just put the _word_ "given", they put givens, things
> that are known or assumed to be true.  Axioms and definitions, where
> definitions assign names to values.  This is for formal arguements.
> reassigning values is handled in post fix occasionally once it is clear
> what x and y are.  but that's not what we are talking about if the name
> doesn't exist already.
>

Most (if not all) uses of the vertical are read as "given" and they all put
the givens to the right of it.

>
> again, you want to use given, that's fine, but the math argument is wrong,
> as is the "it doesn't matter" argument, assuming the current neurological
> model for working memory continues to hold.
>
>  Maybe the difference is small, especially after familiarity sets in, but
> that doesn't mean the difference in load isn't there.  it will only
> increase for more complex statements with more givens.
>
>>
>> --
>> Brendan Barnwell
>> "Do not follow where the path may lead.  Go, instead, where there is no
>> path, and leave a trail."
>> --author unknown
>> ___
>> Python-ideas mailing list
>> Python-ideas@python.org
>> https://mail.python.org/mailman/listinfo/python-ideas
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
> --
>
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "python-ideas" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/python-ideas/CFuqwmE8s-E/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> python-ideas+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
> --
>
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "python-ideas" group.
> To unsubscribe 

Re: [Python-ideas] Crazy idea: allow keywords as names in certain positions

2018-05-13 Thread Elias Tarhini
I like it! The obvious question, though: How would "*from package import
keyword*" be handled, if not simply by SyntaxError? Would *from package
import keyword as keyword_* be allowed?

In a similar vein, what would happen with stdlib functions like
operator.not_? The thought of writing "operator.not" is appealing, but
being forced to use *that* (with *from operator import not* being
non-allowable) may not be.

On Sun, May 13, 2018, 11:20 AM Guido van Rossum  wrote:

> As anyone still following the inline assignment discussion knows, a
> problem with designing new syntax is that it's hard to introduce new
> keywords into the language, since all the nice words seem to be used as
> method names in popular packages. (E.g. we can't use 'where' because
> there's numpy.where
> ,
> and we can't use 'given' because it's used in Hypothesis
> .)
>
> The idea I had (not for the first time :-) is that in many syntactic
> positions we could just treat keywords as names, and that would free up
> these keywords.
>
> For example, we could allow keywords after 'def' and after a period, and
> then the following would become legal:
>
> class C:
> def and(self, other):
> return ...
>
> a = C()
> b = C()
> print(a.and(b))
>
> This does not create syntactic ambiguities because after 'def' and after a
> period the grammar *always* requires a NAME.
>
> There are other positions where we could perhaps allow this, e.g. in a
> decorator, immediately after '@' (the only keyword that's *syntactically*
> legal here is 'not', though I'm not sure it would ever be useful).
>
> Of course this would still not help for names of functions that might be
> imported directly (do people write 'from numpy import where'?). And it
> would probably cause certain typos be harder to diagnose.
>
> I should also mention that this was inspired from some messages where Tim
> Peters berated the fashion of using "reserved words", waxing nostalgically
> about the old days of Fortran (sorry, FORTRAN), which doesn't (didn't?)
> have reserved words at all (nor significant whitespace, apart from the
> "start in column 7" rule).
>
> Anyway, just throwing this out. Please tear it apart!
>
> --
> --Guido van Rossum (python.org/~guido)
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Crazy idea: allow keywords as names in certain positions

2018-05-13 Thread Stephan Houben
Note that Javascript does something similar,
in that reserved keywords are allowed in member access.

var x = {if : 42};
console.log(x.if);

Stephan


2018-05-13 20:42 GMT+02:00 Eric Fahlgren :

> On Sun, May 13, 2018 at 11:20 AM Guido van Rossum 
> wrote:
>
>> For example, we could allow keywords after 'def' and after a period, and
>> then the following would become legal:
>>
>
> ​Our modeling database overloads getattr/setattr (think SQLAlchemy) to
> allow us to access to database fields as if they were Python data members.
> Nothing new here, but we do have problems with keyword collisions on some
> of the objects, as we are wrapping an already-existing modeling language
> (MSC Adams Solver dataset) with our objects.  We were pleased with 'print'
> became a function, because it removed the restriction from that one, but
> one of the remaining ones is 'return', like this:
>
> class Sensor:
> def __init__(self):
> setattr(self, "print", 0)
> setattr(self, "return", 0)
>
> s = Sensor()
> s.print  # Works now, didn't in Python 2.
> s.return  # Bork.
>
> I have a decades old +1 on this.
>
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Crazy idea: allow keywords as names in certain positions

2018-05-13 Thread Rob Cliffe via Python-ideas

On 13/05/2018 19:19, Guido van Rossum wrote:
As anyone still following the inline assignment discussion knows, a 
problem with designing new syntax is that it's hard to introduce new 
keywords into the language, since all the nice words seem to be used 
as method names in popular packages. (E.g. we can't use 'where' 
because there's numpy.where 
, 
and we can't use 'given' because it's used in Hypothesis 
.)


The idea I had (not for the first time :-) is that in many syntactic 
positions we could just treat keywords as names, and that would free 
up these keywords.


For example, we could allow keywords after 'def' and after a period, 
and then the following would become legal:


class C:
    def and(self, other):
    return ...

a = C()
b = C()
print(a.and(b))

This does not create syntactic ambiguities because after 'def' and 
after a period the grammar *always* requires a NAME.


There are other positions where we could perhaps allow this, e.g. in a 
decorator, immediately after '@' (the only keyword that's 
*syntactically* legal here is 'not', though I'm not sure it would ever 
be useful).
So you would be allowing "second class" identifiers - legal in some 
positions where an identifier is allowed, not legal in others.
With respect, that seems like a terrible idea; neither those who want to 
use such identifiers, nor those who don't, would be happy.  Especially 
if it encourages work-arounds such as


    def and(x, y):
    return ...

#   and(1,2)   #  Oops, SyntaxError.  Oh, I know:
    globals()['and'](1,2)    # Works!

and a zillion others.


[snip] And it would probably cause certain typos be harder to diagnose.

No doubt.


I should also mention that this was inspired from some messages where 
Tim Peters berated the fashion of using "reserved words", waxing 
nostalgically about the old days of Fortran (sorry, FORTRAN), which 
doesn't (didn't?) have reserved words at all (nor significant 
whitespace, apart from the "start in column 7" rule).


Anyway, just throwing this out. Please tear it apart!

Thanks. :-)


--
--Guido van Rossum (python.org/~guido )


Best wishes
Rob Cliffe
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Brendan Barnwell

On 2018-05-13 11:53, Matt Arcidy wrote:

again, you want to use given, that's fine, but the math argument is
wrong, as is the "it doesn't matter" argument, assuming the current
neurological model for working memory continues to hold.


	Sorry, but that's nonsense.  In the message you're replying to, what 
I'm arguing "doesn't matter" is the WORD used to do the postfixing.  Are 
you seriously saying that the "neurological model for working memory" 
means that "x + y where x = foo" is easier to understand, on a 
fundamental neurological basis, than "x + y given x = foo"?  Since 
you're the one who was advocating for objective measures, I'm sure 
you'll understand if I want some solid objective evidence for that!


	If you're saying that the entire concept of postfixing the givens 
(rather than putting them before the expression) creates greater 
cognitive load, then how do you explain the use of this format in the 
Wikipedia articles I linked, not to mention various math papers, texts, 
etc. throughout the world?


	Finally, even if we allow that postfixed-givens does increase cognitive 
load on a single, initial reading, that's not sufficient.  Part of what 
I'm saying is that on LATER readings it's faster to see the overall 
expression first, because you don't have to plow through the definitions 
of the givens.


--
Brendan Barnwell
"Do not follow where the path may lead.  Go, instead, where there is no 
path, and leave a trail."

   --author unknown
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Juancarlo Añez
> That's an excellent point. What's "special_gcd" and how does it differ
> from normal gcd? How am I supposed to grok that just from reading the
> code above?
>
> Do I have to dig into the source of special_gcd to understand it?
>
>

One would usually define functions like special_gcd() inline, right before
it is first used.

-- 
Juancarlo *Añez*
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Steven D'Aprano
On Sun, May 13, 2018 at 12:10:08AM -0400, Neil Girdhar wrote:

> > > Suppose you have a generator like
> > >
> > > (expression(f(x), y, z)
> > >  for x in xs
> > >  for y in ys(x)
> > >  for z in zs(y))
> > >
> > > With given notation you can optimize:

Actually, as you admitted, you can't, since this isn't part of 
the proposed syntax or semantics. But let's put that aside.

> > > (expression(f_x, y, z)
> > >  for x in xs
> > >  given f_x = f(x)
> > >  for y in ys(x)
> > >  for z in zs(y))
> > >
> > > whereas with :=, you can't.

Except of course you can:

> > (expression(f_x, y, z) for x in xs
> >  for y in ys(x)
> >  for z in zs(y)
> >  if (f_x := f(x)) or True)
> >  )

[Neil]
> My thought is that if each component is simple enough *and* if each
> component can be reasoned about independently of the others, then it's
> fine.  The issue I had with the := code you presented was that it was
> impossible to reason about the components independently from the whole.

I said it was rubbish code which I wouldn't use for serious work. But 
"impossible" to reason about? That's pretty strong, and definite, words 
for something which is actually pretty easy to reason about.

(expression(f_x, y, z) for x in xs
 for y in ys(x)
 for z in zs(y)
 if (f_x := f(x)) or True)
 )

I'm pretty sure you can reason about "expression(f_x, y, z)" on its own. 
After all, the above code was (apart from the := line) your own example. 
If you can't even reason about your own examples, you're in a bad place.

I think you can reason about the three for-loops "for x in xs" etc on 
their own. Again, they were your idea in the first place.

I expect you can reason about "if  or True" on its own. It's a 
pretty basic Python technique, to call  for its side-effect 
without caring about its return value.

Not something I would use for serious work, but this is YOUR example, 
not mine, so if you hate this generator expression, you were the one who 
suggested it.

Only the  is new or different from ordinary Python code that 
works now:

f_x := f(x)

The semantics of := are pretty damn simple (at least from the high-level 
overview without worrying about precedence or possible scoping issues):

- evaluate f(x)
- assign that value to f_x
- return the value of f_x

which is EXACTLY THE SAME SEMANTICS OF "f_x given f_x = f(x)":

- evaluate f(x)
- assign that value to f_x
- return the value of f_x

And you would reason about them the same way.



-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Neil Girdhar
On Sun, May 13, 2018 at 12:06 PM Steven D'Aprano 
wrote:

> On Sat, May 12, 2018 at 08:06:02PM -0400, Neil Girdhar wrote:
> > On Sat, May 12, 2018 at 2:28 PM Steven D'Aprano 
> wrote:
>
> > > > * there are no difficult mental questions about evaluation order,
> e.g.,
> > > > in a bracketed expression having multiple assignments.
> > >
> > > Aren't there just?
> > >
> > > x = 1
> > > print( x + x given x = 50 )
> > >
> > >
> > > Will that print 100, or 51? Brackets ought to make it clearer:
> > >
> > > (x + x given x = 50)  # this ought to return 100
> > > x + (x given x = 50)  # this ought to return 51
> > >
> > > but if I leave the brackets out, I have no idea what I'll get.
> > >
> >
> > It has to be 100, or else outer parentheses change how an expression is
> > evaluated.
>
> Whether that it right or wrong, you're missing the point. You said that
> we don't have to care about evaluation order. But we do: even if your
> analysis is correct, not everyone will realise it. I didn't.
>

I think the way to think about "given" is the same way you think about
"for" and "if" clauses:

(x + x for x in it)

(x + x if condition else y)

(x + x where x = f(y))


>
> And I still don't, because I think your analyse is wrong.
>
> "Outer parentheses" is a red herring. I should have written:
>
> (x + x) given x = 50  # this ought to return 100
> x + (x given x = 50)  # this ought to return 51
>
> and now there are no outer parentheses to worry about. The question is
> now whether "given" binds more tightly than + or not.
>
> We get to choose the precedence, and whatever we choose, it will
> surprise (or annoy) some people, and more importantly, some people
> simply won't know, and will have to ponder the difficult question of
> what the evaluation order is.


> This is already true today with code that has side-effects. I can
> simulate "given" using exec. It only works in the module scope:
>
> # another_expr given target = expr
> exec("target = expr") or another_expr
>
> but now we can see how precedence makes a real difference:
>
> x = 1
> x + (exec("x = 50") or x)
>
> versus:
>
> x = 1
> exec("x = 50) or (x + x)
>
>
> Regardless of which behaviour we choose, some people won't know it and
> will have to deal with "difficult mental questions about evaluation
> order".
>
> That's unavoidable, regardless of how we spell it, := or "given".


>
> --
> Steve
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
> --
>
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "python-ideas" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/python-ideas/CFuqwmE8s-E/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> python-ideas+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Steven D'Aprano
On Sat, May 12, 2018 at 08:06:02PM -0400, Neil Girdhar wrote:
> On Sat, May 12, 2018 at 2:28 PM Steven D'Aprano  wrote:

> > > * there are no difficult mental questions about evaluation order, e.g.,
> > > in a bracketed expression having multiple assignments.
> >
> > Aren't there just?
> >
> > x = 1
> > print( x + x given x = 50 )
> >
> >
> > Will that print 100, or 51? Brackets ought to make it clearer:
> >
> > (x + x given x = 50)  # this ought to return 100
> > x + (x given x = 50)  # this ought to return 51
> >
> > but if I leave the brackets out, I have no idea what I'll get.
> >
> 
> It has to be 100, or else outer parentheses change how an expression is
> evaluated.

Whether that it right or wrong, you're missing the point. You said that 
we don't have to care about evaluation order. But we do: even if your 
analysis is correct, not everyone will realise it. I didn't.

And I still don't, because I think your analyse is wrong.

"Outer parentheses" is a red herring. I should have written:

(x + x) given x = 50  # this ought to return 100
x + (x given x = 50)  # this ought to return 51

and now there are no outer parentheses to worry about. The question is 
now whether "given" binds more tightly than + or not.

We get to choose the precedence, and whatever we choose, it will 
surprise (or annoy) some people, and more importantly, some people 
simply won't know, and will have to ponder the difficult question of 
what the evaluation order is.

This is already true today with code that has side-effects. I can 
simulate "given" using exec. It only works in the module scope:

# another_expr given target = expr
exec("target = expr") or another_expr

but now we can see how precedence makes a real difference:

x = 1
x + (exec("x = 50") or x)

versus:

x = 1
exec("x = 50) or (x + x)


Regardless of which behaviour we choose, some people won't know it and 
will have to deal with "difficult mental questions about evaluation 
order".

That's unavoidable, regardless of how we spell it, := or "given".


-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] A comprehension scope issue in PEP 572

2018-05-13 Thread Tim Peters
[Tim[
>> ... If a comprehension C is in class scope S, apparently the
>> class locals are _not_ in C's environment.  Since C doesn't
>>> even have read access to S's locals, it seems to me bizarre
>> that ":=" could _create_ a local in S.

[Ethan Furman ]
> Python 3.7.0b3+ (heads/bpo-33217-dirty:28c1790, Apr  5 2018, 13:10:10)
> [GCC 4.8.2] on linux
> Type "help", "copyright", "credits" or "license" for more information.
> --> class C:
> ...   huh = 7
> ...   hah = [i for i in range(huh)]
> ...
> --> C.hah
> [0, 1, 2, 3, 4, 5, 6]
>
> Same results clear back to 3.3 (the oldest version of 3 I have).  Are the
> docs wrong?
>
> Or maybe they just refer to functions:
>
> --> class C:
> ...   huh = 7
> ...   hah = [i for i in range(huh)]
> ...   heh = lambda: [i for i in range(huh)]
> ...
> --> C.hah
> [0, 1, 2, 3, 4, 5, 6]
> --> C.heh()
> Traceback (most recent call last):
>   File "test_class_comp.py", line 7, in 
> print(C.heh())
>   File "test_class_comp.py", line 4, in 
> heh = lambda: [i for i in range(huh)]
> NameError: global name 'huh' is not defined

As Chris already explained (thanks!), the expression defining the
iterable for the outermost `for` (which, perhaps confusingly, is the
_leftmost_ `for`) is treated specially in a comprehension (or genexp),
evaluated at once _in_ the scope containing the comprehension, not in
the comprehension's own scope.  Everything else in the comprehension
is evaluated in the comprehension's scope.

I just want to add that it's really the same thing as your lambda
example.  Comprehensions are also implemented as lambdas (functions),
but invisible functions created by magic.  The synthesized function
takes one argument, which is the expression defining the iterable for
the outermost `for`.  So, skipping irrelevant-to-the-point details,
your original example is more like:

class C:
huh = 7

def _magic(it):
return [i for i in it]

hah = _magic(range(huh))

Since the `range(huh)` part is evaluated _in_ C's scope, no problem.
For a case that blows up, as Chris did you can add another `for` as
"outermost", or just try to reference a class local in the body of the
comprehension:

class C2:
huh = 7
hah = [huh for i in range(5)]

That blows up (NameError on `huh`) for the same reason your lambda
example blows up, because it's implemented like:

class C:
huh = 7

def _magic(it):
return [huh for i in it]

hah = _magic(range(5))

and C's locals are not in the environment seen by any function called
from C's scope.

A primary intent of the proposed ":= in comprehensions" change is that
you _don't_ have to learn this much about implementation cruft to
guess what a comprehension will do when it contains an assignment
expression.  The intent of

total = 0
sums = [total := total + value for value in data]

is obvious - until you think too much about it ;-)  Because there's no
function in sight, there's no reason to guess that the `total` in
`total = 0` has nothing to do with the instances of `total` inside the
comprehension.  The point of the change is to make them all refer to
the same thing, as they already do in (the syntactically similar, but
useless):

total = 0
sums = [total == total + value for value in data]

Except even _that_ doesn't work "as visually expected" in class scope
today.  The `total` inside the comprehension refers to the closest (if
any) scope (_containing_ the `class` statement) in which `total` is
local (usually the module scope, but may be a function scope if the
`class` is inside nested functions).

In function and module scopes, the second `total` example does work in
"the obvious" way, so in those scopes I'd like to see the first
`total` example do so too.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Chris Angelico
On Mon, May 14, 2018 at 12:20 AM, Juancarlo Añez  wrote:
>
>> That's an excellent point. What's "special_gcd" and how does it differ
>> from normal gcd? How am I supposed to grok that just from reading the
>> code above?
>>
>> Do I have to dig into the source of special_gcd to understand it?
>>
>
>
> One would usually define functions like special_gcd() inline, right before
> it is first used.

Okay, then. What happens to the succinctness?

On Sun, May 13, 2018 at 10:27 AM, Juancarlo Añez  wrote:
>
>> if (diff := x - x_base) and (g := gcd(diff, n)) > 1:
>>  return g
>
> I don't see the advantage in that succinctness:
>
> g = special_gcd(x - x_base, n)
> if g:
> return g

It's actually this:

def special_gcd(diff, n):
return diff and gcd(diff, n)
g = special_gcd(x - x_base, n)
if g:
return g

Yes, very succinct. You can't have it both ways; either you need a
name that completely defines the function, such that it can be placed
out-of-line without needing to be read; or you're just creating an
inline helper function, which doesn't shorten your code at all, and
just adds another layer of wrapping around everything.

Remember, you're contrasting with one of two options: either a nested
if, or an inline 'and' with the ability to capture values. What you've
created here is a multi-line way of capturing a value. That's all.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Neil Girdhar
On Sun, May 13, 2018 at 10:56 AM Steven D'Aprano 
wrote:

> On Sun, May 13, 2018 at 12:10:08AM -0400, Neil Girdhar wrote:
>
> > > > Suppose you have a generator like
> > > >
> > > > (expression(f(x), y, z)
> > > >  for x in xs
> > > >  for y in ys(x)
> > > >  for z in zs(y))
> > > >
> > > > With given notation you can optimize:
>
> Actually, as you admitted, you can't, since this isn't part of
> the proposed syntax or semantics. But let's put that aside.
>
> > > > (expression(f_x, y, z)
> > > >  for x in xs
> > > >  given f_x = f(x)
> > > >  for y in ys(x)
> > > >  for z in zs(y))
> > > >
> > > > whereas with :=, you can't.
>
> Except of course you can:
>
> > > (expression(f_x, y, z) for x in xs
> > >  for y in ys(x)
> > >  for z in zs(y)
> > >  if (f_x := f(x)) or True)
> > >  )
>
> [Neil]
> > My thought is that if each component is simple enough *and* if each
> > component can be reasoned about independently of the others, then it's
> > fine.  The issue I had with the := code you presented was that it was
> > impossible to reason about the components independently from the whole.
>
> I said it was rubbish code which I wouldn't use for serious work. But
> "impossible" to reason about? That's pretty strong, and definite, words
> for something which is actually pretty easy to reason about.
>

I was talking about this snippet you wrote:

smooth_signal = [(average := (1-decay)*average + decay*x) for x in signal]

Not impossible to reason about, but not pretty either.


>
> (expression(f_x, y, z) for x in xs
>  for y in ys(x)
>  for z in zs(y)
>  if (f_x := f(x)) or True)
>  )
>
>
Not that it matters, but this doesn't work in general since this relies on
f_x being evaluable to bool.  You can always just write "for f_x in
[f(x)]".  This use of given was more of an aside.


> I'm pretty sure you can reason about "expression(f_x, y, z)" on its own.
> After all, the above code was (apart from the := line) your own example.
> If you can't even reason about your own examples, you're in a bad place.
>
> I think you can reason about the three for-loops "for x in xs" etc on
> their own. Again, they were your idea in the first place.
>
> I expect you can reason about "if  or True" on its own. It's a
> pretty basic Python technique, to call  for its side-effect
> without caring about its return value.
>
> Not something I would use for serious work, but this is YOUR example,
> not mine, so if you hate this generator expression, you were the one who
> suggested it.
>
> Only the  is new or different from ordinary Python code that
> works now:
>
> f_x := f(x)
>
> The semantics of := are pretty damn simple (at least from the high-level
> overview without worrying about precedence or possible scoping issues):
>
> - evaluate f(x)
> - assign that value to f_x
> - return the value of f_x
>
> which is EXACTLY THE SAME SEMANTICS OF "f_x given f_x = f(x)":
>
> - evaluate f(x)
> - assign that value to f_x
> - return the value of f_x
>
> And you would reason about them the same way.
>
>
>
> --
> Steve
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
> --
>
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "python-ideas" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/python-ideas/CFuqwmE8s-E/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> python-ideas+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] keywords and backward compatibility

2018-05-13 Thread Barry Scott
There seems to be a recurring theme of ideas wanting a new keyword
but not being able to have one because of backwards compatibility.

What if I have a way to ask for the new keyword? Would that make it
easier to accept and implement some of the new ideas?

The "given" keyword for example could be allow with a statement like:

from __future__ import keyword_given

If this method of extending the python language was used for a while
I can see that the downside would be that an author of a new module
will end up potentially putting a lot of from __future__ statements as a
preamble.

Barry

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] keywords and backward compatibility

2018-05-13 Thread Chris Angelico
On Mon, May 14, 2018 at 2:08 AM, Barry Scott  wrote:
> There seems to be a recurring theme of ideas wanting a new keyword
> but not being able to have one because of backwards compatibility.
>
> What if I have a way to ask for the new keyword? Would that make it
> easier to accept and implement some of the new ideas?
>
> The "given" keyword for example could be allow with a statement like:
>
> from __future__ import keyword_given
>
> If this method of extending the python language was used for a while
> I can see that the downside would be that an author of a new module
> will end up potentially putting a lot of from __future__ statements as a
> preamble.

A future import always [1] has a target version beyond which its
effect becomes automatic. For instance, "from __future__ import
generator_stop" means that StopIteration leaking out of a generator
function is an error, but starting with Python 3.7, the altered
behaviour happens whether you have the directive or not. So a future
import does not replace backward compatibility considerations; it
simply allows the feature to be brought in progressively across
several versions.

The main problem with creating keywords is that APIs get broken. Let's
suppose that I have a module which has "def given(...)" in it. If you
import my module and try to call that function, you have to go to some
crazy shenanigans to avoid writing "mymodule.given()", which isn't
going to work. The point of a future directive is to make changes on a
module-by-module basis; that's fine for some ("division" changes the
byte code created for the slash operator, "print_function" changes the
way the word 'print' is compiled, "generator_stop" flags the generator
function), but not everything can be implemented that way.

Creating a new keyword is still a high cost.

ChrisA

[1] Except for "barry_as_FLUFL", the April Fools one, although even it
has one, technically. Kinda.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] A comprehension scope issue in PEP 572

2018-05-13 Thread Tim Peters
[Tim]
>> - If the target is not local to any function enclosing F, and is not
>> declared `global` in the block containing F, then the target is bound
>> in the block containing F.

[also Tim]
> FYI, that's still not right, ...
> I suspect that the above should be reworded to the simpler:
>
> - If the target is not  declared `global` or `nonlocal` in the block
>   containing F, then the target is bound in the block containing F.
> ...

I'm satisfied that captures the intent - but now it's misleadingly
wordy.  It should be the briefer:

- The target is bound in the block containing F.

Other text (in section 4.2.2) already covers the intended meanings for
when a `global` or `nonlocal` declaration appears in the block too.

And then it's short enough again that the bullet list isn't really
helpful anymore.  So, putting that all together:

"""
An assignment expression binds the target, except in a function F
synthesized to implement a list comprehension or generator expression
(see XXX).  In the latter case[1], the target is bound in the block
containing F, and errors may be detected:  If the target also appears
as an identifier target of a `for` loop header in F, a `SyntaxError`
exception is raised.  If the block containing F is a class block, a
`SyntaxError` exception is raised.

Footnote:
[1] The intent is that runtime binding of the target occurs as if the
binding were performed in the block containing F.  Because that
necessarily makes the target not local in F, it's an error if the
target also appears in a `for` loop header, which is a local binding
for the same target.  If the containing block is a class block, F has
no access to that block's scope, so it doesn't make sense to consider
the containing block.  The target is bound in the containing block,
where it inherits that block's `global` or `nonlocal` declaration if
one exists, else establishes that the target is local to that block.
"""

Along with the previous:

> ... targets that are identifiers if occurring in an assignment, ...
>
> " statement" should be inserted before the comma.


Of course there are other docs that need to change too.  I viewed this
as the hardest part (witness how long it took to reduce it to
near-triviality ;-) ), so wanted to get it out of the way first.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Crazy idea: allow keywords as names in certain positions

2018-05-13 Thread Rob Cliffe via Python-ideas



On 13/05/2018 19:19, Guido van Rossum wrote:
As anyone still following the inline assignment discussion knows, a 
problem with designing new syntax is that it's hard to introduce new 
keywords into the language, since all the nice words seem to be used 
as method names in popular packages. (E.g. we can't use 'where' 
because there's numpy.where 
, 
and we can't use 'given' because it's used in Hypothesis 
.)


The idea I had (not for the first time :-) is that in many syntactic 
positions we could just treat keywords as names, and that would free 
up these keywords.


For example, we could allow keywords after 'def' and after a period, 
and then the following would become legal:


class C:
    def and(self, other):
    return ...

a = C()
b = C()
print(a.and(b))

This does not create syntactic ambiguities because after 'def' and 
after a period the grammar *always* requires a NAME.


There are other positions where we could perhaps allow this, e.g. in a 
decorator, immediately after '@' (the only keyword that's 
*syntactically* legal here is 'not', though I'm not sure it would ever 
be useful).



This would not prevent code breakage when a new keyword was added. It 
would only reduce the amount of code broken.  Although in my 
unsubstantiated opinion not by very much; I suspect that most of the 
time an identifier is used in a module, it is used at least once in 
contexts where it would still be a SyntaxError if it were a keyword.

Rob Cliffe
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Nick Malaguti
I think Peter tried to outline this earlier, but what he was laying out wasn't 
clear to me at first.

There seem to be 4 variations when it comes to assignment expressions. I'm 
going to try to ignore exact keywords here since we can sort those out once we 
have settled on which variation we prefer.

1. infix: TARGET := EXPR
2. infix: EXPR as TARGET
3. prefix: let TARGET = EXPR in ANOTHER_EXPR
4. postfix: ANOTHER_EXPR given TARGET = EXPR

Both 1 and 2 may appear in the context of a larger expression where TARGET may 
or may not be used:

1. 99 + (TARGET := EXPR) ** 2 + TARGET
2. 99 + (EXPR as TARGET) ** 2 + TARGET

3 and 4 require that TARGET appear in ANOTHER_EXPR, even if TARGET is the only 
thing contained in that expression, whereas with 1 and 2, TARGET need not be 
used again.

Example I:

1. x := 10
2. 10 as x
3. let x = 10 in x
4. x given x = 10

In the simple case where the goal of the assignment expression is to bind the 
EXPR to the TARGET so that TARGET can be used in a future statement, 1 and 2 
are clearly the most straightforward because they do not require ANOTHER_EXPR.

# Please ignore that m.group(2) doesn't do anything useful here

Example II:

1. if m := re.match(...): m.group(2)
2. if re.match(...) as m: res = m.group(2)
3. if let m = re.match(...) in m: m.group(2)
4. if m given m = re.match(...): m.group(2)

I also think expressions that use "or" or "and" to make a compound expression 
benefit from the infix style, mostly because each sub-expression stands on its 
own and is only made longer with the repetition of TARGET:

Example III:

1. if (diff := x - x_base) and (g := gcd(diff, n)) > 1: ...
2. if (x - x_base as diff) and (gcd(diff, n) as g) > 1: ...
3. if (let diff = x - x_base in diff) and (let g = gcd(diff, n) in g > 1): ...
4. if (diff given diff = x - x_base) and (g > 1 given g = gcd(diff, n)): ...

In the more complex case where TARGET is reused in the expression, I find 3 and 
4 to benefit as there is a separation of the binding from its usage. I can 
consider each expression separately and I don't have to deal with the 
assignment side effects at the same time. I believe this is what Neil is mostly 
arguing for.

# Borrowing from Andre, please forgive any mathematical problems like division 
by 0

Example IV:

1:  [(-b/(2*a) + (D := sqrt( (b/(2*a))**2 - c/a), -b/(2*a) - D) 
   for a in range(10) 
   for b in range(10)
   for c in range(10)
   if D >= 0]
2:  [(-b/(2*a) + (sqrt( (b/(2*a))**2 - c/a as D), -b/(2*a) - D) 
for a in range(10) 
for b in range(10)
for c in range(10)
if D >= 0]
3. [let D = sqrt( (b/(2*a))**2 - c/a) in 
   (-b/(2*a) + D, -b/(2*a) - D) 
   for a in range(10) 
   for b in range(10)
   for c in range(10)
   if D >= 0]
4. [(-b/(2*a) + D, -b/(2*a) - D) 
   for a in range(10) 
   for b in range(10)
   for c in range(10)
   if D >= 0
   given D = sqrt( (b/(2*a))**2 - c/a)]

Also in the case with multiple bindings I find that 3 and 4 benefit over 1 and 
2:

Example V:

1. [(x := f(y := (z := f(i) ** 2) + 1)) for i in range(10)]
2. [(f((f(i) ** 2 as z) + 1 as y) as x) for i in range(10)]
3. [let x = f(y), y = z + 1, z = f(i) ** 2 in x for i in range(10)] # maybe the 
order of the let expressions should be reversed?
4. [x given x = f(y) given y = z + 1 given z = f(i) ** 2 for i in range(10)]

No matter which variation we prefer, there are plenty of arguments to be made 
that multiple assignment expressions in a single expression or usage of the 
TARGET later in the expression is harder to work with in most cases,. And since 
1 and 2 (at least to me) are more difficult to parse in those situations, I'm 
more likely to push back on whoever writes that code to do it another way or 
split it into multiple statements.

I feel that Steven prefers 1, mostly for the reason that it makes Examples I, 
II, and III easier to write and easier to read. Neil prefers 4 because Examples 
I, II, and II still aren't that bad with 4, and are easier to work with in 
Examples IV and V.

If you feel that Examples IV and V should be written differently in the first 
place, you probably prefer infix (1 or 2).

If you feel that Examples IV and V are going to be written anyway and you want 
them to be as readable as possible, you probably prefer prefix (3) or postfix 
(4).

If you want to know what all the TARGETs are assigned to up front, you probably 
prefer 1 or 3 (for reading from left to right).

If you want to see how the TARGET is used in the larger expression up front and 
are willing to read to the end to find out if or where the TARGET has been 
defined, you probably prefer 4.

In my mind, all 4 variations have merit. I think I prefer prefix or postfix 
(postfix feels very natural to me) because I believe more complex expressions 
should be separateable (Neil argues better than I can for this).

But Steven has gone a long way to convince me that the sky won't fall if we 
choose an infix 

Re: [Python-ideas] A comprehension scope issue in PEP 572

2018-05-13 Thread Tim Peters
[Tim]
> ...
> - If the target is not local to any function enclosing F, and is not
> declared `global` in the block containing F, then the target is bound
> in the block containing F.

FYI, that's still not right, but I've been distracted by trying to
convince myself that the manual actually defines what happens when
absurdly deeply nested functions mix local values for a name at some
levels with a `global` declaration of the name at other levels.

I suspect that the above should be reworded to the simpler:

- If the target is not  declared `global` or `nonlocal` in the block
  containing F, then the target is bound in the block containing F.

That makes "intuitive sense" because if the target is declared
`global` or `nonlocal` the meaning of binding in the block is already
defined to affect a not-local scope, while if it's not declared at all
then binding in the block "should" establish that it's local.to the
block (regardless of how containing scopes treat the same name)

But whether that all follows from what the manual already says
requires more staring at it ;-)

Regardless, if anyone were to point it out, I'd agree that it _should_
count against this that establishing which names are local to a block
may require searching top-level comprehensions in the block for
assignment expressions.  On a scale of minus a million to plus a
million, I'd only weight that in the negative thousands, though ;-)
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Chris Angelico
On Mon, May 14, 2018 at 7:00 AM, Cameron Simpson  wrote:
> While I can see the issue, on a personal basis I'd accept it: import and
> except don't do this and they happily use "as". In my mind the problem lies
> with "with" (and is a perfectly acceptable inconsistency there, given what
> with does for us).

The same problem happens with 'except', only less subtly.

except Exception as e: # binds the caught exception to e
except (Exception as e): # would bind the type Exception

import doesn't put an expression on the left of 'as', so it's less
likely to cause confusion; but all three of them do something special
before binding to the target given with 'as'.

By the way: do you know which of the three support arbitrary
assignment targets and which support only names? No? Neither did I,
till I checked the grammar. So there's no consistency there, other
than a loose sense that "as" means "we're gonna toss something into
somewhere". Not nearly enough to justify using that syntax for
arbitrary name bindings, given how much hassle there is with 'with'.

ChrisA
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Cameron Simpson

On 14May2018 02:04, Steven D'Aprano  wrote:

"Outer parentheses" is a red herring. I should have written:

   (x + x) given x = 50  # this ought to return 100
   x + (x given x = 50)  # this ought to return 51

and now there are no outer parentheses to worry about. The question is
now whether "given" binds more tightly than + or not.


Just to this: as a general principle I think "words" should bind less tightly 
than "punctuationlike operators".


Certainly for myself I read most code as "words surrounding expressions". While 
"given" and "for (comprehension)" and so forth are all words within expressions 
as far as the language grammar goes, to my intuition and _visually_ they are 
bulky separators between terse "mathy" things. Even the Boolean words "and", 
"or", "not"...) fit this role.


So as a matter of egonomic design "given" ought also to bind less tightly than 
"+". Arithmetic before logic before declaration before control, if you like.


Cheers,
Cameron Simpson 
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Inline assignments using "given" clauses

2018-05-13 Thread Cameron Simpson

On 13May2018 06:45, Eric V. Smith  wrote:

On 5/13/18 1:05 AM, Chris Angelico wrote:

On Sun, May 13, 2018 at 2:58 PM, Cameron Simpson  wrote:

On 13May2018 14:23, Chris Angelico  wrote:

https://www.python.org/dev/peps/pep-0572/#alternative-spellings


[...] I'd already looked at that part of the PEP and found
its explaination... unfulfilling. It says:

EXPR as NAME:

  stuff = [[f(x) as y, x/y] for x in range(5)]

Since EXPR as NAME already has meaning in except and with statements (with
different semantics), this would create unnecessary confusion or require
special-casing (eg to forbid assignment within the headers of these
statements).

[...]

There were a large number of posts, so I can't really point to one of
them. The problem isn't the double-as case that you describe; it's
that these two are ALMOST identical:

with expr as target:
with (expr as target):

In fact, they are functionally identical for many situations - "with
(open(...) as target):" is exactly the same as the form without the
parens. It'd make for data-dependent bugs, which are a really REALLY
bad idea.


A little more detail:

The first one is partially:

target = expr.__enter__()

The second one is partially:

target = expr

For many objects, obj.__enter__() just returns obj, it often looks 
like these two statements do the same thing, but they do not.


Ah, thank you!

Technically I knew this; in practice I'd forgotten and was thus vulnerable in 
exactly the same way as you anticipate.


Chris's concern, which I share, is that users wouldn't know why these are 
different, and why the second on works for some objects but not others.


While I can see the issue, on a personal basis I'd accept it: import and except 
don't do this and they happily use "as". In my mind the problem lies with 
"with" (and is a perfectly acceptable inconsistency there, given what with does 
for us).  I agree the change in semantics is not obvious. But we've got a 
similar thing with tuples as well:


 x = (1)
 x = (1,)

with a different spelling.


I agree the PEP could use more detail in explaining this particular issue.


Yes. This issue certainly isn't clear to me from the PEP's wording.

I'm no longer trying to push the "as" agenda here, BTW. I still like it, but 
that ship seems sailed.


Cheers,
Cameron Simpson 
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Crazy idea: allow keywords as names in certain positions

2018-05-13 Thread Greg Ewing

Guido van Rossum wrote:
Of course this would still not help for names of functions that might be 
imported directly (do people write 'from numpy import where'?).


Maybe things could be rigged so that if you use a reserved word
as a name in an import statement, it's treated as a name everywhere
else in that module. Then "from numpy import where" would Just Work.

--
Greg
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Crazy idea: allow keywords as names in certain positions

2018-05-13 Thread Greg Ewing

Elias Tarhini wrote:
The thought of writing "operator.not" is appealing, but 
being forced to use *that* (with *from operator import not* being 
non-allowable) may not be.


Under the proposal I made in my last post, "from operator import not"
would be fine -- you just wouldn't be able to use the "not" operator
anywhere in the module then. :-)

A more nuanced version would have the effect restricted to the
scope the import appears in, so that you could write

   def f():
  from operator import not
  # 'not' is now an ordinary name inside this
  # function, but it's business as usual elsewhere

Someone else can figure out how to make the parser handle
this, though. :-)

--
Greg
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Crazy idea: allow keywords as names in certain positions

2018-05-13 Thread Carl Smith
New Python versions already use backwards incompatible syntax, but it has
to be a strict superset so the new parser still parses old code. If a new
Python version introduced syntax that would break old code, it would still
work, so long as the parser knew which syntax the file contained, and was
able to parse both versions.

I personally think Python 3 should have always had a new file extension
(mainly to help editors disambiguate), but some kind of directive at the
top of the file would work as well, a bit like JavaScript's Strict Mode.

The killer objection is that you have to maintain two parsers or some kind
of mashup, but still, the old syntax would be frozen, there could be a lot
of reuse in the front end, and there would still only be one VM.

I'm not hoping this happens any time soon, but if was a choice between devs
maintaining two parsers or users migrating to Python 4, as a user...


-- Carl Smith
carl.in...@gmail.com

On 14 May 2018 at 02:28, Greg Ewing  wrote:

> Rob Cliffe via Python-ideas wrote:
>
>> def and(x, y):
>> return ...
>>
>> #   and(1,2)   #  Oops, SyntaxError.  Oh, I know:
>> globals()['and'](1,2)# Works!
>>
>
> If the rule I proposed for "import" were extended to "def"
> then and(1,2) would work. The usual way of using "and" would
> no longer work in that module, but this just goes to show
> that redefining "and" is a silly thing to do in the first
> place.
>
> Redefining the existing keywords could perhaps be forbidden
> if you really want to protect people from shooting themselves
> in the kidneys this particular way.
>
>
> --
> Greg
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Crazy idea: allow keywords as names in certain positions

2018-05-13 Thread Nathaniel Smith
On Sun, May 13, 2018 at 9:00 PM, Greg Ewing  wrote:
> Guido van Rossum wrote:
>>
>> Of course this would still not help for names of functions that might be
>> imported directly (do people write 'from numpy import where'?).
>
>
> Maybe things could be rigged so that if you use a reserved word
> as a name in an import statement, it's treated as a name everywhere
> else in that module. Then "from numpy import where" would Just Work.

'from numpy import *' is also common.

-n

-- 
Nathaniel J. Smith -- https://vorpus.org
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Crazy idea: allow keywords as names in certain positions

2018-05-13 Thread Rob Cliffe via Python-ideas



On 13/05/2018 19:19, Guido van Rossum wrote:
As anyone still following the inline assignment discussion knows, a 
problem with designing new syntax is that it's hard to introduce new 
keywords into the language, since all the nice words seem to be used 
as method names in popular packages. (E.g. we can't use 'where' 
because there's numpy.where 
, 
and we can't use 'given' because it's used in Hypothesis 
.)


The idea I had (not for the first time :-) is that in many syntactic 
positions we could just treat keywords as names, and that would free 
up these keywords.


For example, we could allow keywords after 'def' and after a period, 
and then the following would become legal:


class C:
    def and(self, other):
    return ...

a = C()
b = C()
print(a.and(b))

This does not create syntactic ambiguities because after 'def' and 
after a period the grammar *always* requires a NAME.


There are other positions where we could perhaps allow this, e.g. in a 
decorator, immediately after '@' (the only keyword that's 
*syntactically* legal here is 'not', though I'm not sure it would ever 
be useful).




Please, imagine how you would write the documentation to explain this.
Then, please, put yourself in the position of someone who teaches Python 
trying to explain it.

Regards
Rob Cliffe
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Crazy idea: allow keywords as names in certain positions

2018-05-13 Thread Rob Cliffe via Python-ideas



On 14/05/2018 02:28, Greg Ewing wrote:

Rob Cliffe via Python-ideas wrote:

    def and(x, y):
    return ...

#   and(1,2)   #  Oops, SyntaxError.  Oh, I know:
    globals()['and'](1,2)    # Works!


If the rule I proposed for "import" were extended to "def"
then and(1,2) would work. The usual way of using "and" would
no longer work in that module, but this just goes to show
that redefining "and" is a silly thing to do in the first
place.

Redefining the existing keywords could perhaps be forbidden
if you really want to protect people from shooting themselves
in the kidneys this particular way.

If you forbid redefining keywords, you remove the whole point of this 
proposal: to allow keywords to be sometimes used as bona fide keywords, 
sometimes as identifiers.


I really do not intend to give offence (I know that that's 
counter-productive).  But I have formed a very strong opinion - which of 
course may be wrong, and certainly won't be universally shared - and I 
am honestly expressing that opinion: Nothing I have seen in this thread 
so far has persuaded me that this proposal has any merit.


___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Crazy idea: allow keywords as names in certain positions

2018-05-13 Thread Carl Smith
As long as any new syntax allowed us to still reference the occassional
thing in the older libraries that used newly reserved names, it would
not come up that often, and would avoid the biggest cost of a whole
new version.

If `foo` was a reserved word, then this could be allowed...

import foo as bar

...but not these...

import foo
import bar as foo

The same could be done with params, so this would be illegal...

def f(foo): ...

...but this would be fine...

f(foo=1)

It would be illegal to define a property named `foo`, but you could
still do `bar.foo` to use a library, etc.

It could be done, but it's not especially relevant here, so I'll shut up
now.


-- Carl Smith
carl.in...@gmail.com

On 14 May 2018 at 03:47, Rob Cliffe via Python-ideas <
python-ideas@python.org> wrote:

>
>
> On 13/05/2018 19:19, Guido van Rossum wrote:
>
> As anyone still following the inline assignment discussion knows, a
> problem with designing new syntax is that it's hard to introduce new
> keywords into the language, since all the nice words seem to be used as
> method names in popular packages. (E.g. we can't use 'where' because
> there's numpy.where
> ,
> and we can't use 'given' because it's used in Hypothesis
> .)
>
> The idea I had (not for the first time :-) is that in many syntactic
> positions we could just treat keywords as names, and that would free up
> these keywords.
>
> For example, we could allow keywords after 'def' and after a period, and
> then the following would become legal:
>
> class C:
> def and(self, other):
> return ...
>
> a = C()
> b = C()
> print(a.and(b))
>
> This does not create syntactic ambiguities because after 'def' and after a
> period the grammar *always* requires a NAME.
>
> There are other positions where we could perhaps allow this, e.g. in a
> decorator, immediately after '@' (the only keyword that's *syntactically*
> legal here is 'not', though I'm not sure it would ever be useful).
>
>
> Please, imagine how you would write the documentation to explain this.
> Then, please, put yourself in the position of someone who teaches Python
> trying to explain it.
> Regards
> Rob Cliffe
>
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/