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

2018-05-14 Thread Nick Coghlan
On 14 May 2018 at 08:24, Ed Kellett  wrote:

> On 2018-05-14 05:02, Nick Coghlan wrote:
> > 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)
>
> I suspect that SQL is not high on the list of languages people might
> confuse with Python.


If we used "where" as a name binding keyword, ORM docs like
http://docs.sqlalchemy.org/en/latest/orm/query.html, and
https://docs.djangoproject.com/en/2.0/topics/db/queries/ would need to be
modified to explain that "SQL WHERE" and "Python where" do very different
things.

It's better to just avoid the potential for that problem entirely (either
by using a symbolic notation, or by using a different keyword)


> FWIW, as I'm sure will have been mentioned, Haskell
> uses "where", and people seem to manage fine with it.
>

Unfortunately, Haskell's adoption numbers and reputation as a difficult to
learn language don't back up that assumption (I doubt that outcome has
anything to do with their use of "where", it just means "Haskell uses it
that way" can't be credited as evidence that something won't cause
confusion)

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-14 Thread Ed Kellett
On 2018-05-14 05:02, Nick Coghlan wrote:
> 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)

I suspect that SQL is not high on the list of languages people might
confuse with Python. FWIW, as I'm sure will have been mentioned, Haskell
uses "where", and people seem to manage fine with it.



signature.asc
Description: OpenPGP digital signature
___
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] "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] "given" vs ":=" in list comprehensions

2018-05-12 Thread Chris Angelico
On Sun, May 13, 2018 at 10:34 AM, Andre Roberge  wrote:
> Second example: multiple assignments.
>
> When we have multiple temporary assignments, the situation can be more
> complicated.  In the following series of examples, I will start in reverse
> order compared to above.
>
> 5) using *where* before the iterations
>
> real_roots2 = [ (-b/(2*a) + D, -b/(2*a) - D)
>  where D= sqrt( (b/(2*a))**2 - c/a)
>  where c = c_values/100
>  for c_values in range(1000)
>  if D >= 0]
>
> 6) using *given* before the iterations
>
> real_roots2 = [ (-b/(2*a) + D, -b/(2*a) - D)
>  given D= sqrt( (b/(2*a))**2 - c/a)
>  given c = c_values/100
>  for c_values in range(1000)
>  if D >= 0]
>
> 7) using *given* at the very end
>
> real_roots2 = [ (-b/(2*a) + D, -b/(2*a) - D)
>  for c_values in range(1000)
>  if D >= 0
>  given D= sqrt( (b/(2*a))**2 - c/a)
>  given c = c_values/100]

In what order are multiple assignments performed? I guarantee you that
whichever you pick, people will wonder why you didn't pick the other.
For instance, you've used the word "given" twice, and they appear to
nest; but can you use 'c' in the main body?

The 'for' loops all execute left to right. Now you're introducing
'given' statements that execute from right to left. I think.

> 8) Using :=
>
> real_roots2 = [  ( -b/(2*a) + (D:= sqrt( (b/(2*a))**2 -
> (c:=c_values/100)/a),
>-b/(2*a) - D)
>  for c_values in range(1000)
>  if D >= 0]
>
> I find this last version extremely difficult to understand compared with the
> others where a keyword is used.  Perhaps it is because I do not fully
> understand how := should be used...

It's used where you want to have an expression that you then capture
the value of.

> Finally ... if "where" cannot be used, given the very special status of such
> temporary assignments, could "where_" (with a trailing underscore) be
> considered? I would argue that any word followed by an underscore would be
> more readable than a compound symbol such as ":=".

Definitely not. There is a strong convention around Python that goes
the opposite way: if you want to use a keyword like "class" in your
API, you use "class_" to avoid the clash. Creating a keyword that
inverts this is going to cause nothing but pain.

For the situation you're looking for, 'given' is going to be at least
as good. But I am still far from convinced that it's better than ':='.
Pushing the expression out-of-line creates confusing order of
evaluation, whereas prepending 'NAME :=' to an expression doesn't
change when anything's evaluated.

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] "given" vs ":=" in list comprehensions

2018-05-12 Thread Andre Roberge
 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)

Here are two sets of two examples illustrating a situation that I have not
seen before, and which read (to me) much better when using a keyword (given
or where) than a symbol (:=). Furthermore, the position of the temporary
assignment can, in my opinion, be done differently and help in making the
code clearer.

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]

2) using *given* at the very end

real_roots = [ (-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)]

3) using *given* before the iterations

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

4) using *where* before the iterations  (which would be my preferred choice
if it were available)

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

Second example: multiple assignments.

When we have multiple temporary assignments, the situation can be more
complicated.  In the following series of examples, I will start in reverse
order compared to above.

5) using *where* before the iterations

real_roots2 = [ (-b/(2*a) + D, -b/(2*a) - D)
 where D= sqrt( (b/(2*a))**2 - c/a)
 where c = c_values/100
 for c_values in range(1000)
 if D >= 0]

6) using *given* before the iterations

real_roots2 = [ (-b/(2*a) + D, -b/(2*a) - D)
 given D= sqrt( (b/(2*a))**2 - c/a)
 given c = c_values/100
 for c_values in range(1000)
 if D >= 0]

7) using *given* at the very end

real_roots2 = [ (-b/(2*a) + D, -b/(2*a) - D)
 for c_values in range(1000)
 if D >= 0
 given D= sqrt( (b/(2*a))**2 - c/a)
 given c = c_values/100]


8) Using :=

real_roots2 = [  ( -b/(2*a) + (D:= sqrt( (b/(2*a))**2 -
(c:=c_values/100)/a),
   -b/(2*a) - D)
 for c_values in range(1000)
 if D >= 0]

I find this last version extremely difficult to understand compared with
the others where a keyword is used.  Perhaps it is because I do not fully
understand how := should be used...

Finally ... if "where" cannot be used, given the very special status of
such temporary assignments, could "where_" (with a trailing underscore) be
considered? I would argue that any word followed by an underscore would be
more readable than a compound symbol such as ":=".

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