Re: [Python-ideas] Multi-core reference count garbage collection

2018-07-20 Thread Steven D'Aprano
On Fri, Jul 20, 2018 at 09:44:39PM +0100, Jonathan Fine wrote:
> Hi Steve
> 
> You wrote:
> > My understanding is that reference counting is both deterministic and
> > immediate. Shifting the reference counting into another thread so that
> > it becomes non-deterministic and potentially delayed doesn't sound like
> > an advantage to my naive understanding.
> 
> The choice is not as simple as that. Here's an example.
> 
> Suppose you and your friend want to sort a deck of cards. Here's an algorithm.

Jonathan, you keep avoiding my direct questions. What problem are you 
trying to solve?

Its okay if there is no immediate problem, that you're just exploring 
alternative garbage collection strategies. Or if you're trying to remove 
the GIL. Or you think that this will make print faster. (Probably not 
the last one *wink*)

And please don't patronise me -- I might not be an expert on garbage 
collection but I know that parallelising certain tasks can make them run 
faster. Your sorting example is irrelevant to understanding this 
reference counting proposal.

Help us understand where you are coming from in this discussion.


> * Divide the deck into two
> * Each person sorts their half deck
> * One of you does a merge of the two half decks
> 
> This algorithm is non-deterministic.

No in any important way it isn't. Although the sub-sorting steps may run 
in any order, the final merge doesn't occur until they are both 
completed. There are no race conditions where the merge happens before 
the sort, for example (unless your implementation is *really* bad). 
Which means from the perspective of the outsider the overall sort is 
deterministic: you start with an unsorted list, call sort, and when the 
sort() function returns, you have a sorted list. The non-determinism is 
no more important than the random partition in Quicksort.

But in the case of reference counting, I understand that multithreaded 
reference counting can suffer from race conditions when incrementing or 
decrementing:

http://flyingfrogblog.blogspot.com/2013/09/how-do-reference-counting-and-tracing.html

That would be a bad thing.

But as I said, my view of multi-threaded reference counting is very 
naive, and I'm no expert. I'm less interested in the technical details 
of how and whether it works as to *why* you are interested in trying it.

Hence my repeated requests for you to explain what problem(s) (if any) 
you are hoping to solve.


-- 
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/


[Python-ideas] if we were to ever shorten `A if A else B` (was: PEP 505: None-aware operators)

2018-07-20 Thread Brett Cannon
On Thu, 19 Jul 2018 at 14:29 Steve Dower  wrote:

> [SNIP]
>
> * "We could have 'else', we don't need '??'"
>
> This is the "a else 'default'" rather than "a ?? 'default'" proposal,
> which I do like the look of, but I think it will simultaneously mess
> with operator precedence and also force me to search for the 'if' that
> we actually need to be comparing "(a else 'default')" vs. "a ??
> 'default'"::
>
>  x = a if b else c else d
>  x = a if (b else c) else d
>  x = a if b else (c else d)
>

The searching for the 'if' also throws me with this proposal. I think
someone else proposed `A unless B` but I always prefer knowing upfront what
I'm working with, not later by having to read farther along.

Personally, if the `A?? B` is the part people like but hate the syntax then
my vote would go to `A otherwise B` since it's unambiguous, the case you
care about the state  of comes first, and it doesn't trip your brain up
looking for 'if'. :)
___
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] Multi-core reference count garbage collection

2018-07-20 Thread Chris Angelico
On Sat, Jul 21, 2018 at 6:44 AM, Jonathan Fine  wrote:
> Hi Steve
>
> You wrote:
>> My understanding is that reference counting is both deterministic and
>> immediate. Shifting the reference counting into another thread so that
>> it becomes non-deterministic and potentially delayed doesn't sound like
>> an advantage to my naive understanding.
>
> The choice is not as simple as that. Here's an example.
>
> Suppose you and your friend want to sort a deck of cards. Here's an algorithm.
>
> * Divide the deck into two
> * Each person sorts their half deck
> * One of you does a merge of the two half decks
>
> This algorithm is non-deterministic. But for a large deck it's quicker
> than any deterministic algorithm.

Divide the deck into "first half" and "second half". Then sort the
half decks using a stable algorithm. Finally, merge the decks,
favouring cards from the first half. Voila! You now have a fully
deterministic and stable sort.

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] Multi-core reference count garbage collection

2018-07-20 Thread Jonathan Fine
Hi Steve

You wrote:
> My understanding is that reference counting is both deterministic and
> immediate. Shifting the reference counting into another thread so that
> it becomes non-deterministic and potentially delayed doesn't sound like
> an advantage to my naive understanding.

The choice is not as simple as that. Here's an example.

Suppose you and your friend want to sort a deck of cards. Here's an algorithm.

* Divide the deck into two
* Each person sorts their half deck
* One of you does a merge of the two half decks

This algorithm is non-deterministic. But for a large deck it's quicker
than any deterministic algorithm.

I hope this helps.

-- 
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] PEP 505: None-aware operators

2018-07-20 Thread Steve Dower

On 20Jul2018 1119, Brendan Barnwell wrote:
In this situation I lean toward "explicit is 
better than implicit" --- if you want to compare against None, you 
should do so explicitly --- and "special cases aren't special enough to 
break the rules" --- that is, None is not special enough to warrant the 
creation of multiple new operators solely to compare things against this 
specific value.


"The rules" declare that None is special - it's the one and only value 
that represents "no value". So is giving it special meaning here 
breaking the rules or following them? (See also the ~50% of the PEP 
dedicated to this subject, and also consider proposing a non-special 
result for "??? if has_no_value(value) else value" in the 'True' case.)


Cheers,
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] Multi-core reference count garbage collection

2018-07-20 Thread Steven D'Aprano
On Fri, Jul 20, 2018 at 06:37:49PM +0100, Jonathan Fine wrote:
> Hi Steve
> 
> You wrote
> > Sorry Jonathan, can you please explain:
> >
> > - what problem you are solving with this?
> >
> > - and what's wrong with the existing garbage collector?
> 
> The problem I'm trying to solve doing multi-core reference counting
> garbage collection without a GIL. 

Perhaps I'm being a bit slow tonight, but that sounds like you're just 
repeating the solution: "multi-core reference counting garbage 
collection without a GIL". What problem does that solve?

If the quote-unquote "problem" is "get rid of the GIL", there are 
already at least two implementations of Python without a GIL (IronPython 
and Jython). Do they solve your problem?

If there's some other problem you are trying to solve, you should 
explain what it is.


> As far as I know, we're not yet able
> to do efficient multi-core garbage collection using Python.

Why would that be an advantage?

My understanding is that reference counting is both deterministic and 
immediate. Shifting the reference counting into another thread so that 
it becomes non-deterministic and potentially delayed doesn't sound like 
an advantage to my naive understanding.

But then I've never been one to think that threads are the only, or even 
the best, form of concurrency. I've never understood why so many people 
care about the GIL.

(Perhaps I'm jaundiced from dealing with too many people who honestly 
believe that the GIL is why their single-threaded code runs slowly. My 
favourite was the fellow I knew who was so convinced that Python was 
slow because of the GIL that he moved to Ruby, which also has a GIL and 
is slower than Python.)


-- 
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

2018-07-20 Thread Brendan Barnwell

On 2018-07-20 10:52, Steven D'Aprano wrote:

The problem is that `A else B` looks like it ought to be the same as
"else B" in if...else statements and the ternary if operator. That is,
"if the condition is false", and in this case there is nothing that
even hints that the condition is "A is None" rather than just A.


	Personally I consider this a problem with the whole null-coalescing 
idea.  Although it's true that the proposed null-coalescing operators 
don't look like existing syntax, it's also true that there's nothing 
about them that suggests to the uninitiated that they have anything to 
do with comparing to None.  In this situation I lean toward "explicit is 
better than implicit" --- if you want to compare against None, you 
should do so explicitly --- and "special cases aren't special enough to 
break the rules" --- that is, None is not special enough to warrant the 
creation of multiple new operators solely to compare things against this 
specific value.


--
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] Idea: Deferred Default Arguments?

2018-07-20 Thread Steven D'Aprano
On Fri, Jul 20, 2018 at 05:54:44PM +0200, Peter O'Connor wrote:
> On Fri, Jul 20, 2018 at 5:41 PM, Steven D'Aprano 
> wrote:
> >
> >
> > What makes you think that a built-in deferred feature won't have exactly
> > the same issues? Do you have an implementation that doesn't need to do
> > intraspection?
> 
> 
> I don't know about these low level things, but I assume it'd be implemented
> in C and wouldn't have the same cost as entering a new function in Python.
>  I imagine it just being a small modification of the mechanism that Python
> already uses to assign values to arguments when a function is called.  Is
> that not the case?

I don't know. That's why I'm asking why you think it wouldn't.


-- 
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] Multi-core reference count garbage collection

2018-07-20 Thread Jonathan Fine
Hi Steve

You wrote
> Sorry Jonathan, can you please explain:
>
> - what problem you are solving with this?
>
> - and what's wrong with the existing garbage collector?

The problem I'm trying to solve doing multi-core reference counting
garbage collection without a GIL. As far as I know, we're not yet able
to do efficient multi-core garbage collection using Python. If anyone
can tell me that's already been solved, I'd be delighted.

Stephan Houben's post tells us that buffered reference counting
appears in the major reference work
"The Garbage Collection Handbook: The Art of Automatic Memory Management",
by Richard Jones, Antony Hosking, Eliot Moss

So it might be a good idea.

Please let me know if you'd like further information.
-- 
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] PEP 505: None-aware operators

2018-07-20 Thread Steven D'Aprano
On Fri, Jul 20, 2018 at 12:03:47PM +1200, Greg Ewing wrote:
> Rhodri James wrote:
> >If anyone can think of a good word for "if it isn't None, otherwise", 
> >I'd be all for it :-)
> 
> I don't think there's any single Engish word that captures
> all of that, so we'd have to invent one.
> 
> Some suggestions:
> 
> inno (If Not None, Otherwise)
> 
> oft  (Or, Failing That)

How about pttpciseano?

("pity that the python community is so edgy about new operators")

*wink*

Remember that adding a new keyword risks breaking code that uses that 
keyword as a variable. Adding a new operator does not.


-- 
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

2018-07-20 Thread Steven D'Aprano
On Thu, Jul 19, 2018 at 10:33:21AM +0200, Antoine Pitrou wrote:

>  def insort_right(a, x, lo=0, hi=None):
>  # ...
>  hi = hi else len(a)

I read that as "hi, if it is truthy, else len(a)".

The advantage of ?? as None-aware operator is that it cannot possibly be 
misread as applying to arbitrary falsey objects:

- for those familiar with the equivalent from other languages, 
  the use of ?? to check for nil/null/None is familiar and obvious;

- for those who aren't, the ?? syntax avoids leading them to guess
  the wrong behaviour, as "else" would do.


P.S. I just had to delete 40+ screenfuls of irrelevant quoted text. Come 
on folks, please trim your posts! Don't blame your tools.



-- 
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

2018-07-20 Thread Steven D'Aprano
On Thu, Jul 19, 2018 at 08:57:50PM -0400, Michael Selik wrote:

> Try/except also looks decent.
> 
> try:
> x = foo['bar'][0]
> except TypeError:
> x = 'default'

Consider the case that foo['bar'] is supposed to return either a 
collection (something that can be indexed) or None. But due to a bug, it 
returns a float 1.234. Now the try...except will *wrongly* catch the 
exception from 1.234[0] and return the default.

The problem here is that the try...except block is NOT equivalent to the 
None-aware pattern:

obj = foo['bar']  # avoid time-of-check-to-time-of-use bugs
if obj is None:
x = 'default'
else:
   x = obj[0]

except in the special case that we can guarantee that foo['bar'] can 
only ever return a collection or None and will never, ever be buggy.



-- 
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

2018-07-20 Thread Mark E. Haase
On Thu, Jul 19, 2018 at 2:36 PM Brendan Barnwell 
wrote:

> People keep saying that this null-coalescing behavior is so common
> and
> useful, etc., but that hasn't been my experience at all.  In my
> experience, the desire to shortcut this kind of logic is more often a
> sign of corner-cutting and insufficiently specified data formats, and is
> likely to cause bugs later on.  Eventually it has to actually matter
> whether something is None or not, and these operators just kick that can
> down the road.  In terms of their abstract meaning, they are not
> remotely close to as common or useful as operators like & and |.
>
>
Brendan,

I am sure you didn't intend any offense, but the phrase "corner-cutting" is
pejorative, especially when stated as a generalization and not as a
critique of a specific example. I have used these operators in professional
projects in other languages (i.e. Dart), and I used them because they
seemed like the best tool for the job at hand, not because I was shirking
effort or short on time.

There are accepted PEPs that I don't find useful, e.g. PEP-465 (infix
matrix multiplication operator). It's not because it's a bad PEP; it's just
aimed at a type of programming that I don't do. That PEP had to address
some of the same criticisms that arise from PEP-505: there's no precedent
for that spelling, it's a small niche, and we can already to that in pure
python.[1] But I trust the Python numeric computing community in their
assertion that the @ syntax is valuable to their work.

In the same way that PEP-465 is valuable to a certain type of programming,
None-coalescing (as an abstract concept, not the concrete proposal in
PEP-505) is valuable to another type of programming. Python is often used a
glue language.[2] In my own experience, it's very common to request data
from one system, do some processing on it, and send it to another system.
For example, I might run a SQL query, convert the results to JSON, and
return it in an HTTP response. As a developer, I may not get to choose the
database schema. I may also not get to choose the JSON schema. My job is to
marshal data from one system to another. Consider the following example:

def get_user_json(user_id):
  user = user_table.find_by_id(user_id)
  user_dict = {
# Username is always non-null in database.
'username': user['username'],

# Creation datetime is always non-null in database; must be ISO-8601
string in JSON.
'created_at': user['created'].isoformat(),

# Signature can be null in database and null in JSON.
'signature': user['signature'],

# Background color can be null in database but must not be null in JSON.
'background_color': user.get('background_color', 'blue')

# Login datetime can be null in database if user has never logged in.
Must either
# be null or an ISO-8601 string in JSON.
'last_logged_in_at': user['last_logged_in_at'].isoformat() if
user['last_login'] is not None else None,

# Remaining fields omitted for brevity
  }
  return json.dumps(user_dict)

Python makes a lot of the desired behavior concise to write. For example,
the DBAPI (PEP-249) states that null and None are interchanged when reading
and writing from the database. The stdlib json module also converts between
None and null. This makes a lot of the mappings trivial to express in
Python. But it gets tricky for cases like "last_logged_in_at", where a null
is permitted by the business rules I've been given, but if it's non-null
then I need to call a method on it. As written above, it is over 100
characters long. With safe-navigation operators, it could be made to fit
the line length without loss of clarity:

'last_logged_in_at': user['last_logged_in_at'] ?. isoformat(),

Many people in this thread prefer to write it as a block:

  if user['last_logged_in_at'] is None:
user_dict['last_logged_in_at'] = None
  else:
user_dict['last_logged_in_at'] = user['last_logged_in_at'].isoformat()

I agree that the block is readable, but only because my made-up function is
very short. In real-world glue code, you may have dozens of mappings, and
multiplying by 4 leads to functions that have so many lines of code that
readability is significantly worse, and that highly repetitive code
inevitably leads to typos.

It's not just databases and web services. An early draft of PEP-505
contains additional examples of where None arises in glue code.[4] And it's
not even just glue code: the standard library itself contains around 500
examples of none-coalescing or safe-navigation![5] I certainly don't think
anybody here will claim that stdlib authors have cut hundreds of corners.



[1] https://www.python.org/dev/peps/pep-0465/
[2] https://www.python.org/doc/essays/omg-darpa-mcc-position/
[3] https://www.python.org/dev/peps/pep-0249/
[4]
https://github.com/python/peps/blob/c5270848fe4481947ee951c2a415824b4dcd8a4f/pep-0505.txt#L63
[5] https://www.python.org/dev/peps/pep-0505/#examples

Re: [Python-ideas] PEP 505: None-aware operators

2018-07-20 Thread Steve Dower
Just for fun, I decided to go through some recently written code by some 
genuine Python experts (without their permission...) to see what changes would 
be worth taking. So I went to the sources of our github bots.

Honestly, I only found three places that were worth changing (though I'm now 
kind of leaning towards ?[] eating LookupError, since that seems much more 
useful when traversing the result of json.loads()...). I'm also not holding up 
the third one as the strongest example :)


>From 
>https://github.com/python/miss-islington/blob/master/miss_islington/status_change.py:

async def check_status(event, gh, *args, **kwargs):
if (
event.data["commit"].get("committer")
and event.data["commit"]["committer"]["login"] == "miss-islington"
):
sha = event.data["sha"]
await check_ci_status_and_approval(gh, sha, leave_comment=True)

After:

async def check_status(event, gh, *args, **kwargs):
if event.data["commit"].get("committer")?["login"] == "miss-islington":
sha = event.data["sha"]
await check_ci_status_and_approval(gh, sha, leave_comment=True)


>From https://github.com/python/bedevere/blob/master/bedevere/__main__.py:

try:
print('GH requests remaining:', gh.rate_limit.remaining)
except AttributeError:
pass

Assuming you want to continue hiding the message when no value is available:
if (remaining := gh.rate_limit?.remaining) is not None:
print('GH requests remaining:', remaining)

Assuming you want the message printed anyway:
print(f'GH requests remaining: {gh.rate_limit?.remaining ?? "N/A"}')


>From https://github.com/python/bedevere/blob/master/bedevere/news.py (this is 
>the one I'm including for completeness, not because it's the most compelling 
>example I've ever seen):

async def check_news(gh, pull_request, filenames=None):
if not filenames:
filenames = await util.filenames_for_PR(gh, pull_request)

After:
async def check_news(gh, pull_request, filenames=None):
filenames ??= await util.filenames_for_PR(gh, pull_request)


On 19Jul2018 , Steven D'Aprano wrote:
> In other words, we ought to be comparing the expressiveness of
> 
>  process(spam ?? something)
> 
> versus:
> 
> process(something if spam is None else spam)

Agreed, though to make it a more favourable comparison I'd replace "spam" with 
"spam()?.eggs" and put it in a class/module definition where you don't want 
temporary names leaking ;)

Cheers,
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

2018-07-20 Thread Steven D'Aprano
On Thu, Jul 19, 2018 at 12:57:01PM +0100, Jonathan Fine wrote:

> > Possibly this is exactly the wrong time to propose the next big syntax
> > change, since we currently have nobody to declare on it, but since we're
> > likely to argue for a while anyway it probably can't hurt [...]
> 
> Perhaps "argue" is not the right word here. It sounds too much for or
> against. And it has implications of being heated and angry.

You're new here, aren't you?

*wink*


-- 
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] Multi-core reference count garbage collection

2018-07-20 Thread Steven D'Aprano
On Thu, Jul 19, 2018 at 07:33:13AM +0100, Jonathan Fine wrote:
> Hi
> 
> Based on other people's work (including in particular talks by Larry
> Hastings) and my own thinking, I've come up with a scheme for multi-core
> reference count garbage collection.

Sorry Jonathan, can you please explain:

- what problem you are solving with this?

- and what's wrong with the existing garbage collector?



-- 
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] The future of Python parallelism. The GIL. Subinterpreters. Actors.

2018-07-20 Thread Nick Coghlan
On 18 July 2018 at 05:35, Eric Snow  wrote:
> In order to make all this work the missing piece is a mechanism by
> which the decref (#3) happens under the original interpreter.  At the
> moment Emily Morehouse and I are pursuing an approach that extends the
> existing ceval "pending call" machinery currently used for handling
> signals (see Py_AddPendingCall).  The new [*private*] API would work
> the same way but on a per-interpreter basis rather than just the main
> interpreter.  This would allow one interpreter to queue up a decref to
> happen later under another interpreter.
>
> FWIW, this ability to decref an object under a different interpreter
> is a blocker right now for a number of things, including supporting
> buffers in PEP 554 channels.

Aw, I guess the original idea of just doing an active interpreter
context switch in the current thread around the shared object decref
operation didn't work out? That's a shame.

I'd be curious as to the technical details of what actually failed in
that approach, as I would have expected it to at least work, even if
the performance might not have been wonderful. (Although thinking
about it further now given a per-interpreter locking model, I suspect
there could be some wonderful opportunities for cross-interpreter
deadlocks that we didn't consider in our initial design sketch...)

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] Idea: Deferred Default Arguments?

2018-07-20 Thread Peter O'Connor
On Fri, Jul 20, 2018 at 5:41 PM, Steven D'Aprano 
wrote:
>
>
> What makes you think that a built-in deferred feature won't have exactly
> the same issues? Do you have an implementation that doesn't need to do
> intraspection?


I don't know about these low level things, but I assume it'd be implemented
in C and wouldn't have the same cost as entering a new function in Python.
 I imagine it just being a small modification of the mechanism that Python
already uses to assign values to arguments when a function is called.  Is
that not the case?



On Fri, Jul 20, 2018 at 5:41 PM, Steven D'Aprano 
wrote:

> On Fri, Jul 20, 2018 at 04:43:56PM +0200, Peter O'Connor wrote:
>
> > I still think it would be nice to have this as a built-in python feature,
> > for a few reasons:
> > - When using non-differable functions (say in other codebases), we have
> to
> > do a bunch of "func = deferrable_args(func)" at the top of the module (or
> > we can just do them at runtime, but then we're doing inspection every
> time,
> > which is probably slow).
> > - It adds a layer to the call stack for every deferrable function you're
> in.
> > - To avoid annoying errors where you've defined an arg as deferred but
> > forgot to wrap the function in question.
>
> What makes you think that a built-in deferred feature won't have exactly
> the same issues? Do you have an implementation that doesn't need to do
> intraspection?
>
>
> --
> 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/
>
___
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] Idea: Deferred Default Arguments?

2018-07-20 Thread Nick Coghlan
On 20 July 2018 at 22:45, Steven D'Aprano  wrote:
> Perhaps you mean duplicate, or repeat, or copy. But surely they're not
> redefined -- then they would have different values. Being able to
> redefine the defaults in a wrapper function is a feature.
>
> Putting aside the terminology, I think this is a minor annoyance: DRY
> violations when setting default values.

FWIW, I tend to handle this problem the same way I handle other DRY
problems with magic constants: give the default value a name and
either export it directly, or export an API for retrieving it.

If that results in name sprawl ("But now I have 15 defaults to
export!"), then I take it as a hint that I may not be modeling my data
correctly, and am missing a class definition or two somewhere.

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] Idea: Deferred Default Arguments?

2018-07-20 Thread Steven D'Aprano
On Fri, Jul 20, 2018 at 04:43:56PM +0200, Peter O'Connor wrote:

> I still think it would be nice to have this as a built-in python feature,
> for a few reasons:
> - When using non-differable functions (say in other codebases), we have to
> do a bunch of "func = deferrable_args(func)" at the top of the module (or
> we can just do them at runtime, but then we're doing inspection every time,
> which is probably slow).
> - It adds a layer to the call stack for every deferrable function you're in.
> - To avoid annoying errors where you've defined an arg as deferred but
> forgot to wrap the function in question.

What makes you think that a built-in deferred feature won't have exactly 
the same issues? Do you have an implementation that doesn't need to do 
intraspection?


-- 
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] Idea: Deferred Default Arguments?

2018-07-20 Thread Jonathan Fine
Hi Peter

You wrote:
On Fri, Jul 20, 2018 at 3:43 PM, Peter O'Connor
 wrote:
> Ah, right, the fix_it(fcn) is a nice idea.  It might also be a good idea, if
> we're making an external library anyway, to have a "deferred" object to
> avoid overloading "None" (which may mean something else than "differ
> argument").  I implemented the decorator here
https://github.com/petered/peters_example_code/blob/master/peters_example_code/deferral.py

Oh, well done Peter. Thank you. About 15 lines of code, and the same
again for comments. And all for the good of the community (and
scratching your own itch).

I think we've now got pretty much the right basic ideas for solving
your original problem. And your original problem is fairly widespread.

So what, do you think, are the next steps?

-- 
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] Idea: Deferred Default Arguments?

2018-07-20 Thread Peter O'Connor
Ah, right, the fix_it(fcn) is a nice idea.  It might also be a good idea,
if we're making an external library anyway, to have a "deferred" object to
avoid overloading "None" (which may mean something else than "differ
argument").  I implemented the decorator here
,
and it can be used as:

from deferral import deferrable_args, deferred

@deferrable_args
def subfunction_1(a=2, b=3, c=4):
return a+b*c

@deferrable_args
def subfunction_2(d=5, e=6, f=7):
return d*e+f

def main_function(a=deferred, b=deferred, c=deferred, d=deferred,
e=deferred, f=deferred):
return subfunction_1(a=a, b=b, c=c) + subfunction_2(d=d, e=e, f=f)

assert main_function() == (2+3*4)+(5*6+7)
assert main_function(a=8) == (8+3*4)+(5*6+7)

I still think it would be nice to have this as a built-in python feature,
for a few reasons:
- When using non-differable functions (say in other codebases), we have to
do a bunch of "func = deferrable_args(func)" at the top of the module (or
we can just do them at runtime, but then we're doing inspection every time,
which is probably slow).
- It adds a layer to the call stack for every deferrable function you're in.
- To avoid annoying errors where you've defined an arg as deferred but
forgot to wrap the function in question.


On Fri, Jul 20, 2018 at 3:39 PM, Jonathan Fine  wrote:

> Hi Peter
>
> You make the very good point, that
>
> > subfunction_1 may be written by someone totally different from the
> author of
> > main_function, and may even be in a different codebase.  For the author
> of
> > subfunction_1, it makes no sense to use the "None" approach instead of
> > python's normal default mechanism (since all arguments here are
> immutables).
>
> Good point. To rephrase, what should we do if we want to use a third
> party or legacy function, which begins
> ===
> def fn(a=1, b=2, c=3):
>   # function body
> ===
>
> We can solve this by defining a function decorator. Suppose we have a
> function fix_it, whose argument and return value are both functions.
> The basic specification of fix_it is that
> ---
> fixed_fn = fix_it(fn)
> ---
> is in practice equivalent to
> ---
> def fixed_fn(a=None, b=None, c=None):
> if a is None: a = 1
> if b is None: b = 2
> if c is None: c = 3
> # function body for fn
> # or if you prefer
> return fn(a, b, c)
> ---
>
> An aside. We can code fix_it by using
> https://docs.python.org/3/library/inspect.html
> ===
> >>> import inspect
> >>> def fn(a=1, b=2, c=3): pass
> ...
> >>> str(inspect.signature(fn))
> '(a=1, b=2, c=3)'
> ===
>
> You could also use with new code, like so:
> ---
> @fix_it
> def fn(a=1, b=2, c=3):
>   # function body
> ---
>
> I think this helps solve your problem. Is there, Peter, anything else
> that would be left to do (except, of course, write the fix_it
> function).
>
> Thank you again for your problem and comments.
>
> --
> 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] Idea: Deferred Default Arguments?

2018-07-20 Thread Brice Parent

It might be stupid, but how about solving this problem using the following:

from . import other_func, SomeClass

def my_func(a=other_func.defaults.a, b=other_func.defaults.b, 
c=SomeClass.some_method.defaults.c):

    ...

or
def my_func(a=None, b=None, c=None):  # or use some sentinel value 
instead of None

    if a is None:
    a = other_func.defaults.a
    if b is None:
    b = other_func.defaults.b
    if c is None:
    c = SomeClass.some_method.defaults.c
    ...

or even
def my_func(a=None, b=None, c=None):
    if a is None:
    a = default(other_func, "a")
    if b is None:
    b = default(other_func, "b")
    if c is None:
    c = default(SomeClass.some_method, "c")
 ...

I used *.defaults.* but it might be something else, as well as the 
function I named 'default' which might be anything else.


I prefer the first, as it's both short and easy to read, but I'm not 
sure about the implications about such a thing. And it probably has 
already been proposed for other use cases.
The second and third versions are more verbose, but probably easier to 
implement, specially the third which should already be doable using 
something like


import inspect

def default(function, argument):
    return inspect.signature(function).parameters[argument].default.
___
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-07-20 Thread Rhodri James

On 20/07/18 14:06, Michel Desmoulin wrote:

Proposal a __very__ dumbed down "try" expression


 variable = try Expression as not sentinel [else default]


I like this approach.  I think it should play nice with the ternary if, 
though I haven't actually checked the grammar.


My only doubt is how much value there is to having a sentinel other than 
"None".


--
Rhodri James *-* Kynesim Ltd
___
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-07-20 Thread Grégory Lielens
I like it much better than the operator version, if I understand correctly, 
it's like a watcher for special value, that monitor the stack.
Danger is that it monitor the whole stack, so that final result is dependent on 
how much you decompose your algorithm into nested fiction calls: all return 
values will be monitored, and only return values...
But if you refactor a big function into nested functions, and happen to return 
the special value in the new subfunctions, it will have side effects, that can 
not be known within the context: it expose internals that used to be hidden, 
deliberately so...___
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] Idea: Deferred Default Arguments?

2018-07-20 Thread Jonathan Fine
Hi Peter

You make the very good point, that

> subfunction_1 may be written by someone totally different from the author of
> main_function, and may even be in a different codebase.  For the author of
> subfunction_1, it makes no sense to use the "None" approach instead of
> python's normal default mechanism (since all arguments here are immutables).

Good point. To rephrase, what should we do if we want to use a third
party or legacy function, which begins
===
def fn(a=1, b=2, c=3):
  # function body
===

We can solve this by defining a function decorator. Suppose we have a
function fix_it, whose argument and return value are both functions.
The basic specification of fix_it is that
---
fixed_fn = fix_it(fn)
---
is in practice equivalent to
---
def fixed_fn(a=None, b=None, c=None):
if a is None: a = 1
if b is None: b = 2
if c is None: c = 3
# function body for fn
# or if you prefer
return fn(a, b, c)
---

An aside. We can code fix_it by using
https://docs.python.org/3/library/inspect.html
===
>>> import inspect
>>> def fn(a=1, b=2, c=3): pass
...
>>> str(inspect.signature(fn))
'(a=1, b=2, c=3)'
===

You could also use with new code, like so:
---
@fix_it
def fn(a=1, b=2, c=3):
  # function body
---

I think this helps solve your problem. Is there, Peter, anything else
that would be left to do (except, of course, write the fix_it
function).

Thank you again for your problem and comments.

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

2018-07-20 Thread Michel Desmoulin
Proposal a __very__ dumbed down "try" expression


variable = try Expression as not sentinel [else default]

The semantic is:

1 - try the expression. If any call (from a normal method, or a
__dunder__ one) returns the sentinel, we shortcircuit.

2 - if we shortcircuit, the variable will be set do the default value.
If no default is provided, the variable is set to the sentinel.

3 - if we don't shortcircuit, the returned value is the one from the
expression.


Example
==


value = try foo.bar[0] as not None

If anything returns None, we shortcircuit and value will end up being
None. Otherwise value contains the result of foo.bar[0].

value = try foo.bar[0] as not True

If anything returns True, we shortcircuit and value will end being True.
Otherwise value contains the result of foo.bar[0].

value = try foo.bar[0] as not None else "foo"

If anything returns None, we shortcircuit and value will end up being
'foo'. Otherwise value contains the result of foo.bar[0].


value = try foo.bar[0] as not True else "foo"

If anything returns True, we shortcircuit and value will end up being
'foo'. Otherwise value contains the result of foo.bar[0].


This as several benefits:
=

- Does not introduce new keywords or operators

- Read pretty much as ordinary Python

- Allow for inline try, as suggested before several times on
python-idea, but restrict it to a very narrow subset of what it can do.
This will end the debate about inline try/except, while sill providing a
sane subsets of use cases it would have provided.

- more flexible than ? as it allows to choose what to choose the
sentinel and the default value instead of just None.

- the expression is untouched. It's surrounded by the rest, so it still
reads as the expression would without try / as.

- avoding "except", exception names and ":" make sure we don't confuse
this try expression with the regular try/except statements. try would
then be a very restricted version of it, like lambda is for def.


If you don't like these keywords
===

We can opt for something different:

value = try Expression as not sentinel [or default]
value = try Expression if not sentinel [else default]
value = try Expression with not sentinel [else default]

The proposal is more about the structure try (stuff), guard against a
sentinel, and optionally return a default value.

Besides, I don't know what the grammar would allow.
___
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] Idea: Deferred Default Arguments?

2018-07-20 Thread Steven D'Aprano
On Fri, Jul 20, 2018 at 11:03:12AM +0200, Peter O'Connor wrote:
> Often when programming I run into a situation where it would be nice to
> have "deferred defaults".  Here is an example of what I mean:
> 
> def subfunction_1(a=2, b=3, c=4):
> return a+b*c
> 
> def subfunction_2(d=5, e=6, f=7):
> return d*e+f
> 
> def main_function(a=2, b=3, c=4, d=5, e=6, f=7):
> return subfunction_1(a=a, b=b, c=c) + subfunction_2(d=d, e=e, f=f)
> 
> Here you can see that I had to redefine the defaults in the main_function.

Perhaps you mean duplicate, or repeat, or copy. But surely they're not 
redefined -- then they would have different values. Being able to 
redefine the defaults in a wrapper function is a feature.

Putting aside the terminology, I think this is a minor annoyance: DRY 
violations when setting default values.


> In larger codebases, I find bugs often arise because defaults are defined
> in multiple places, and somebody changes them in a lower-level function but
> fails to realize that they are still defined differently in a higher
> function.

Changing function defaults in production code without a period of 
deprecation and warnings is a no-no. Default values are a part of the 
function API, and changing the public API of a function without warning 
is asking for trouble.

But during development, there are no such constraints (your only users 
are your development team) and it is a real nuisance keeping defaults in 
sync across multiple functions and/or classes.

I've raised this issue in the past:

https://mail.python.org/pipermail/python-list/2016-September/714546.html

and I still don't have a great solution for it.


> The only way I currently see to achieve this is not very nice at all, and
> completely obfuscates the signature of the function:
[...]

There are lots of other ways to solve this. None of which are great.


> What I was thinking was a "deferred" builtin that would just allow a lower
> function to define the value (and raise an exception if anyone tried to use
> it before it was defined)
[...]
> I assume this has been discussed before somewhere, but couldn't find
> anything on it, so please feel free to point me towards any previous
> discussion on the topic.

https://mail.python.org/pipermail/python-ideas/2011-July/010678.html


-- 
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

2018-07-20 Thread Judah Levy
One of the big problems with most of the proposed spellings is that
question marks to a learner will feel like truthiness tests and not None
tests. I would propose adding a new default statement for the most useful
part of this PEP, the ?= assignment

currently:
if x is None:
 x = blah

with `?=`:
x ?= blah

with defalult:
default x: blah

This a) makes it obvious even to an amateur python-reader that x will only
be changed if it does not yet exist, and b) has no similarity to the
truthiness checks involved with the standard meaning of `?` as the ternary
operator in many other languages.

On Fri, Jul 20, 2018 at 8:30 AM Chris Angelico  wrote:

> On Fri, Jul 20, 2018 at 10:24 PM, Paul Moore  wrote:
> > On 20 July 2018 at 13:16, Chris Angelico  wrote:
> >> On Fri, Jul 20, 2018 at 10:14 PM, Rhodri James 
> wrote:
> >>> I go with SF fandom's traditional :-) definition: "somebody did it
> once."
> >>> If it's been done more than once, it's an honoured tradition.
> >>
> >> But if Shakespeare did it, it's just the way the language is.
> >>
> >> I think Fortran is the programming world's Shakespeare.
> >
> > Or maybe COBOL:
> >
> > "And lo from yonder file a record doth appear"...
>
> Hah! But I was thinking of all those uber-obvious features like "a +
> b" meaning addition. Those symbols, and the infix style, aren't
> "traditions" - they're the baseline that we measure everything else
> against. Also, the use of decimal digits to represent literals; if you
> *don't* use decimal, you're unusual. (Which makes the Shakespeare
> Programming Language [1] an ironic example, since it doesn't use
> decimal digits for numeric literals.)
>
> ChrisA
> [1] http://shakespearelang.sourceforge.net/report/shakespeare/
> ___
> 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] Idea: Deferred Default Arguments?

2018-07-20 Thread Peter O'Connor
On Fri, Jul 20, 2018 at 1:30 PM, Jonathan Fine  wrote:
>
>
> I sort of think we've now got a reasonable answer for Peter's problem.
> What do you think, Peter? And Brice, are you happy with my
> interpretation of your deferred keyword?


I think the problem with the "None" approach (second pattern) is that it
forces the writer of the subfunction to write their defaults in a more
awkward way in anticipation of other functions which defer their defaults
to it.  Translated to the original example, it would become:

def subfunction_1(a=None, b=None, c=None):
if a is None: a=1
if b is None: b=2
if c is None: c=3
return a+b*c

def subfunction_2(d=None, e=None, f=None):
if d is None: d=5
if e is None: e=6
if f is None: f=7
return d*e+f

def main_function(a=None, b=None, c=None, d=None, e=None, f=None):
return subfunction_1(a=a, b=b, c=c) + subfunction_2(d=d, e=e, f=f)

subfunction_1 may be written by someone totally different from the author
of main_function, and may even be in a different codebase.  For the author
of subfunction_1, it makes no sense to use the "None" approach instead of
python's normal default mechanism (since all arguments here are
immutables).



On Fri, Jul 20, 2018 at 1:30 PM, Jonathan Fine  wrote:

> Excellent contributions. I'm going to try to (partially) consolidate
> what we've got.
>
> REVIEW
> ===
> I'll start by reviewing the situation regarding default arguments.
> There are two basic patterns for default arguments.
>
> The first is
> ---
> def fn(a=EXP):
> # body of function
> ---
>
> The second is
> ---
> def fn(a=None):
> if a is None:
> a = EXP
> # body of function
> ---
>
> Here, EXP is any Python expression. A fairly gotcha is to use a list,
> or some other mutable object, as EXP. This happens when you write
> ---
> def fn(a=[]):
># body of function
> ---
> because then EXP = '[]' which will be evaluated just once, and every
> call fn() will be using the same list! To avoid this you should use
> the second pattern. I think there may be an example of this in the
> standard Python tutorial.
>
> (An aside. You probably need the second pattern if you EXP is, say,
> ([], []). Although technically immutable, this value has mutable
> members. And can't be hashed, or use as a dictionary key or element of
> a set.)
>
> WHEN TO USE None
> =
>
> If you want something mutable as the 'default argument' you have to
> use the second pattern. If your default argument is immutable then you
> can if you wish use the second pattern.
>
> But you don't have to use the second pattern. When you use the second
> pattern, the expression f(None) means 'create for me the default
> argument' (and raise an exception if there isn't one).
>
> Think about it. For immutable EXP, fn() is the same, whether fn is
> coded using the first pattern or the second. But the value of fn(None)
> depends very much on which pattern is used to code fn().
>
> So here's the big conclusion (drum roll):
> ===
> fn should be coded using the second pattern if we wish to pass None as
> a sentinel argument to fn.
> ===
>
> SUMMARY
> =
> My suggestion was to use the second pattern to solve Peter O'Connor's
> original problem. It can be done now, but is a bit verbose, and looses
> useful information in help(fn).
>
> Brice Parent's suggestion was to introduce a keyword deferred, like so
> ---
> def fn(deferred a=EXP):
> # body of function
> ---
> which I like to think of as a syntactic shorthand for the second pattern.
>
> I sort of think we've now got a reasonable answer for Peter's problem.
> What do you think, Peter? And Brice, are you happy with my
> interpretation of your deferred keyword?
>
> ---
> 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] PEP 505: None-aware operators

2018-07-20 Thread Chris Angelico
On Fri, Jul 20, 2018 at 10:24 PM, Paul Moore  wrote:
> On 20 July 2018 at 13:16, Chris Angelico  wrote:
>> On Fri, Jul 20, 2018 at 10:14 PM, Rhodri James  wrote:
>>> I go with SF fandom's traditional :-) definition: "somebody did it once."
>>> If it's been done more than once, it's an honoured tradition.
>>
>> But if Shakespeare did it, it's just the way the language is.
>>
>> I think Fortran is the programming world's Shakespeare.
>
> Or maybe COBOL:
>
> "And lo from yonder file a record doth appear"...

Hah! But I was thinking of all those uber-obvious features like "a +
b" meaning addition. Those symbols, and the infix style, aren't
"traditions" - they're the baseline that we measure everything else
against. Also, the use of decimal digits to represent literals; if you
*don't* use decimal, you're unusual. (Which makes the Shakespeare
Programming Language [1] an ironic example, since it doesn't use
decimal digits for numeric literals.)

ChrisA
[1] http://shakespearelang.sourceforge.net/report/shakespeare/
___
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

2018-07-20 Thread Paul Moore
On 20 July 2018 at 13:16, Chris Angelico  wrote:
> On Fri, Jul 20, 2018 at 10:14 PM, Rhodri James  wrote:
>> I go with SF fandom's traditional :-) definition: "somebody did it once."
>> If it's been done more than once, it's an honoured tradition.
>
> But if Shakespeare did it, it's just the way the language is.
>
> I think Fortran is the programming world's Shakespeare.

Or maybe COBOL:

"And lo from yonder file a record doth appear"...

Paul
___
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

2018-07-20 Thread Chris Angelico
On Fri, Jul 20, 2018 at 10:14 PM, Rhodri James  wrote:
> I go with SF fandom's traditional :-) definition: "somebody did it once."
> If it's been done more than once, it's an honoured tradition.

But if Shakespeare did it, it's just the way the language is.

I think Fortran is the programming world's Shakespeare.

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] PEP 505: None-aware operators

2018-07-20 Thread Rhodri James

On 20/07/18 01:30, Greg Ewing wrote:

Rhodri James wrote:

On 19/07/18 07:06, Greg Ewing wrote:


There's no such tradition for the new
operators being proposed.


There is, actually, it's just not a long one.  C# has had null-aware 
operators for a while, for example.


THere's a precedent, yes, but I wouldn't call it a tradition.
A substantial period of time is part of the definition of the
word.

Wikipedia:

"A tradition is a belief or behavior passed down within a group
or society with symbolic meaning or special significance with
origins in the past."

Merriam-Webster:

"the handing down of information, beliefs, or customs from one
generation to another."

I don't think C# has been around long enought to span multiple
generations of programmers.


I go with SF fandom's traditional :-) definition: "somebody did it 
once."  If it's been done more than once, it's an honoured tradition.


--
Rhodri James *-* Kynesim Ltd
___
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] Idea: Deferred Default Arguments?

2018-07-20 Thread Jonathan Fine
Excellent contributions. I'm going to try to (partially) consolidate
what we've got.

REVIEW
===
I'll start by reviewing the situation regarding default arguments.
There are two basic patterns for default arguments.

The first is
---
def fn(a=EXP):
# body of function
---

The second is
---
def fn(a=None):
if a is None:
a = EXP
# body of function
---

Here, EXP is any Python expression. A fairly gotcha is to use a list,
or some other mutable object, as EXP. This happens when you write
---
def fn(a=[]):
   # body of function
---
because then EXP = '[]' which will be evaluated just once, and every
call fn() will be using the same list! To avoid this you should use
the second pattern. I think there may be an example of this in the
standard Python tutorial.

(An aside. You probably need the second pattern if you EXP is, say,
([], []). Although technically immutable, this value has mutable
members. And can't be hashed, or use as a dictionary key or element of
a set.)

WHEN TO USE None
=

If you want something mutable as the 'default argument' you have to
use the second pattern. If your default argument is immutable then you
can if you wish use the second pattern.

But you don't have to use the second pattern. When you use the second
pattern, the expression f(None) means 'create for me the default
argument' (and raise an exception if there isn't one).

Think about it. For immutable EXP, fn() is the same, whether fn is
coded using the first pattern or the second. But the value of fn(None)
depends very much on which pattern is used to code fn().

So here's the big conclusion (drum roll):
===
fn should be coded using the second pattern if we wish to pass None as
a sentinel argument to fn.
===

SUMMARY
=
My suggestion was to use the second pattern to solve Peter O'Connor's
original problem. It can be done now, but is a bit verbose, and looses
useful information in help(fn).

Brice Parent's suggestion was to introduce a keyword deferred, like so
---
def fn(deferred a=EXP):
# body of function
---
which I like to think of as a syntactic shorthand for the second pattern.

I sort of think we've now got a reasonable answer for Peter's problem.
What do you think, Peter? And Brice, are you happy with my
interpretation of your deferred keyword?

---
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] Idea: Deferred Default Arguments?

2018-07-20 Thread Grégory Lielens
A crazy idea, didn't think much about it yet:

def subfunc(c,a=0,b=1):
  Blabla

def function(c,d=3, from args(subfunc) import a,b):
  Blabla
  return anotherfunc(a+b+c+d,subfunc(c,a,b))
  

___
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] Multi-core reference count garbage collection

2018-07-20 Thread Jonathan Fine
In an earlier post, I defined BUFFERED multi-core reference count
garbage collection. The basic idea is that each worker process store
in buffers the need to do an INCR and DECR on the reference count for
a piece of memory with a given ID. There is then a garbage collection
process that does the right thing.
https://mail.python.org/pipermail/python-ideas/2018-July/052054.html

An important aside. I'm very grateful for all the comments, which are
very helpful, made to the first part. It's really nice to know that
mine is not a new idea, and about some of the features and quirks (or
optimisations if you like) in the CPython GC system.

Here, I describe the easy part of doing the right thing. And make a
start on the hard part.

EASY PART
The GC process is responsible for keeping the running totals of the
reference counts. It does this by processing the INCR and DECR buffers
that are passed to it. (Once these buffers are processed they can, of
course, be passed back to the system for reuse.)

Where to store the totals of the reference counts is a design
decision. The main constraint is that ONLY the GC process should be
changing these counts. The buffering is roughly equivalent to the
changes made by the worker processes being queued for the GC process
to perform. But buffering also allows the 'queue' to be reordered.
This can substantially reduce the number of system calls required to
coordinate the various processes. And the amount of time a process is
locked out from running.

We could, following CPython, store the reference counts as a system
field in the object being stored. This is probably most economical,
regarding use of memory. However, if the GC process has associated to
it some high-speed memory of its own, it will be quicker if possible
to store the reference count totals in that high-speed memory. And so
storing the counts separately will probably make better use of
process-specific high speed memory.

Either way the algorithm is easy.

HARD PART
The do-nothing garbage collection avoids the hard part, which is to
know when a piece of memory can be reclaimed. With single-core
reference counting, this would be when the count becomes zero. But is
the same true for multi-core garbage collection?

The answer is both YES and NO.

First for the NO. They buffered scheme described here is asychronous,
and in particular reordering. So there might be INCR operations
pending, that would take the global reference count from zero to one.
(And it can go the other way. The object might be inaccessible, but
not all of its DECR operations are processed yet.)

So, and this is important, we cannot rely on the reference count
totals owned by the GC process to tell is if there is or is not a
reference to the object in the worker threads.

Now for the YES. The operations for the processes can be put in a
definite temporal order (i.e. serialized). When this is done then
(assuming every process is behaving as it should) the following
statement is true:

Suppose at some point T in time the quantity
* the GC process reference count for the object with some ID
* plus any pending INCR operations in worker process buffers
* minus any similarly pending DECR operations
is zero. Call this the adjusted reference count.

If that is true at T, then after time T the object with the given ID
is inaccessible to the worker processes. And so the piece of memory
can be reclaimed.

We can, of course, compute the adjusted reference count by pausing all
working threads. In other words, provide and use a global interpreter
lock.

The remainder of the hard part is to get hold of adjusted reference
counts, without having to lock the worker threads.

As before, remarks and comments very welcome. The previous ones were
much appreciated.

-- 
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] Performance improvements via static typing

2018-07-20 Thread Stefan Behnel
Michael Hall schrieb am 19.07.2018 um 15:51:
> While I am aware of projects like Cython and mypy, it seems to make sense
> for CPython to allow optional enforcement of type hints, with compiler
> optimizations related to it to be used. While this would not receive the
> same level of performance benefits as using ctypes directly, there do
> appear to be various gains available here.

Well, first of all, a C level type check at runtime is quite fast compared
to a byte code dispatch with stack argument handling, and can be done
regardless of any type hints. There are various code patterns that would
suggest a certain type ("x.append()" probably appends to a list, "x.get()"
will likely be a dict lookup, etc.), and that can be optimised for without
static type declarations and even without any type hints.

Then, the mere fact that user code says "a: List" does not help in any way.
Even "a: list" would not help, because any behaviour of that "list" might
have been overridden by the list subtype that the function eventually receives.

The same applies to "x: float". Here, in order to gain speed, the compiler
would have to generate two separate code paths through the entire function,
one for C double computations, and one for Python float subtypes. And then
exponentiate that by the number of other typed arguments that may or may
not contain subtypes. Quite some overhead.

It's unclear if the gain would have any reasonable relation to the effort
in the end. Sure, type hints could be used as a bare trigger for certain
optimistic optimisations, but then, it's cheap enough to always apply these
optimisations regardless, via a C type check.

Stefan

___
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] Idea: Deferred Default Arguments?

2018-07-20 Thread Grégory Lielens
Excellent point! I am not fully convinced by the syntax yet, but having 
proposed something is already very valuable and  I do not have a better 
proposal. As I had to defer defaults countless times, and each times 
grumped about it, I hope something will come out of 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/


Re: [Python-ideas] Idea: Deferred Default Arguments?

2018-07-20 Thread Chris Angelico
On Fri, Jul 20, 2018 at 7:03 PM, Peter O'Connor
 wrote:
> Often when programming I run into a situation where it would be nice to have
> "deferred defaults".  Here is an example of what I mean:
>
> def subfunction_1(a=2, b=3, c=4):
> return a+b*c
>
> def subfunction_2(d=5, e=6, f=7):
> return d*e+f
>
> def main_function(a=2, b=3, c=4, d=5, e=6, f=7):
> return subfunction_1(a=a, b=b, c=c) + subfunction_2(d=d, e=e, f=f)
>
> Here you can see that I had to redefine the defaults in the main_function.
> In larger codebases, I find bugs often arise because defaults are defined in
> multiple places, and somebody changes them in a lower-level function but
> fails to realize that they are still defined differently in a higher
> function.
>
> The only way I currently see to achieve this is not very nice at all, and
> completely obfuscates the signature of the function:
>
> def main_function(**kwargs):
> return subfunction_1(**{k: v for k, v in kwargs.items() if k in
> ['a', 'b', 'c']})
>+ subfunction_2(**{k: v for k, v in kwargs.items() if k in
> ['d', 'e', 'f']})

Hmm. This might be something where a bit of a helper could, well,
help. Is this a pattern that you make use of a lot? Suppose you write
your main function like this:

@combines(subfunction_1, subfunction_2)
def main_function(sf1, sf2):
return subfunction_1(**sf1) + subfunction_2(**sf2)

or even like this:

@precombine
def main_function(subfunction_1, subfunction_2):
return subfunction_1 + subfunction_2

The decorator could then generate a new function, with a proper
signature (available to help()), that hides the messy details of
filtering kwargs - and in the case of precombine, actually calls the
function as well. (Obviously you can't use this if you might want to
call a subfunction conditionally.)

Another option would be to have all your subfunctions absorb and
ignore all unexpected arguments.

def subfunction_1(a=2, b=3, c=4, **_):
return a+b*c

def subfunction_2(d=5, e=6, f=7, **_):
return d*e+f

def main_function(**kw):
return subfunction_1(**kw) + subfunction_2(**kw)

This doesn't help with the signature, but it's an easy thing to do.
You'd have to document your parameters separately from your functions;
appropriate for something like the subprocess module (where a bunch of
functions basically pipe their args straight into Popen), not
appropriate for a lot of other places.

On the plus side, both of these ideas work with existing Python
versions, so you wouldn't have to wait for 3.8 or 3.9 :)

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] PEP 505: None-aware operators

2018-07-20 Thread Grégory Lielens


On Friday, July 20, 2018 at 11:12:26 AM UTC+2, Chris Angelico wrote:
>
> On Fri, Jul 20, 2018 at 5:10 PM, Grégory Lielens
> > wrote:
>
> Excuse me, that wasn't my words you quoted. Watch your citations please :)
>
> ChrisA
>

Yes, sorry, it was Brendan Barnwell. And I can not edit my previous 
post:-/ 
___
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] Idea: Deferred Default Arguments?

2018-07-20 Thread Jonathan Fine
Hi Peter

Interesting problem. We can already get something like your proposed
solution by using None instead of deferred.

You have to start with
def subfunction_1(a=None, b=None, c=None):
if a is None: a = 2
# similarly for b and c.
return a+b*c

You will loose the default values being shown when you do help(subfunction).

There's another thread on PEP 505, active right now, that would allow
you to write something like
a = a OR 2
to provide the default values.
https://mail.python.org/pipermail/python-ideas/2018-July/052071.html

I hope this helps. Please let us know if that might work for you.

-- 
Jonathan

On Fri, Jul 20, 2018 at 10:03 AM, Peter O'Connor
 wrote:
> Often when programming I run into a situation where it would be nice to have
> "deferred defaults".  Here is an example of what I mean:
>
> def subfunction_1(a=2, b=3, c=4):
> return a+b*c
>
> def subfunction_2(d=5, e=6, f=7):
> return d*e+f
>
> def main_function(a=2, b=3, c=4, d=5, e=6, f=7):
> return subfunction_1(a=a, b=b, c=c) + subfunction_2(d=d, e=e, f=f)
>
> Here you can see that I had to redefine the defaults in the main_function.
> In larger codebases, I find bugs often arise because defaults are defined in
> multiple places, and somebody changes them in a lower-level function but
> fails to realize that they are still defined differently in a higher
> function.
>
> The only way I currently see to achieve this is not very nice at all, and
> completely obfuscates the signature of the function:
>
> def main_function(**kwargs):
> return subfunction_1(**{k: v for k, v in kwargs.items() if k in
> ['a', 'b', 'c']})
>+ subfunction_2(**{k: v for k, v in kwargs.items() if k in
> ['d', 'e', 'f']})
>
> What I was thinking was a "deferred" builtin that would just allow a lower
> function to define the value (and raise an exception if anyone tried to use
> it before it was defined)
>
> def main_function(a=deferred, b=deferred, c=deferred, d=deferred,
> e=deferred, f=deferred):
> return subfunction_1(a=a, b=b, c=c) + subfunction_2(d=d, e=e, f=f)
>
> I assume this has been discussed before somewhere, but couldn't find
> anything on it, so please feel free to point me towards any previous
> discussion on the topic.
>
> ___
> 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] PEP 505: None-aware operators

2018-07-20 Thread Chris Angelico
On Fri, Jul 20, 2018 at 5:10 PM, Grégory Lielens
 wrote:
>
>
>> On 2018-07-19 02:11, Chris Angelico wrote:
>
>
>>
>> -snip-
>> As far as I can see, these null-coalescing operators would break
>> that
>> model.  The PEP doesn't seem to provide for a "real" magic method
>> allowing users to override the actual behavior of the method.  (You can
>> only override __has_value__ to hook into it, but not define by fiat what
>> A ?? B does, as you can with other operators.)  And I think the reason
>> for this is that the operator itself is too specific, much more specific
>> in semantics than other operators.  (I had similar doubts about adding
>> the matrix-multiplication operator @.)
>>
>> People keep saying that this null-coalescing behavior is so common
>> and
>> useful, etc., but that hasn't been my experience at all.  In my
>> experience, the desire to shortcut this kind of logic is more often a
>> sign of corner-cutting and insufficiently specified data formats, and is
>> likely to cause bugs later on.  Eventually it has to actually matter
>> whether something is None or not, and these operators just kick that can
>> down the road.  In terms of their abstract meaning, they are not
>> remotely close to as common or useful as operators like & and |.
>
>
> Fully agree with you on this

Excuse me, that wasn't my words you quoted. Watch your citations please :)

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] Adding Python interpreter info to "pip install"

2018-07-20 Thread Chris Angelico
On Fri, Jul 20, 2018 at 5:56 PM, Thomas Jollans  wrote:
> On 20/07/18 05:10, Al Sweigart wrote:
>> Sorry, I meant "pip list", rather than "pip info".
>>
>> I thought about the fact that "pip --version" provides this info, but 1)
>> it provides the location of pip, not the python interpreter it installs
>> packages for and 2) it would be an additional step for the
>> question-asker to go through after posting the output of "pip install".
>
> If the extra line of output was something like
>
> This is $(pip --version)
>
> that would be more consistent, and provide enough information.

Yes, that's what I was saying. It would remove the extra step, at the
price of one line of spam every 'pip install'. Is that worth it? Not
sure, but at least it's not a whole lot of complexity.

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] Idea: Deferred Default Arguments?

2018-07-20 Thread Peter O'Connor
Often when programming I run into a situation where it would be nice to
have "deferred defaults".  Here is an example of what I mean:

def subfunction_1(a=2, b=3, c=4):
return a+b*c

def subfunction_2(d=5, e=6, f=7):
return d*e+f

def main_function(a=2, b=3, c=4, d=5, e=6, f=7):
return subfunction_1(a=a, b=b, c=c) + subfunction_2(d=d, e=e, f=f)

Here you can see that I had to redefine the defaults in the main_function.
In larger codebases, I find bugs often arise because defaults are defined
in multiple places, and somebody changes them in a lower-level function but
fails to realize that they are still defined differently in a higher
function.

The only way I currently see to achieve this is not very nice at all, and
completely obfuscates the signature of the function:

def main_function(**kwargs):
return subfunction_1(**{k: v for k, v in kwargs.items() if k in
['a', 'b', 'c']})
   + subfunction_2(**{k: v for k, v in kwargs.items() if k in
['d', 'e', 'f']})

What I was thinking was a "deferred" builtin that would just allow a lower
function to define the value (and raise an exception if anyone tried to use
it before it was defined)

def main_function(a=deferred, b=deferred, c=deferred, d=deferred,
e=deferred, f=deferred):
return subfunction_1(a=a, b=b, c=c) + subfunction_2(d=d, e=e, f=f)

I assume this has been discussed before somewhere, but couldn't find
anything on it, so please feel free to point me towards any previous
discussion on the topic.
___
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] Adding Python interpreter info to "pip install"

2018-07-20 Thread Thomas Jollans
On 20/07/18 05:10, Al Sweigart wrote:
> Sorry, I meant "pip list", rather than "pip info".
> 
> I thought about the fact that "pip --version" provides this info, but 1)
> it provides the location of pip, not the python interpreter it installs
> packages for and 2) it would be an additional step for the
> question-asker to go through after posting the output of "pip install".

If the extra line of output was something like

This is $(pip --version)

that would be more consistent, and provide enough information.

> 
> It would be nice to display output that the question-asker can compare
> directly with the output of "which python". And I'd like to shorten the
> potential amount of back-and-forth before the helper can get the
> information they need.
> 
> Additionally, while they could always just run "python -m pip install
> spam" but most tutorials tell them to run pip directly, so I still see
> the need for this.
> 
> 
> On Thu, Jul 19, 2018 at 5:50 PM, Chris Angelico  > wrote:
> 
> On Fri, Jul 20, 2018 at 10:45 AM, Al Sweigart  > wrote:
> > The goal of this idea is to make it easier to find out when
> someone has
> > installed packages for the wrong python installation. I'm coming
> across
> > quite a few StackOverflow posts and emails where beginners are
> using pip to
> > install a package, but then finding they can't import it because
> they have
> > multiple python installations and used the wrong pip.
> >
> > For example, this guy has this problem:
> >
> 
> https://stackoverflow.com/questions/37662012/which-pip-is-with-which-python
> 
> 
> >
> > I'd propose adding a simple line to the output of "pip install"
> that changes
> > this:
> >
> > user@user:~$ pip3 install pyperclip
> > Collecting pyperclip
> > Installing collected packages: pyperclip
> > Successfully installed pyperclip-1.6.2
> >
> > ...to something like this:
> >
> > user@user:~$ pip3 install pyperclip
> > Running pip for /usr/bin/python3
> > Collecting pyperclip
> > Installing collected packages: pyperclip
> > Successfully installed pyperclip-1.6.2
> >
> > This way, when they copy/paste their output to StackOverflow, it'll be
> > somewhat more obvious to their helper that they used pip for the wrong
> > python installation.
> >
> > This info would also be useful for the output of "pip info", but
> that would
> > break scripts that reads that output.
> >
> > Any thoughts?
> 
> You can get some very useful information from "pip3 --version". As
> well as pip's own version, it tells you the version of Python that
> it's running under, AND what directory it's being run from. If you
> want to request that similar info be added to other commands, I would
> strongly recommend lifting the exact format of --version and using
> that.
> 
> (I'm not sure what "pip info" is, btw. My pip doesn't seem to have
> that.)
> 
> 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/
> 

___
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] Adding Python interpreter info to "pip install"

2018-07-20 Thread Terry Reedy

On 7/20/2018 12:21 AM, Nathaniel Smith wrote:

On Thu, Jul 19, 2018 at 5:45 PM, Al Sweigart  wrote:

The goal of this idea is to make it easier to find out when someone has
installed packages for the wrong python installation. I'm coming across
quite a few StackOverflow posts and emails where beginners are using pip to
install a package, but then finding they can't import it because they have
multiple python installations and used the wrong pip.


So have I.  The solution is to run pip the way the core developers 
recommend, which is to explicitly run the version of python you want pip 
to install to.  On Windows,


py -x.y -m pip install somemod

I have given that answer on SO and just gave it on python-list, thereby 
solving the users 2.7 versus 3.7 problem.



This sounds like a great idea to me, but pip is developer separately
from python itself, and I don't think the pip maintainers monitor
python-ideas. I'd suggest filing a feature request on the pip tracker:

https://github.com/pypa/pip/issues/new?template=feature-request.md


Definitely.


--
Terry Jan Reedy

___
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

2018-07-20 Thread Grégory Lielens


On 2018-07-19 02:11, Chris Angelico wrote: 

 

> -snip-
> As far as I can see, these null-coalescing operators would break 
> that 
> model.  The PEP doesn't seem to provide for a "real" magic method 
> allowing users to override the actual behavior of the method.  (You can 
> only override __has_value__ to hook into it, but not define by fiat what 
> A ?? B does, as you can with other operators.)  And I think the reason 
> for this is that the operator itself is too specific, much more specific 
> in semantics than other operators.  (I had similar doubts about adding 
> the matrix-multiplication operator @.) 
>
> People keep saying that this null-coalescing behavior is so common 
> and 
> useful, etc., but that hasn't been my experience at all.  In my 
> experience, the desire to shortcut this kind of logic is more often a 
> sign of corner-cutting and insufficiently specified data formats, and is 
> likely to cause bugs later on.  Eventually it has to actually matter 
> whether something is None or not, and these operators just kick that can 
> down the road.  In terms of their abstract meaning, they are not 
> remotely close to as common or useful as operators like & and |. 
>

Fully agree with you on this, so -1 on those new operators. I like 
operators (I was behind one of the early proposals for matmul operator 
(even proposed a bunch of others, for orthogonality purpose: 
element-wise/object-as-a-whole is a dichotomy that can happen for other 
things that multiplication), but they need to benefit from operators 
specifics: precendence order, tradition meaning direct translation of 
formula/recipies already written with a similar notation, and be generic 
enough to allow productive use of overloading (instead of confusing use).

Matmul have this (with possible exception for overloading, but they are 
quite a few other mathematical entities where you want to have more than 1 
multiplication, beside matrices).

Those new operators, not so much, the only benefit is more compact notation 
of something that is already quite compact (A if A is not None else B) and 
very explicit (it reads like pseudocode, which is a huge strengh of python).
?? and associates is much more cryptic, force you to think much harder 
about precedence, just to be slightly more compact. Granted, compact 
notation can be valuable, but usually if you want to couple multiple such 
things (like you often do with matmul), and precedence rules allows you to 
do it elegantly combine multiple operator with infix notation (again matmul 
is present in formulas that have scalar mul, + and -) . 
Do we do this with None-coalescence? I don't think so, not often anyway...
Do we want to do this more with None-coalescence? Not me, certainly not: 
When I None coalesce, I want it to be as clear and atomic as possible 
because it's a corner case.

so strong -1...
___
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-07-20 Thread Aliaksei Yaletski
Hi

I'm new to that list, hope, that my idea will be helpfull.

  hi = hi OR len(a)
> ---
> where (A OR B) returns A if A is not None, otherwise it returns B.
>

Probably, we can introduce syntactic sugar for "if not equal" comparison?
Not only for "is not None" check, but for comparison with any expression.

Something like:

x = foo if 'value': bar

equal to :

x = foo if foo != 'value' else bar

so, expression:

x = foo if foo is not None else bar

become:

x = foo if None: bar

That syntax does not use new keywords or operators, looks pythonic and
simplify most common "is not None" expression.

-- 
Regards,

Aliaksei Yaletski.

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