Re: [Python-ideas] Revisiting dedicated overloadable boolean operators

2018-08-03 Thread Benedikt Werner
The proposal is for new operators.  The operators would be "bNOT", 
"bAND", "bOR", and "bXOR".  They would be completely independent of 
the existing "not", "and", and "or" operators, operating purely on 
boolean values.  It would be possible to overload these operators.

I see, I misunderstood you there.
Then I have to say that these names really don't feel very pythonic to 
me. I guess they are still the best names out of the ones I have seen so 
far but I still don't like them very much.


I guess having overloadable operators with proper precedences would be 
quite handy for fluent style APIs but I don't think it's worth 
justifying a new set of operators.
___
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] Revisiting dedicated overloadable boolean operators

2018-08-03 Thread Todd
On Fri, Aug 3, 2018 at 5:38 PM, Chris Barker  wrote:

> On Fri, Aug 3, 2018 at 1:02 PM, Nicholas Chammas <
> nicholas.cham...@gmail.com> wrote:
>
>>  The project overloaded the bitwise operators &, |, and ~ since they
>> could not
>>
> override the boolean operators and, or, and not.
>>
>> I actually think that is a good solution to this problem -- the fact is
> that for most data types bitwise operators are useless -- and for even more
> not-very-useful.
>
> numpy did not do this, because, as it happens, bitwise operators can be
> useful for numpy arrays of integers (though as I write this, bitwise
> operations really aren't that common -- maybe requiring a function call for
> them would be a good way to go -- too late now).
>
> Also, in a common use-case, bitwise-and behaves the same as logical_and,
> e.g.
>
> if (arr > x) & (arr2 == y)
>
> This "works" because both arrays being bitwise-anded are boolean arrays.
>
> So you really don't need to call:
>
> np.logical_and and friends very often.
>
> so -1 on yet another set of operartors.
>
> -CHB
>
>
There are a few problems with using the bitwise operators.

First, and most important in my opinion, is that the precedence is
significantly off from that of the logical operators.  As your own example
shows, any non-trivial example requires a lot of parentheses to keep things
working.  And if you are switching back and forth between, say, array
logical operations and "normal" logical operations it is easy to mess up.

Second is that it can be restricted to only working on boolean-like data
types.  Combining how easy it is to get the precedence wrong with the fact
that getting it wrong can silently fail is not a good combination in my
opinion.  Making sure the operator is actually doing what people want and
expect it to do seems like a big benefit to me.

Third is that it allows both boolean and bitwise operations to be carried
out on the same data types.  Numpy is a special case where the two
basically are equivalent if you are working with boolean arrays.  But that
is a special case.
___
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] Revisiting dedicated overloadable boolean operators

2018-08-03 Thread Todd
On Fri, Aug 3, 2018 at 6:05 PM, Benedikt Werner <1benediktwer...@gmail.com>
wrote:

> There was a proposal to allow overloading boolean operators in Pep-335
>> [2], but that PEP was rejected for a variety of very good reasons.  I think
>> none of those reasons (besides the conversation fizzling out) apply to my
>> proposal.
>>
> Maybe I am missing something, but I don't really see how this idea solves
> the problems that lead to PEP 335 getting rejected. As far as I understand
> it the main reason for the rejection was that this would decrease
> performance for all boolean operations which are extremely common where as
> the need for overriding these operators is rather rare. (See the rejection
> email here: https://mail.python.org/pipermail/python-dev/2012-March/
> 117510.html)
>
> As I see it this proposal only proposes a different syntax and doesn't
> solve this problem.
>
> The only real solution for this would be a new set of operators but I
> agree with Chris that overriding the bitwise operators is good enough for
> most cases and a new set of operators really is a bit over the top just for
> this. I especially dislike using || and && as they are prominently used in
> other programming languages and this would be extremely confusing for
> newcomers from those languages. Also if the syntax isn't clear and consice
> I feel it doesn't really add any value as the main point of operator
> overloading is to make code easy to read and understand. This really only
> would be the case if we could overload the boolean operators. Otherweise I
> think using a function or overloading the bitwise ops is the best solution.
>
>
The proposal is for new operators.  The operators would be "bNOT", "bAND",
"bOR", and "bXOR".  They would be completely independent of the existing
"not", "and", and "or" operators, operating purely on boolean values.  It
would be possible to overload these operators.
___
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] PEP 505: None-aware operators: operators ?= and ?? and OR

2018-08-03 Thread Eric Fahlgren
On Fri, Aug 3, 2018 at 6:19 PM Steven D'Aprano  wrote:

> It needs some work. Something like "Here's an example in the standard
> library. On converting it to none-aware version, we realised the std lib
> version is buggy, because ...". A couple of sentences.
>

Yup, that's what I was getting at...
___
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] With expressions

2018-08-03 Thread Steven D'Aprano
On Sat, Aug 04, 2018 at 12:28:40AM +0200, Robert Vanden Eynde wrote:

> As the code I showed, being just that:
> 
> filename = ...
> lines = ...
> parsed_data = ...
> 
> With implementation details? The highest value is there, the alg is clear.,
> one fetches the filename, one preprocess the lines, then parse the data.

As programmers, surely we have to care about implementation details of 
the code we are maintaining or writing. If we don't care about 
implementation, who does?

Of course there is a tension between having to deal with implementation 
details too earlier, or hiding them too deeply. We have to balance too 
little refactoring from too much refactoring, and people can 
legitimately disagree as to when a function, method or class carries its 
own weight.

The same applies to syntactic features. That's why *concrete use-cases* 
are important, not pretend, made-up toy examples.

The Python community as a whole is not very receptive to arguments from 
functional programming purity. I know Python veterans who still don't 
like list comprehensions (although they're a minority). As a whole, the 
community does not believe that using multiple statements is always a 
problem to be fixed.

The question is not whether it is *possible* to have a with expression, 
or whether we might find some toy examples that kinda look good, but how 
much it improves *real code*.

And arguments that we should have a "with" expression because we already 
have "if" expressions and comprehensions will just fall flat. Arguments 
by consistency ("we have A, so we ought to have E too, because they're 
both vowels") are not very productive.


-- 
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] PEP 505: None-aware operators: operators ?= and ?? and OR

2018-08-03 Thread Steven D'Aprano
On Fri, Aug 03, 2018 at 06:30:25AM -0700, Eric Fahlgren wrote:

> After looking at the code a bit more, I agree, we've uncovered a bug in the
> stdlib and the null coalescing version actually fixes it.
[...]
> But!  We are not here to talk about bugs in the email package, this
> discussion is about PEP 505, which means to me that the example is a bug in
> the PEP.

On the contrary! It strongly suggests to me that None-aware operators, 
or at least this one, makes it *easier* to write correct code than 
incorrect code.

If your analysis that the email package is buggy is correct, this is a 
strong example in favour of the none-aware operator.


> In my view, the before and after examples should have identical
> results, unless there is some very clear and thorough discussion
> accompanying the example as to why they are different and more importantly,
> why the "after" version is better or worse.  In this light, the example
> certainly needs a lot of work.

It needs some work. Something like "Here's an example in the standard 
library. On converting it to none-aware version, we realised the std lib 
version is buggy, because ...". A couple of sentences.


-- 
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] Revisiting dedicated overloadable boolean operators

2018-08-03 Thread MRAB

On 2018-08-03 23:05, Benedikt Werner wrote:
There was a proposal to allow overloading boolean operators in Pep-335 
[2], but that PEP was rejected for a variety of very good reasons.  I 
think none of those reasons (besides the conversation fizzling out) 
apply to my proposal.

Maybe I am missing something, but I don't really see how this idea
solves the problems that lead to PEP 335 getting rejected. As far as I
understand it the main reason for the rejection was that this would
decrease performance for all boolean operations which are extremely
common where as the need for overriding these operators is rather rare.
(See the rejection email here:
https://mail.python.org/pipermail/python-dev/2012-March/117510.html)

As I see it this proposal only proposes a different syntax and doesn't
solve this problem.


[snip]

I've been re-reading PEP 335 and I think that the __and1__ method isn't 
needed.


The __bool__ method is called anyway, and currently must return either 
False or True, but what if it could return the special value 
NeedOtherOperand mentioned in the PEP?


The disadvantage would be that if the first operand is a bool, the 
operator could still short-circuit, and I'm not sure how much of an 
issue that would be.

___
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] With expressions

2018-08-03 Thread Steven D'Aprano
On Fri, Aug 03, 2018 at 12:49:24PM +0200, Robert Vanden Eynde wrote:

> Le ven. 3 août 2018 à 03:07, Steven D'Aprano  a écrit :
> 
> > On Thu, Aug 02, 2018 at 03:13:25PM +0200, Robert Vanden Eynde wrote:
> >
> > > This brings the discussion of variable assignement in Expression.
> > Functional
> > > programming community seems to be more interested in python.
> >
> > I'm not sure what you mean there. Your English grammar is just slightly
> > off, enough to make your meaning unclear, sorry.
> >
> 
> When I say "functional programming", I speak about the paradigm used in
> language like Haskell.

I know what functional programming is. What I don't understand is what 
you mean when you say that the F.P. community "seems to be more 
interested in python". Surely they are more interested in functional 
languages than a multi-paradigm language like Python which does not 
privilege functional idioms over imperative idioms.


[...]
> > try...except exceptions have been proposed before and rejected.
> 
> I'm wondering why, that must have been the same reasons of not accepting
> "with".

Read the PEP. Or the (long!) discussions on Python-Ideas and Python-Dev.

https://www.python.org/dev/peps/pep-0463/


> > > value = (x+y**2 where x,y = (2,4))
> >
> > A "where" *statement* is interesting, but this is not a good example of
> > it. The above is better written in the normal syntax:
> >
> > value = 2 + 4**2
> 
> 
> That's the discussion we had on the list called "variable assignement in
> expressions". What you did here is inlining the variables, technically it's
> not possible if you're calling a function and using the variable more than
> once.

Which is why I said it was not a good example. If you're going to 
propose syntax, you ought to give good examples, not bad examples.

In any case, this is not a proposal for a "where" expression. You aren't 
going to convince people to add a "with" expression by showing them 
expression forms of "if", "for" or hypothetical "where". Each feature 
must justify itself, not sneak in behind another feature.


[...]
> > > with open('hello') as f:
> > > lines = f.readlines()
> > > del f  # f is leaked !
> >
> > 99% of the time, I would think that "del f" was a waste of time. If that
> > code is in function, then f will be closed when the "with" block is
> > exited, and garbage collected when the function returns.
> 
> Yes of course, but what if "f" was defined before? We lose its value, even
> if "f" was created only as a temporary variable to have the variables lines.
[...]
> But maybe we are in a script and we have a lots of
> variables? That kind of questions arise, when we wanted a temporary
> variable.

Then don't use f. Use F, fi, fp, fileobj, f_, f1, ϕ, фп, or 
myfileobject. Surely you haven't used them all. There is no shortage of 
useful identifier names.

Or factor your code into named functions with isolated namespaces, so 
the f in one function doesn't clobber the f in another function. 
Structured programming won the debate against unstructured programming a 
long time ago.

https://en.wikipedia.org/wiki/Structured_programming#History


[...]
> One difficultly of finding use cases, it that it's about changing the
> paradigm, probably all cases have a really readable implementation in
> current python / imperative style. But when I see:
> 
> try:
> a_variable = int(input("..."))
> except ValueError:
> try:
>a_variable = fetch_db()
> except DbError:
>a_variable = default
> 
> I really think "why can't I put it one one line like I do with if".
> 
> a_variable = (int(input("...")) except ValueError:
>fetch_db() except DbError:
>default)

Whereas when I see somebody using a double if...else expression in a 
single line, I wish they would spread it out over multiple lines so it 
is readable and understandable, instead of trying to squeeze the maximum 
amount of code per line they can.


> For "with", I'm just wondering "why do I have to indent, it will lose the
> focus of the reader on the result itself".

If this is a problem, then you can easily focus the reader on the 
result by factoring the code into a named function.

text = read('filename')

requires no indentation, no complicated new syntax, and it is easily 
extensible to more complex examples:

text = (prefix + (read('filename') or 'default') + moretext).upper()

This argument isn't about whether it might occasionally be useful to use 
a with expression, but whether it is useful *enough* to justify adding 
new syntax to the language.


-- 
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] With expressions

2018-08-03 Thread Eric Fahlgren
On Fri, Aug 3, 2018 at 5:26 PM Abe Dillon  wrote:

> One last thing:
>
> Since expressions tend to have pretty limited space, it might be worth it
> to consider more concise options like maybe instead of:
>
>  except (Exception[-list])[ as e]): 
>

You're reinventing PEP 463:

https://www.python.org/dev/peps/pep-0463/
___
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] With expressions

2018-08-03 Thread Abe Dillon
One last thing:

Since expressions tend to have pretty limited space, it might be worth it
to consider more concise options like maybe instead of:

 except (Exception[-list])[ as e]): 

it could be:

 (Exception[-list])[ as e])! 

So:

y = x[0] IndexError! default

instead of

y = x[0] except IndexError: default

or:

y = spam.ham[0] (AttributeError, IndexError) as e! foo(e)

instead of

y = spam.ham[0] except (AttributeError, IndexError) as e: foo(e)

Or something to that effect. (thought I think it might be best to err on
the side of 'except' because it's more clear what it does and it only adds
7 characters).

On Fri, Aug 3, 2018 at 6:57 PM, Abe Dillon  wrote:

> [Benedikt Werner]
>
>> As the with-expression mimics the with-statement I would say this is
>> similar to:
>> with supress(AttributeError):
>> tmp = person.name[0]
>> initial = tmp # Error on assignment wouldn't get suppressed. Not relevant
>> for this case but still.
>
>
> Ah, yes. That makes much more sense now. I would say the error on
> assignment IS relevant for that case and it's not clear to me how you would
> present that error to the user without causing a lot of confusion.
>
> If it were implemented as:
>
> tmp = None
> with suppress(AttributeError):
> tmp = person.name[0]
> initial = tmp
>
> Then it would solve many of the common use cases for the None-aware
> operators proposed in PEP 505, especially if we made it easy to filter out
> None-specific errors:
>
> class NoneError(BaseException):
> pass
>
> class NoneAttributeError(AttributeError, NoneError):
> pass
>
> ... code to make erroneous attribute access on NoneType objects throw
> NoneAttributeErrors ...
> ... shouldn't break much code other than maybe some doc-string tests ...
>
> initial = person.name[0] with suppress(NoneError)
>
> [Robert Vanden Eynde]
>
>> With implementation details? The highest value is there, the alg is
>> clear., one fetches the filename, one preprocess the lines, then parse the
>> data.
>
>
> Yes. Sorry for using confusing language. I was trying to say that I like
> your proposed syntax (for both with and except) because it follows the same
> principal. At the same time, I was trying to demonstrate part of the value
> of expression-ized statements to everyone else. Since Python is strictly
> evaluated statement by statement, there is no notion of looking ahead and
> re-ordering code. You can't use a variable in one statement then define
> that variable later on (like you do in comprehensions). Expressions, on the
> other hand; are parsed in a more complex way, so you can do things like put
> the relevant logic up front and move all the book-keeping to the end.
>
> [Robert Vanden Eynde]
>
>> About if elif elif else, ternary if does have that:
>> y = (x+1 if x < 0 else
>>  x-1 if x > 0 else
>>  0)
>
>
> True, and your except syntax could chain in a similar manner. In-fact it
> might be possible to make a separate "finally" operator that executes the
> left side then executes the right side no matter what:
>
> y = ((x[0] except InxexError: x.default) except AttributeError: None)
> finally print("hello!")
>
> [Robert Vanden Eynde]
>
>> Limiting the scope is interesting, for "with" the only limitation in that
>> the body must have exactly one assignment, like in the ternary if case?
>> a = ([l.strip() for l in f.readlines()] with open ('name') as f)
>> By cutting the edge cases, "with something():" is not possible, only
>> "with ... as" being possible?
>
>
> I think it's better to forget what I said about limiting the scope of the
> operator. It was a half-baked thought.
>
> As for assignment expressions, they're already on their way thanks to PEP
> 572. I like the "where" version you proposed because it places the logic
> first, but unfortunately PEP 572 (4th alternate spelling
> ) states
> that they had considered that version and rejected it because "where" is a
> pretty common variable name. From the PEP:
>
> SQLAlchemy and numpy have where methods, as does tkinter.dnd.Icon in the
>> standard library
>
>
> So adding a new "where" keyword would break backwards compatibility in a
> major way.
>
> On Fri, Aug 3, 2018 at 5:40 PM, Benedikt Werner <1benediktwer...@gmail.com
> > wrote:
>
>> For instance, what would the following do?
>>
>> initial = person.name[0] with suppress(AttributeError)  # Hangover from
>> PEP 505 discussion...
>>
>> As the with-expression mimics the with-statement I would say this is
>> similar to:
>>
>> with supress(AttributeError):
>> tmp = person.name[0]
>> initial = tmp# Error on assignment wouldn't get 
>> suppressed. Not relevant for this case but still.
>>
>> I don't understand where this is ambigous?
>>
>> So maybe it only makes sense to use expression assignment (PEP 572):
>>
>> data = (d := file.read() with open(...) as file)
>>
>> To which I say, "Eww..."
>>
>> I definitely agree that this looks a bit bad but 

Re: [Python-ideas] With expressions

2018-08-03 Thread Abe Dillon
[Benedikt Werner]

> As the with-expression mimics the with-statement I would say this is
> similar to:
> with supress(AttributeError):
> tmp = person.name[0]
> initial = tmp # Error on assignment wouldn't get suppressed. Not relevant
> for this case but still.


Ah, yes. That makes much more sense now. I would say the error on
assignment IS relevant for that case and it's not clear to me how you would
present that error to the user without causing a lot of confusion.

If it were implemented as:

tmp = None
with suppress(AttributeError):
tmp = person.name[0]
initial = tmp

Then it would solve many of the common use cases for the None-aware
operators proposed in PEP 505, especially if we made it easy to filter out
None-specific errors:

class NoneError(BaseException):
pass

class NoneAttributeError(AttributeError, NoneError):
pass

... code to make erroneous attribute access on NoneType objects throw
NoneAttributeErrors ...
... shouldn't break much code other than maybe some doc-string tests ...

initial = person.name[0] with suppress(NoneError)

[Robert Vanden Eynde]

> With implementation details? The highest value is there, the alg is
> clear., one fetches the filename, one preprocess the lines, then parse the
> data.


Yes. Sorry for using confusing language. I was trying to say that I like
your proposed syntax (for both with and except) because it follows the same
principal. At the same time, I was trying to demonstrate part of the value
of expression-ized statements to everyone else. Since Python is strictly
evaluated statement by statement, there is no notion of looking ahead and
re-ordering code. You can't use a variable in one statement then define
that variable later on (like you do in comprehensions). Expressions, on the
other hand; are parsed in a more complex way, so you can do things like put
the relevant logic up front and move all the book-keeping to the end.

[Robert Vanden Eynde]

> About if elif elif else, ternary if does have that:
> y = (x+1 if x < 0 else
>  x-1 if x > 0 else
>  0)


True, and your except syntax could chain in a similar manner. In-fact it
might be possible to make a separate "finally" operator that executes the
left side then executes the right side no matter what:

y = ((x[0] except InxexError: x.default) except AttributeError: None)
finally print("hello!")

[Robert Vanden Eynde]

> Limiting the scope is interesting, for "with" the only limitation in that
> the body must have exactly one assignment, like in the ternary if case?
> a = ([l.strip() for l in f.readlines()] with open ('name') as f)
> By cutting the edge cases, "with something():" is not possible, only "with
> ... as" being possible?


I think it's better to forget what I said about limiting the scope of the
operator. It was a half-baked thought.

As for assignment expressions, they're already on their way thanks to PEP
572. I like the "where" version you proposed because it places the logic
first, but unfortunately PEP 572 (4th alternate spelling
) states
that they had considered that version and rejected it because "where" is a
pretty common variable name. From the PEP:

SQLAlchemy and numpy have where methods, as does tkinter.dnd.Icon in the
> standard library


So adding a new "where" keyword would break backwards compatibility in a
major way.

On Fri, Aug 3, 2018 at 5:40 PM, Benedikt Werner <1benediktwer...@gmail.com>
wrote:

> For instance, what would the following do?
>
> initial = person.name[0] with suppress(AttributeError)  # Hangover from
> PEP 505 discussion...
>
> As the with-expression mimics the with-statement I would say this is
> similar to:
>
> with supress(AttributeError):
> tmp = person.name[0]
> initial = tmp # Error on assignment wouldn't get suppressed. 
> Not relevant for this case but still.
>
> I don't understand where this is ambigous?
>
> So maybe it only makes sense to use expression assignment (PEP 572):
>
> data = (d := file.read() with open(...) as file)
>
> To which I say, "Eww..."
>
> I definitely agree that this looks a bit bad but I don't get why you would
> consider using an expression assignment there.
>
> data = file.read with open(...) as file
>
> works perfectly fine so why would you want to additonaly assign it to
> another variable "d"?
>
>
> Overall I like the idea of the with-expression as it allows you to make
> some common use cases like the open/read example more readable. It's clear
> at first sight that what is actually done is reading the file. While it's
> true that it's usually easy to write a simple function to do the job that
> still isn't as simple to understand and in most cases when reading the code
> you then have to look at the function to see if anything else is done
> there. Also what if you then do readlines somewhere? Then you need another
> function.
>
> ___
> Python-ideas mailing list
> 

Re: [Python-ideas] With expressions

2018-08-03 Thread Benedikt Werner

For instance, what would the following do?

initial = person.name [0] with 
suppress(AttributeError)  # Hangover from PEP 505 discussion...
As the with-expression mimics the with-statement I would say this is 
similar to:


with supress(AttributeError):
tmp = person.name[0]
initial = tmp   # Error on assignment wouldn't get suppressed. 
Not relevant for this case but still.

I don't understand where this is ambigous?


So maybe it only makes sense to use expression assignment (PEP 572):

data = (d := file.read() with open(...) as file)

To which I say, "Eww..."
I definitely agree that this looks a bit bad but I don't get why you 
would consider using an expression assignment there.


data = file.read with open(...) as file

works perfectly fine so why would you want to additonaly assign it to 
another variable "d"?



Overall I like the idea of the with-expression as it allows you to make 
some common use cases like the open/read example more readable. It's 
clear at first sight that what is actually done is reading the file. 
While it's true that it's usually easy to write a simple function to do 
the job that still isn't as simple to understand and in most cases when 
reading the code you then have to look at the function to see if 
anything else is done there. Also what if you then do readlines 
somewhere? Then you need another function.
___
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] With expressions

2018-08-03 Thread Robert Vanden Eynde
>
> Expressionization may break the "one and only on obvious way" guideline,
> but it can offer concise, readable code in a lot of instances where a
> statement-based version would be clumsy and noisy, and there's already some
> precedent for it:
>
> function declaration => lambda
> for-loops => generator expressions and comprehensions
> if-else => ternary statements
>

Totally agree. That's the problem when being multi paradigm, but we already
have that "problem" and that's alright.


> With the exception of lambda, expressionized statements usually allow one
> to put the "meat before the vegetables" so to speak. That is; the highest
> value part of the expression comes first and all the book-keeping follows
>

As the code I showed, being just that:

filename = ...
lines = ...
parsed_data = ...

With implementation details? The highest value is there, the alg is clear.,
one fetches the filename, one preprocess the lines, then parse the data.



> One tactic that other expressionizations have taken is to limit the scope.
> For instance, the ternary operation only covers expressionization of
> "if-else" not "just if" or "if-elif-..." or "if-elif-...-else", and
> generator expressions don't allow the 'else' clause
>  of normal
> for-loops. So maybe you can obviate some of the edge cases by requiring an
> as clause or something. I don't know how that would help with the
> suppress(AttributeError) case thought...
>

About if elif elif else, ternary if does have that:

y = (x+1 if x < 0 else
   x-1 if x > 0 else
   0)

Limiting the scope is interesting, for "with" the only limitation in that
the body must have exactly one assignment, like in the ternary if case?

a = ([l.strip() for l in f.readlines()] with open ('name') as f)

By cutting the edge cases, "with something():" is not possible, only "with
... as" being possible?

But the "scope limitation" for try except in expression concept would be
not to have "else" or "finally"? The else and finally clauses do not make
sense in Expression style assignment anyway.

a = (int('stuff') except ValueError: 5)


> On Fri, Aug 3, 2018 at 12:56 PM, Todd  wrote:
>
>> On Thu, Aug 2, 2018 at 5:35 AM, Ken Hilton  wrote:
>>
>>> Hi, I don't know if someone has already suggested this before, but here
>>> goes:
>>>
>>> With expressions allow using the enter/exit semantics of the with
>>> statement inside an expression context. Examples:
>>>
>>> contents = f.read() with open('file') as f #the most obvious one
>>> multiplecontents = [f.read() with open(name) as f for name in names]
>>> #reading multiple files
>>>
>>> I don't know if it's worth making the "as NAME" part of the with
>>> mandatory in an expression - is this a valid use case?
>>>
>>> data = database.selectrows() with threadlock
>>>
>>> Where this would benefit: I think the major use case is `f.read() with
>>> open('file') as f`. Previous documentation has suggested
>>> `open('file').read()` and rely on garbage collection; as the disadvantages
>>> of that became obvious, it transitioned to a method that couldn't be done
>>> in an expression:
>>>
>>> with open('file') as f:
>>> contents = f.read()
>>>
>>> Therefore `f.read() with open('file') as f`, I think, would be much
>>> welcomed as the best way to read a file in an expression.
>>>
>>> For those wondering about the scope semantics of the "as NAME", I think
>>> they would be identical to the scope semantics of the "for" expression -
>>> i.e. these are legal:
>>>
>>> contents = f.read() with open('file') as f
>>> grid = [[i] * 4 for i in range(4)]
>>>
>>> But these are not:
>>>
>>> contents = f.read() with open('file') as f
>>> f.seek(0)
>>> grid = [[i] * 4 for i in range(4)]
>>> grid[i][i] = 4
>>>
>>> Is this a good idea? Are there some subtleties I've failed to explain?
>>> Please let me know.
>>>
>>> Sharing,
>>> Ken Hilton
>>>
>>>
>> If this is a common enough operation for you, it would be trivially easy
>> to just write a function that does this.  There is already a module on pypi
>> that has this function: read_and_close.
>>
>> ___
>> 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/
>
___
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] Revisiting dedicated overloadable boolean operators

2018-08-03 Thread Benedikt Werner
There was a proposal to allow overloading boolean operators in Pep-335 
[2], but that PEP was rejected for a variety of very good reasons.  I 
think none of those reasons (besides the conversation fizzling out) 
apply to my proposal.
Maybe I am missing something, but I don't really see how this idea 
solves the problems that lead to PEP 335 getting rejected. As far as I 
understand it the main reason for the rejection was that this would 
decrease performance for all boolean operations which are extremely 
common where as the need for overriding these operators is rather rare. 
(See the rejection email here: 
https://mail.python.org/pipermail/python-dev/2012-March/117510.html)


As I see it this proposal only proposes a different syntax and doesn't 
solve this problem.


The only real solution for this would be a new set of operators but I 
agree with Chris that overriding the bitwise operators is good enough 
for most cases and a new set of operators really is a bit over the top 
just for this. I especially dislike using || and && as they are 
prominently used in other programming languages and this would be 
extremely confusing for newcomers from those languages. Also if the 
syntax isn't clear and consice I feel it doesn't really add any value as 
the main point of operator overloading is to make code easy to read and 
understand. This really only would be the case if we could overload the 
boolean operators. Otherweise I think using a function or overloading 
the bitwise ops is the best solution.


___
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] Revisiting dedicated overloadable boolean operators

2018-08-03 Thread Chris Barker via Python-ideas
On Fri, Aug 3, 2018 at 1:02 PM, Nicholas Chammas  wrote:

>  The project overloaded the bitwise operators &, |, and ~ since they
> could not
>
override the boolean operators and, or, and not.
>
> I actually think that is a good solution to this problem -- the fact is
that for most data types bitwise operators are useless -- and for even more
not-very-useful.

numpy did not do this, because, as it happens, bitwise operators can be
useful for numpy arrays of integers (though as I write this, bitwise
operations really aren't that common -- maybe requiring a function call for
them would be a good way to go -- too late now).

Also, in a common use-case, bitwise-and behaves the same as logical_and,
e.g.

if (arr > x) & (arr2 == y)

This "works" because both arrays being bitwise-anded are boolean arrays.

So you really don't need to call:

np.logical_and and friends very often.

so -1 on yet another set of operartors.

-CHB



-- 

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR(206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115   (206) 526-6317   main reception

chris.bar...@noaa.gov
___
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] With expressions

2018-08-03 Thread Abe Dillon
I like this idea in theory, but I'm not sold yet.

I think there's a lot of draw to the concept of "expressionizing"
statements because many statements require an unnatural ordering in-which
the most important code, the logic, comes after some necessary but
ultimately noisy (from the readers perspective) preamble. So I expect
people to keep asking for expressionized statements and slowly, but,
surely, they'll make their way into the language. They just need to be very
carefully thought out.

Expressionization may break the "one and only on obvious way" guideline,
but it can offer concise, readable code in a lot of instances where a
statement-based version would be clumsy and noisy, and there's already some
precedent for it:

function declaration => lambda
for-loops => generator expressions and comprehensions
if-else => ternary statements

With the exception of lambda, expressionized statements usually allow one
to put the "meat before the vegitables" so to speak. That is; the highest
value part of the expression comes first and all the book-keeping follows. To
illustrate this, I'll write a part of an expression and gradually reveal
the complete expression, you can see how progressively easier it is to
predict the next reveal:

def initials(people):
return {"".join(name[0] ...

# The identifier "name" isn't in scope so it must be assigned in the for
clause of a comprehension.

def initials(people):
return {"".join(name[0] for name in ...

# This is a nested comprehension so it's not much of a surprise that the
iterator might be related to another
# yet-to-be assigned identifier.

def initials(people):
return {"".join(name[0] for name in person.names ...

# Blindly accessing the first element of an empty sequence could cause
problems

def initials(people):
return {"".join(name[0] for name in person.names if name) ...

# The inner generator is closed but we still need a binding for "person"

def initials(people):
return {"".join(name[0] for name in person.names if name) for person in
...

# There's not much left to iterate over and decent variable names point to
one obvious choice

def initials(people):
return {"".join(name[0] for name in person.names if name) for person in
people}


The same could be said for lambdas if they were defined logic-first because
they're usually used in a context where the call signature is obvious:

hand = sorted(cards, key=(card.suit if card is not wild else max_value <==
card))[-5:]

Of course, no such thing exists so the '<==' syntax is made up (in-fact a
possibly better alternative is, "with"), but it doesn't really matter
because a reverse lambda isn't going to happen. You can see, however; that
the function's signature is pretty obvious from context, so it's more for
the computer's sake than the reader's sake and would be better placed out
of the way.

I like the current proposal because it follows that design idea, however; I
haven't taken the time to think about all the edge cases yet.
For instance, what would the following do?

initial = person.name[0] with suppress(AttributeError)  # Hangover from PEP
505 discussion...

Now that I think of it, this seems to inherently make assignment part of
the expression:

data = file.read() with open(...) as file

is supposed to be equivalent to:

with open(...) as file:
data = file.read()

Right?

So maybe it only makes sense to use expression assignment (PEP 572):

data = (d := file.read() with open(...) as file)

To which I say, "Eww..."

Also:

initial = (i := person.name[0] with suppress(AttributeError))

Is still ambiguous (and still eww).

One tactic that other expressionizations have taken is to limit the scope.
For instance, the ternary operation only covers expressionization of
"if-else" not "just if" or "if-elif-..." or "if-elif-...-else", and
generator expressions don't allow the 'else' clause
 of normal for-loops.
So maybe you can obviate some of the edge cases by requiring an as clause
or something. I don't know how that would help with the
suppress(AttributeError) case thought...

On Fri, Aug 3, 2018 at 12:56 PM, Todd  wrote:

> On Thu, Aug 2, 2018 at 5:35 AM, Ken Hilton  wrote:
>
>> Hi, I don't know if someone has already suggested this before, but here
>> goes:
>>
>> With expressions allow using the enter/exit semantics of the with
>> statement inside an expression context. Examples:
>>
>> contents = f.read() with open('file') as f #the most obvious one
>> multiplecontents = [f.read() with open(name) as f for name in names]
>> #reading multiple files
>>
>> I don't know if it's worth making the "as NAME" part of the with
>> mandatory in an expression - is this a valid use case?
>>
>> data = database.selectrows() with threadlock
>>
>> Where this would benefit: I think the major use case is `f.read() with
>> open('file') as f`. Previous documentation has suggested
>> `open('file').read()` and rely on garbage collection; as the 

Re: [Python-ideas] Revisiting dedicated overloadable boolean operators

2018-08-03 Thread Nicholas Chammas
On Fri, Aug 3, 2018 at 1:47 PM Todd toddr...@gmail.com
 wrote:

The operators would be:
>
> bNOT - boolean "not"
> bAND - boolean "and"
> bOR - boolean "or"
> bXOR - boolean "xor"
>
These look pretty ugly to me. But that could just be a matter of
familiarity.

For what it’s worth, the Apache Spark project offers a popular DataFrame
API for querying tabular data, similar to Pandas. The project overloaded
the bitwise operators &, |, and ~ since they could not override the boolean
operators and, or, and not.

For example:

non_python_rhode_islanders = (
person
.where(~person['is_python_programmer'])
.where(person['state'] == 'RI' & person['age'] > 18)
.select('first_name', 'last_name')
)
non_python_rhode_islanders.show(20)

This did lead to confusion among users
 since people (myself
included) would initially try the boolean operators and wonder why they
weren’t working. So the Spark devs added a warning
 to catch when users were
making this mistake. But now it seems quite OK to me to use &, |, and ~ in
the context of Spark DataFrames, even though their use doesn’t match their
designed meaning. It’s unfortunate, but I think the Spark devs made a
practical choice that works well enough for their users.

PEP 335 would have addressed this issue by letting developers overload the
common boolean operators directly, but from what I gather of Guido’s
rejection
, the
biggest problem was that it would have had an undue performance impact on
non-users of boolean operator overloading. (Not sure if I interpreted his
email correctly.)
​
___
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] Revisiting dedicated overloadable boolean operators

2018-08-03 Thread Todd
On Fri, Aug 3, 2018 at 2:26 PM, Jonathan Fine  wrote:

> Hi Todd
>
> Thank you for your contribution! I've got a couple of comments. The
> experts, I hope, will have more to say.
>
>
Thanks for your reply, Jonathan.



> You wrote:
>
> > As to why this is useful, the overall problem is that the current logical
> > operators, like and, or, and not, cannot be overloaded, which means
> projects
> > like numpy and SQLAlchemy instead have to (ab)use bitwise operator
>
> > There was a proposal to allow overloading boolean operators in Pep-335
> [2],
> > but that PEP was rejected for a variety of very good reasons.
>
> The key thing is, I think, the wish for a domain specific language. I
> find this to be a wholesome wish. But I'd rather create a broad
> solution, than something that works just for special cases. And if at
> all possible, implement domain specific languages without extending
> the syntax and semantics of the language.
>

This proposal isn't domain-specific.  I think the fact that it would
benefit projects as diverse as numpy and SQLAlchemy (as well as others such
as sympy) demonstrates that.

Boolean operators like the sort I am discussing have been a standard part
of programming languages since forever.  In fact, they are the basic
operations on which modern microprocessors are built.

The fact that Python, strictly speaking, doesn't have them is extremely
unusual for a programming language.  In many cases they aren't necessary in
Python since Python's logical operators do the job well enough, but there
are a set of highly diverse and highly prominent cases where those logical
operators won't work.  There are workarounds, but they are less than
optimal for the reasons I describe, and the previous discussion I linked to
goes into much more detail why these new operators are important.

There is the problem of short-circuiting evaluation, as in the 'and'
> and 'or' operators (and elsewhere in Python). This has to be a syntax
> and semantics feature. It can't be controlled by the objects.
>

Yes, sorry, I left that out.  The consensus from the previous discussion is
that this wouldn't be short-circuiting.  I can imagine ways to support
short-circuiting as well (such as a second set of dunder methods with one
set overriding the other), but it isn't really relevant to my proposal.
This proposal is assuming the semantics from the previous discussion.  All
I am trying to address here is how the operators would be spelled.
___
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] Revisiting dedicated overloadable boolean operators

2018-08-03 Thread Jonathan Fine
Hi Todd

Thank you for your contribution! I've got a couple of comments. The
experts, I hope, will have more to say.

You wrote:

> As to why this is useful, the overall problem is that the current logical
> operators, like and, or, and not, cannot be overloaded, which means projects
> like numpy and SQLAlchemy instead have to (ab)use bitwise operator

> There was a proposal to allow overloading boolean operators in Pep-335 [2],
> but that PEP was rejected for a variety of very good reasons.

The key thing is, I think, the wish for a domain specific language. I
find this to be a wholesome wish. But I'd rather create a broad
solution, than something that works just for special cases. And if at
all possible, implement domain specific languages without extending
the syntax and semantics of the language.

This would benefit many existing users and projects now, without
having to wait for the introduction of a new version of Python, and
their project adopting that version.

It may help to build on PEP 465 -- A dedicated infix operator for
matrix multiplication
https://www.python.org/dev/peps/pep-0465/

This addition allows you (from the PEP) to write
>>> S = (H @ beta - r).T @ inv(H @ V @ H.T) @ (H @ beta - r)

You my want to extend the syntax and semantics so that
>>> S = (H @beta - r).T @ inv(H @ V @ H.T) @ (H @beta - r)
invokes double-under methods, whose name might be something like
__at_beta__

I'm impressed by
> https://en.wikipedia.org/wiki/Fluent_interface
> https://martinfowler.com/bliki/FluentInterface.html
and encourage work on tools for creating such in Python.

There is the problem of short-circuiting evaluation, as in the 'and'
and 'or' operators (and elsewhere in Python). This has to be a syntax
and semantics feature. It can't be controlled by the objects.

However, as Steve Dower pointed out last month, we can use lamda for
this purpose. I think it's easy to define a function OR such that the
following
> EXP_1 or EXP_2
>> OR(lambda: EXP_1, lambda:EXP_2)
do pretty the same thing (except refactoring the expressions into the lambdas).

In fact, I think OR has to be
>>> def OR(fn_1, fn_2):
... return fn_1() or fn_2()

I hope this help you solve the underlying problems, and have a better
time with Python.

-- 
Jonathan
___
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] With expressions

2018-08-03 Thread Todd
On Thu, Aug 2, 2018 at 5:35 AM, Ken Hilton  wrote:

> Hi, I don't know if someone has already suggested this before, but here
> goes:
>
> With expressions allow using the enter/exit semantics of the with
> statement inside an expression context. Examples:
>
> contents = f.read() with open('file') as f #the most obvious one
> multiplecontents = [f.read() with open(name) as f for name in names]
> #reading multiple files
>
> I don't know if it's worth making the "as NAME" part of the with mandatory
> in an expression - is this a valid use case?
>
> data = database.selectrows() with threadlock
>
> Where this would benefit: I think the major use case is `f.read() with
> open('file') as f`. Previous documentation has suggested
> `open('file').read()` and rely on garbage collection; as the disadvantages
> of that became obvious, it transitioned to a method that couldn't be done
> in an expression:
>
> with open('file') as f:
> contents = f.read()
>
> Therefore `f.read() with open('file') as f`, I think, would be much
> welcomed as the best way to read a file in an expression.
>
> For those wondering about the scope semantics of the "as NAME", I think
> they would be identical to the scope semantics of the "for" expression -
> i.e. these are legal:
>
> contents = f.read() with open('file') as f
> grid = [[i] * 4 for i in range(4)]
>
> But these are not:
>
> contents = f.read() with open('file') as f
> f.seek(0)
> grid = [[i] * 4 for i in range(4)]
> grid[i][i] = 4
>
> Is this a good idea? Are there some subtleties I've failed to explain?
> Please let me know.
>
> Sharing,
> Ken Hilton
>
>
If this is a common enough operation for you, it would be trivially easy to
just write a function that does this.  There is already a module on pypi
that has this function: read_and_close.
___
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] Revisiting dedicated overloadable boolean operators

2018-08-03 Thread Todd
Coming back to the previous discussion about a new set of overloadable
boolean operators [1], I have an idea for overloadable boolean operators
that I think might work.  The idea would be to define four new operators
that take two inputs and return a boolean result based on them.  This
behavior can be overridden in appropriate dunder methods.  These operators
would have similar precedence to existing logical operators.  The operators
would be:

bNOT - boolean "not"
bAND - boolean "and"
bOR - boolean "or"
bXOR - boolean "xor"

With corresponding dunder methods:

__bNOT__ and _rbNOT__ (or __r_bNOT__)
__bAND__ and _rbAND__ (or __r_bAND__)
__bOR__ and _rbOR__ (or __r_bOR__)
__bXOR__ and _rbXOR__ (or __r_bXOR__)

The basic idea is that the "b" is short for "boolean", and we change the
rest of the operator to upercase to avoid confusions with the existing
operators.  I think these operators would be preferably to the proposals so
far (see [1] again) for a few reasons:

  1. They are not easy to mistake with existing operators.  They are
clearly not similar to the existing bitwise operators like & or |, and
although they are clearly related to the "not", "and", and "or" I think
they are distinct enough that it should not be easy to confuse the two or
accidentally use one in place of the other.

   2. They are related to the operations they carry out, which is also an
advantage over the existing bitwise operators.

   3. The corresponding dunder methods (such as __bAND__ and _rbAND__) are
obvious and not easily confused with anything else.

   4. The unusual capitalization means they are not likely to be used much
in existing Python code.  It doesn't fall under any standard capitalization
scheme I am aware of.

   5. At least for english the capitalization means they are not easy to
confuse with existing words.  For example Band is a word, but it is not
likely to be capitalized as bAND.

As to why this is useful, the overall problem is that the current logical
operators, like and, or, and not, cannot be overloaded, which means
projects like numpy and SQLAlchemy instead have to (ab)use bitwise
operators to define their own boolean operations (for example elementwise
"and" in numpy arrays).  This has a variety of problems, such not having
appropriate precedence leading to precedence errors being common, and the
simple fact that this precludes them from using the bitwise operators for
bitwise operations.

There was a proposal to allow overloading boolean operators in Pep-335 [2],
but that PEP was rejected for a variety of very good reasons.  I think none
of those reasons (besides the conversation fizzling out) apply to my
proposal.

So the alternative proposal that has been floating around is to instead
define new operators specifically for this.  Although there seemed to be
some support for this in principle, the actually operators so far have not
met with much enthusiasm.  So far the main operators proposed so far seem
to be:

1. Double bitwise operators, such as && and ||.  These have the
disadvantage of looking like they should be a type of bitwise operator.

2. the existing operators, with some non-letter character at the front and
back, like ".and.".  These have the advantage that they are currently not
valid syntax in most cases, but I think are too similar to existing logical
operators, to easy to confuse, and it is not immediately obvious in what
way they should differ from existing operators.  They also mean different
things in other languages.

So I think my proposal addresses the main issues raised with existing
proposals, but has the downside that it requires new keywords.

Thoughts?

[1] https://mail.python.org/pipermail/python-ideas/2015-November/037207.html
[2] https://www.python.org/dev/peps/pep-0335/
___
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] With expressions

2018-08-03 Thread Chris Barker via Python-ideas
On Fri, Aug 3, 2018 at 3:49 AM, Robert Vanden Eynde 
wrote:

>
> When I say "functional programming", I speak about the paradigm used in
> language like Haskell. In language like those, all constructs are
> "expression-based".
>

sure -- but Python is explicitly NOT a functional language in that sense.
It does support some functional paradigms, but features are not added to
conform to the functional paradigm per-se, but because they are considered
useful features.

So one needs to defend a new proposal with arguments about how it makes
python programming better (by SOME definition of better) on its own merits.

-CHB


-- 

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR(206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115   (206) 526-6317   main reception

chris.bar...@noaa.gov
___
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] PEP 505: None-aware operators: operators ?= and ?? and OR

2018-08-03 Thread Eric Fahlgren
On Thu, Aug 2, 2018 at 10:06 PM Alexandre Brault 
wrote:

> I would make the opposite argument and claim that since when policy is
> None mangle_from_ is initialised to True and not None, None is likely not a
> potential value for policy.mangle_from_. Looking at
> Lib/email/_policybase.py where the abstract policy class in question is
> defined, policies default their mangle_from_ to False, which gives
> additional credence to the notion that policy.mangle_from_ is not meant to
> be None.
>

After looking at the code a bit more, I agree, we've uncovered a bug in the
stdlib and the null coalescing version actually fixes it.

So yes, *strictly speaking* the two chunks of code are not exactly the
> same. In practice, they'll act the same way given sensible inputs.
>

But!  We are not here to talk about bugs in the email package, this
discussion is about PEP 505, which means to me that the example is a bug in
the PEP.  In my view, the before and after examples should have identical
results, unless there is some very clear and thorough discussion
accompanying the example as to why they are different and more importantly,
why the "after" version is better or worse.  In this light, the example
certainly needs a lot of work.
___
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] With expressions

2018-08-03 Thread Robert Vanden Eynde
Thanks for answering each line. If someone wants "too long didn't read",
just check my code at the paragraph "readlines is a toy example, but maybe
the code would be more creative".

Le ven. 3 août 2018 à 03:07, Steven D'Aprano  a écrit :

> On Thu, Aug 02, 2018 at 03:13:25PM +0200, Robert Vanden Eynde wrote:
>
> > This brings the discussion of variable assignement in Expression.
> Functional
> > programming community seems to be more interested in python.
>
> I'm not sure what you mean there. Your English grammar is just slightly
> off, enough to make your meaning unclear,

sorry.
>

When I say "functional programming", I speak about the paradigm used in
language like Haskell. In language like those, all constructs are
"expression-based". I consider the code "result = 5 if condition else 2"
more "functional style" than "if condition: result = 5; else: result = 2".
Functional style focus on the result, uses expressions. Imperative focus on
the process, "we must do a condition, then we set the variable, else, we
set a variable to something else".


>
> > lines = (f.readlines() with open('hello') as f)
>
> readlines has the same problems as read, as I described earlier, and the
> same trivial three-line solution.
>
>
> > digit = (int('hello') except ValueError: 5)
>
> try...except exceptions have been proposed before and rejected.
>

I'm wondering why, that must have been the same reasons of not accepting
"with".

if condition:
something = x
else:
something = y

Can be refactored

something = x if condition else y

Or

something = (x if condition else
y)

But,

try:
something = x
except:
something = y

Can't?

The use cases seems similar.

One can use the first form, using more of a imperative programming, or the
second line, which is more "functional programming", more expressions
oriented.


>
> > value = (x+y**2 where x,y = (2,4))
>
> A "where" *statement* is interesting, but this is not a good example of
> it. The above is better written in the normal syntax:
>
> value = 2 + 4**2


That's the discussion we had on the list called "variable assignement in
expressions". What you did here is inlining the variables, technically it's
not possible if you're calling a function and using the variable more than
once.

So we're really comparing it to :

x,y = (2,4)
value = x+y**2

Or

x = 2
y = 4
value = x+y**2

Where the idea is to separate the steps of a computation, introducing
temporary variables with a meaningful name is useful (And as mentioned, if
a function is called and the variable reused, it's called once, but that's
not the main point).

In Haskell there is "value = (x = 2 in y = 4 in x+y**2)" or similar.

position = initial + speed * time
position_inch = distance / 2.54

Vs

position_inch = (initial + speed * time) / 2.54

The programmer chooses what's more clear given the context and the audience.

Or maybe he wants to emphasize that the code creates a position_inch
variable usable in the code after ?

Or both, he wants to explain how he computes position_inch using a
temporary variable but doesn't want the rest of the code depend o
"position" ?).

Yes the del is generally useless, more about  leaking below.


> no need to introduce temporary variables that exist only to obfuscate
> the code.
>
>
> > values = [x+y**2 for x in range(5) for y in range(7)]
> > values = [x+y**2 for x,y in product (range(5), range(7))]
> > y = 5 if condition else 2
>
> These already exist, because they are useful.
>

I see those as a refactoring of imperative programming style as well
(values = []; for ...: values.append(...))

>
> > y = (lambda x: x+2)(x=5)
>
> This is not a good example of the use of a lambda. Better:
>
> y = 5 + 2
>

Same thing as in the where syntax. However, some constructs are easier to
refactor as

def meaningfulname(x):
 return x+2

y = meaningfulname(5)


> Why bother writing a function with such a simple body if you are going
> to immediately call it on the spot? Unless the body is more complex, or
> you are going to call it elsewhere, or call it repeatedly, the lambda
> adds nothing.
>

Indeed, in complex expressions.

Or if I want to separate the steps of a computation.

position = initial + speed * time
position_inch = distance / 2.54


> Nobody denies that *some* statements are well-suited and useful as
> expressions. The question is whether "with" is one of those.
>

I'm just pointing out those constructs are very similar, it kind of makes
sense to compare them.

Of course I don't know about real world examples that would simplify a
code. But often as I'm a "expression first" guy

I write:

result = ...
# code using result and that doesn't care about the temporary variable it
uses.

Then I figure how to compute result, without polluting the namespace. Again
adding temporary variables before "result = ..." Is totally fine and that's
the way to go in imperative programming.


>
> > with open('hello') as f:
> > lines = f.readlines()
> > 

Re: [Python-ideas] PEP 505: None-aware operators: operators ?= and ?? and OR

2018-08-03 Thread Jonathan Fine
Hi Alexandre

Thank you for your post.

In PEP 505 the context for the example being discussed is:

> Some of these are shown below as examples before and after converting to use 
> the new operators.

You wrote:
> So yes, *strictly speaking* the two chunks of code are not exactly the same.

I see nothing in the context that indicates that given suitable
(Python) context, the before and after expressions give different
values. I assumed the before and after values were intended to be the
same.

By the way, I think that even without your *strictly speaking*, the
two chunks of code are not exactly the same (in that they can give
different values from identical inputs).

> In practice, they'll act the same way given sensible inputs.

For me, the truth or falsity of this statement requires more than the
peep-hole view of the code supplied by the PEP. Your argument for its
truth certainly looked beyond the PEP.

I think lack of clarity can mislead, and prevents the PEP performing
properly one of its key functions
===
https://www.python.org/dev/peps/pep-0001/#what-is-a-pep
The PEP should provide a concise technical specification of the
feature and a rationale for the feature [being proposed].
===
and so is a bug in the PEP. Fixing it will help the progress of the PEP.

Where to report the bug? Either to Steve Dower, or raise an issue on github.
https://www.python.org/dev/peps/pep-0001/#reporting-pep-bugs-or-submitting-pep-updates

Steve's already been emailed on this. We're waiting to hear back from him.

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