[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread David Mertz
On Sun, Apr 19, 2020 at 11:40 PM Steven D'Aprano 
wrote:

def M(*vals):
# ... magic stuff ...
return dct


> py> alpha = 'something'
> py> M(alpha)
> Traceback (most recent call last):
>   File "", line 1, in 
>   File "", line 5, in M
> TypeError: 'NoneType' object is not subscriptable
>

Yep.  It works in IPython and it works in a script, but I didn't try the
plain Python shell.  I'm using Python 3.8, but I imagine the same problem
exists between IPython and Python shell in other versions.

etc, and how many hours of debugging it will take to get it to work.
>

Some positive but finite number of hours to deal with the edge cases.  For
the discussion, can we just stipulate some future L() that is a better
version of M()?

(base) 551-bin % python auto-dict.py
{'alpha': 'something'}
args: ()
kws: {'alpha': 'something', 'beta': 'else', 'gamma': 'again'}
(base) 552-bin % cat auto-dict.py
from magic import M

alpha = 'something'
beta = 'else'
gamma = 'again'

print(M(alpha))

def show(*args, **kws):
print('args:', args)
print('kws:', kws)

show(**M(alpha, beta, gamma))



> I'm also looking at that call to eval and wondering if someone smarter
> than me can use that to trick me into evaluating something I don't like.
>

Yes... in L() is should be `ast.literal_eval()`.

Maybe I'll write a better L() in the next day or two.  But I really AM NOT
pushing for anyone to use such a thing, just to consider the conceptual
space it occupies vs. having new syntax.

-- 
Keeping medicines from the bloodstreams of the sick; food
from the bellies of the hungry; books from the hands of the
uneducated; technology from the underdeveloped; and putting
advocates of freedom in prisons.  Intellectual property is
to the 21st century what the slave trade was to the 16th.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/ZG2PADDC7QQMZ72HI6KCOP2EEP3PLUGI/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Keyword arguments self-assignment

2020-04-19 Thread Greg Ewing

On 20/04/20 2:57 pm, Steven D'Aprano wrote:


 process_files(delete=obsolete_files, archive=irrelevent_files)
 process_files(archive=obsolete_files, delete=irrelevent_files)


That's not a use case for the proposed feature. The
intended use cases are more like

def fancy_file_processing(delete, archive):
extra_processing_for_deleted(delete)
other_processing_for_archived(archive)
basic_file_processing(delete=delete, archive=archive)

Since fancy_file_processing is a wrapper around
basic_file_processing, it makes sense to name the
corresponding arguments the same way.

Now maybe someone will misuse it in a situation that
doesn't involve wrapping and warp their local names
to fit. But any language feature can be abused. The
blame for abuse lies with the abuser, not the feature.

--
Greg
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/AYHBUUMENXA76O3JEUOYUU7OOCQNJBDE/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread David Mertz
On Sun, Apr 19, 2020, 10:16 PM Steven D'Aprano  wrote:

> > Understand that I'm not really advocating for a magic function like
> Q().  I
> > think it's important to keep in mind that anyone COULD create such a
> thing
> > for 20 years, and very few people bothered to.
>
> You don't really know how many people are using such a thing in their
> private code.


I've read quite a bit of open source code and code at places I've worked. I
think "very few" is a safe claim. It's more than "none."

At least with a language feature, the hack is official, and it's the
> responsibility of the language devs to keep it working, at which point it
> ceases to be a hack and becomes just part of the language.
>

I see you're point here. Q(), or the improved M(), are certainly not more
magic than namedtuple, or typing, or dataclass, or @total_ordering. But
those are parts of the official language, and we can trust that edge cases
and bugs will be well addressed in every release.

Attrs is pretty magic, and also widely used... But after a while, that
motivated dataclass, which is largely similar, to be added to the official
language. Popular packages like Django or Pandas have a fair amount of
magic in them, but that magic is specific to working with the objects they
create.

I do recognize that Q() or M() or Alex's dict_of() break the rules of what
functions are supposed to do. Python is pass-by-reference not pass-by-name,
and these deliberately muck with that.

So you've moved me a bit towards the side of wanting a new DICT DISPLAY.
Something completely limited to calling form feels artificially limited for
no reason. And the addition of f"{foo=}" is very similar magic for similar
reasons.

So constructing a dictionary like these are only -0 for me (maybe -0.1):

dct = {**, foo, bar, baz}
dct = **{foo, bar, baz}
dct = {foo=, bar=, baz=}

With any of those corresponding in function calls:

fun(**kws, foo, bar, baz)
fun(**, foo, bar, baz)
fun(**kws, **{foo, bar, baz})
fun(**kws, foo=, bar=, baz=)

The form with the dangling equal signs still strikes me as horribly ugly,
but I see the closer analogy with the f-string magic.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/37IZURMADBWSAHAWROFRD7S5ISQA5NU4/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread Steven D'Aprano
On Sun, Apr 19, 2020 at 10:50:55PM +0200, Alex Hall wrote:

> I think I'm uniquely qualified to say with certainty that this is 100% not
> true. A basic version like Q("email firstname lastname") like you wrote is
> indeed easy to do correctly, but I've said why I wouldn't want to use it
> and I think others would agree. The real thing, `Q(email, firstname,
> lastname, cellphone)`, is very hard to do correctly.

Thank you Alex for the very informative response.


-- 
Steven
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/HEPD6KXJFLYHFFJ3X6T544NDKR4BIIG2/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread Chris Angelico
On Mon, Apr 20, 2020 at 1:39 PM Steven D'Aprano  wrote:
> I'm also looking at that call to eval and wondering if someone smarter
> than me can use that to trick me into evaluating something I don't like.
>

I'm very confused by that call. It appears to be evaluating a bare
name in a specific context... which should give the value of that
variable. But, isn't that going to be... one of the parameters to the
function? Hasn't it already been parsed out?

It'd be a lot more interesting if people post MacroPy proposals rather
than these bizarre source-code-parsing things that are fundamentally
broken in so many ways.

ChrisA
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/DFX4MPVAFX37UBW3HKIVNOQ2TNZFKCJW/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread Steven D'Aprano
On Sun, Apr 19, 2020 at 04:14:51PM -0400, David Mertz wrote:

> Per your wish, Eric, the glorious successor of Q() ... named M():
> 
> >>> def M(*vals):
> ... import sys
> ... import inspect
> ... caller = sys._getframe(1)
> ... call = inspect.stack()[1].code_context[0]
> ... _, call = call.split('M(')
> ... call = call.strip()[:-1]
> ... names = [name.strip() for name in call.split(',')]
> ... dct = {}
> ... for name in names:
> ... dct[name] = eval(name, globals(), caller.f_locals)
> ... return dct

When I try it I get this:

py> alpha = 'something'
py> M(alpha)
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 5, in M
TypeError: 'NoneType' object is not subscriptable

Tried and failed in both 3.5 and 3.8, so I'm not sure what version of 
Python you are using where it works, or under what conditions.

Your example M(x, y, z) fails with the same error.

Since this is fundamentally broken and doesn't work for me, I can't test 
it, but I wonder how well it will cope for things like:

func(arg, FunctionM(x, y), M(z))

M(x, M(y)['y'])

func(arg, M(
x, 
y,
),
 z)

etc, and how many hours of debugging it will take to get it to work.

I'm also looking at that call to eval and wondering if someone smarter 
than me can use that to trick me into evaluating something I don't like.


-- 
Steven
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/NEPHZXR53V3BSH7ZYMXQN5N3VSLMFPMQ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: collections.UpdateDict, collections.InsertDict, collections.InsertOrIgnoreDict

2020-04-19 Thread Kyle Stanley
Steven D'Aprano wrote:
> Do nothing?

> I don't have to suggest a better idea, since its not me proposing a
> change. I don't think any change is needed. It is up to you to firstly
> justify that a change is needed, and only then justify a specific
> response to that need.

[snip]

> If you personally would use them, I'm happy for you. But unless there is
> likely to be either moderate or widespread use among the community, or
> at least some uses in the stdlib, those functions belong in your own
> personal toolbox, not the stdlib.

+1 to doing nothing here, at least based on the current proposal.

Soni, I would strongly recommend spending some more time to come up
with specific, concrete use cases for feature proposals in the future
(or in this thread). Preferably with some detailed "before and after"
examples using *non-trivial* real world code, and some explanations as
to why you think it should be included in the standard library instead
of just something implemented locally or in a 3rd party package.

Without doing the above, it's very likely going to end up being an
infinite loop of seeing the same repeated counter-arguments on your
proposals. If those points can't be answered and defended, it's highly
unlikely the proposal would be accepted in the first place; regardless
of how interesting the ideas may seem.

On Thu, Apr 16, 2020 at 10:37 PM Steven D'Aprano  wrote:
>
> On Thu, Apr 16, 2020 at 01:11:46PM -0300, Soni L. wrote:
>
> > we can't break setdefault (particularly for tuple keys), do you have a
> > better idea?
>
> Do nothing?
>
> I don't have to suggest a better idea, since its not me proposing a
> change. I don't think any change is needed. It is up to you to firstly
> justify that a change is needed, and only then justify a specific
> response to that need.
>
> An anecdote... when I first discovered Python back in 1.5 days, and
> specifically the dict.update method, practically the first thing I did
> was wonder why update replaced existing keys. What if I wanted it to
> keep the existing key, or raise an exception? So I immediately wrote a
> pair of functions to do both those things.
>
> It's been close to 20 years now and so long as I can remember, I have
> never, not once, used either of those variants I don't even know
> whether I even still have them (not that it would be hard to recreate
> them).
>
> If you personally would use them, I'm happy for you. But unless there is
> likely to be either moderate or widespread use among the community, or
> at least some uses in the stdlib, those functions belong in your own
> personal toolbox, not the stdlib.
>
>
> --
> Steven
> ___
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at 
> https://mail.python.org/archives/list/python-ideas@python.org/message/SPY2DRKUZ3LUX56AYOA2QKEMT4KAZLNP/
> Code of Conduct: http://python.org/psf/codeofconduct/
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/RVBUMROZZIDR3DCMDPBG2RTGUSQKSQPN/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Keyword arguments self-assignment

2020-04-19 Thread Steven D'Aprano
On Sun, Apr 19, 2020 at 06:06:50PM +0200, Alex Hall wrote:
> >
> > >>  function(*, dunder, invert, private, meta, ignorecase)
> > >>
> > >
> > >
> > > No reader will ever have to think about the difference. They will simply
> > > see the second version and know which arguments are being passed.
> >
> > I seem to be immune to this magical knowledge.
> >
> 
> Sorry, what? How is there any doubt that the arguments being passed are
> dunder, invert, private, meta, and ignorecase? They're right there.

That tells us the meaning of the arguments in the *caller's* context. 

It doesn't tell us the meaning of the arguments in the *callee's* 
context, which is critical information. There is a huge difference 
between these:

process_files(delete=obsolete_files, archive=irrelevent_files)
process_files(archive=obsolete_files, delete=irrelevent_files)

even though both calls receive the same arguments, so it is critical to 
know the callee's context, i.e. the parameters those arguments get 
bound to.


> Now, which parameters those arguments are bound to is less obvious, but:
> 
> 
>1. When you read the function call, you're thinking about the arguments,
>not the parameters. You can see which information goes into the function,
>and the first question you should ask yourself is 'is that the right
>information?'.

And the only way to know that is to think about the parameters. I trust 
that you will agree that we should care about the difference between 
(let's say):

pow(8, 2)  # 64
pow(2, 8)  # 256

and that it's critical to match the arguments to the parameters in the 
right order or you will get the wrong answer.

I can't tell you how many times I messed up list.insert() calls because 
I got the arguments in the wrong order.

So for the reader who doesn't know what this star argument `*` does, it 
is not enough for them to say "Oh that's fine then, we're passing the 
right arguments, it doesn't matter what parameters they get matched to". 
The parameters are absolutely critical.


-- 
Steven
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/BRMV32XDSC2UFVCCCYTRULE53FWMAUKO/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread Steven D'Aprano
On Sun, Apr 19, 2020 at 02:34:35PM -0400, Eric V. Smith wrote:

> I'd be only -0.5 on any proposal from this thread (as opposed to -1000 
> as I am now) if it were more general purpose than just function calls. 
[...]
> My point is: We already have a way to pass the items in a dictionary as 
> keyword args: let's not invent another one. Instead, let's focus on a 
> general purpose way of creating a dictionary that meets the requirements 
> of being able to be passed as keyword args. That way we'd me making the 
> language more expressive beyond just function calls.

Good point. Maybe we should step back and look at the bigger picture and 
ask what we're fundamentally trying to do. And that, it seems to me, is 
solve a problem that beginners often ask:

"How do I get the name of a variable?"

The answer is, in general, you can't. But what if we could?

In low-level languages like C and Pascal, there are usually "address of" 
unary operators. Would it solve the problem if we had a "name of" 
operator? Let's call it `$` just for something to call it.

{'name': name}
{$name: name}

Well, that saves us a mere one character. In a function call:

func(arg, $name=name)

and that *costs* us an unnecessary character, if it even worked, which 
it probably wouldn't.

What if it expanded to name=value?

{'name': name}
{$name}

Hmm, that's terser, but now it looks like a set. If we changed the 
dollar sign to a colon, we come back to Andrew's suggestion.

Maybe I've stepped back too far. Sometimes we can overgeneralise. But 
either way, it's good food for thought.


-- 
Steven
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/YDIZCVDZS4BTBI2PUWG2RBYUKTC4MSI3/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread Greg Ewing

On 20/04/20 1:36 pm, Steven D'Aprano wrote:

 **{alpha, beta, gamma}
 **{:alpha, :beta, :gamma}
 *, alpha, beta, gamma
 **, alpha, beta, gamma
 alpha=, beta=, gamma=

although I may have missed some. I'm not seeing "much" difference in
complexity between them, syntax-wise.


To my eyes, the last three are a lot simpler than the first
two. Not just in the number of characters, but in the amount
of mental processing required to figure out what's going on.

Can we at least try to avoid unnecessary hyperbole in describing ideas
we don't like?


I don't think it's hyperbole, I really mean what I said.
And I have reasons for disliking some of those, which I
think I have explained.

--
Greg
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/7XTU2VDAQV4KTZVACP7YY22Q54BY7UOP/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread Steven D'Aprano
On Sun, Apr 19, 2020 at 11:58:01AM -0400, David Mertz wrote:

> Understand that I'm not really advocating for a magic function like Q().  I
> think it's important to keep in mind that anyone COULD create such a thing
> for 20 years, and very few people bothered to.

You don't really know how many people are using such a thing in their 
private code. Its also a pretty obscure thing to use: frame hacks are 
not something that most Python programmers know anything about.

The fact that your Q() and similar solutions are described as "magic" or 
"sorcery" demenstrates that even the creators of the functions are aware 
that they are somewhat unclean hacks that shouldn't be relied on.

At least with a language feature, the hack is official, and it's the 
responsibility of the language devs to keep it working, at which point 
it ceases to be a hack and becomes just part of the language.

With a Python level hack, if something breaks, it's *my* responsibility 
to fix it, and I'll get zero sympathy from anyone else.

So if the only choices are "deal with the middling pain of `name=name` 
function calls" versus "take on an unknown amount of technical debt by 
using an unsupported hack", I'll keep writing `name=name` thank you very 
much :-)


> If repeating names was
> actually such a big pain point, a decent solution has been available for a
> very long time, but it didn't itch enough for many people to write a few
> lines with some slight magic to scratch it.

The fact that it requires the use of a private function means that many 
people will not consider it a decent solution, but technical debt which 
will have to be paid eventually.

When I compare the Python community to (say) the Java community, I am 
pleasantly surprised about how seriously most Python people are about 
not using _private APIs. Sometimes I feel that Java programmers spend 
half their day trying to protect their code from other people using it, 
and the other half trying to break that protection on other people's 
code. Whereas the Python community, generally, wouldn't touch someone 
else's _private API if you paid them.

There's another issue. Put yourself in the shoes of someone who *isn't* 
the author of your Q() function, and you come across this function call:

func(arg, **Q(alpha))

It looks like a regular function. Obviously it must return a dict, 
because it is passed to the dict-unpacking operator. You don't know that 
there's anything special about Q, it just looks like a plain old Python 
function, so you know that Q takes the *value* of `alpha`, because 
that's how Python function works.

Would you recognise this as a different spelling of `alpha=alpha`?

I doubt it. And if you did, you would probably say "Wait a minute, how 
the hell does Q know the *name* from the *value* of the variable? 
Most objects don't have names!"

If you *didn't* recognise Q as magic, you might be tempted to change it. 
Say you need a couple of extra arguments:

func(arg, **Q(alpha, 'something', beta+1))

and who the hell knows what that will do! (Cue the Sorceror's Apprentice 
music.) It might even work by accident, and that would be the worst 
thing of all, because then it could stop working when we least expect 
it.

Sorry David, when I see your magic Q() I see technical debt, not a 
viable solution for production code.



-- 
Steven
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/JRUONSLVDJGVOTKFRFXBBAHVAFSIZ3ND/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread Steven D'Aprano
On Mon, Apr 20, 2020 at 02:50:53AM +1200, Greg Ewing wrote:
> On 19/04/20 6:58 pm, Steven D'Aprano wrote:
> >There are three tokens there: `**{`, an identifier, and `}`. Adding an
> >optional comma makes four.
> >
> >If this is your idea of "complicated syntax", I cannot imagine how you
> >cope with function definitions in their full generality:
> 
> What I mean is that much simpler syntaxes have been proposed
> that achieve the same goal, and that don't look like something
> they're not.

I'll accept the second part, but what are those "much simpler" syntaxes? 
I know of these alternatives:

**{alpha, beta, gamma}
**{:alpha, :beta, :gamma}
*, alpha, beta, gamma
**, alpha, beta, gamma
alpha=, beta=, gamma=

although I may have missed some. I'm not seeing "much" difference in 
complexity between them, syntax-wise.

Can we at least try to avoid unnecessary hyperbole in describing ideas 
we don't like? It's disheartening and frustrating to see microscopic 
differences blown all out of proportion.



-- 
Steven
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/F4XXVR3IM5MEPXGTBIQYYVQVQZZFKBGS/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Keyword arguments self-assignment

2020-04-19 Thread Steven D'Aprano
On Sun, Apr 19, 2020 at 09:28:28AM -0400, Eric V. Smith wrote:

[...]
> >This will cause a slight reduction in readability of code, as cases of
> >foo = phoo, start to stand out and get changed to just foo (by renaming
> >the variable phoo). It is a natural outcome of you get what you make
> >special cases for.
> 
> I agree: this is part of why I consider this whole proposal to be an 
> anti-pattern. I'd expect a PEP to mention the above issues. Thanks for 
> highlighting them.

If it is an anti-pattern for one method to duplicate the parameter names 
of another method, is it a pattern to intentionally differentiate the 
parameter names by using synonyms?

I regularly -- not frequently, but often enough that it becomes a pain 
point -- have a situation where I have one or more public functions 
which call other functions with the same parameters.

Here's a real signature from one of my functions where this occurs.

def inspect(obj=_SENTINEL, pattern=None,
*, dunder=True, meta=False, private=True, 
ignorecase=False, invert=False)

It ends up calling a ton of methods that accept some or all of the same 
parameter names, using the `dunder=dunder` idiom. Today I learned this 
is an antipattern.

For the record, earlier in this thread I considered making this same 
argument against this proposal because it would encourage people to 
rename their parameters to match those of other functions, but I deleted 
it. At least I hope I deleted it, because seeing it actually written 
down shows me that it's a really weak argument.

Consistency of parameter names is more often a good thing than a bad 
thing. I don't know if that counts as a point in favour of this 
proposal, but I'm pretty sure it shouldn't count as a point against it.



-- 
Steven
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/3WYPDIMIQUOLS7FMCN7PPPOZFB52CFPE/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread oliveira . rodrigo . m
David Mertz wrote:
> [...] Many of the new syntax ideas COULD be done with an
> arcane function that only needs to be written once (but better than my 15
> minute versions). The fact that such magic functions are not in widespread
> use, to my mind, argues quite strongly against them actually meriting new
> syntax.

People can live without this syntax, the rationale of the proposal ins't that 
users are actively complaining about this and if people aren't expressing 
anything about this issue isn't real reason to rule out an idea.

Type hints may be an example, I guess... We could keep using comments for that 
or other hacks, no new syntax needed. But in order for people who would benefit 
from it to start actually using it to make it as easy as possible was the push 
this feature needed for gaining wider adoption. Correct me if I'm off here 
please.

The proposal intends to allow for better code and to serve as an incentive for 
the widespread use of keyword parameters.

A utility function `Q` won't have high adherence because it is essentially a 
hack and no one wants to install a lib and go importing `Q` in every project 
file. If it's not easy and/or doesn't look nice people won't use it.

This is only my humble opinion though.

Rodrigo Martins de Oliveira
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/VRNDZ33ZMHDSWETIOBGIUGJGT4B2MCZL/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread Steven D'Aprano
On Sun, Apr 19, 2020 at 02:10:21PM +0200, Alex Hall wrote:
> >
> > And notice that there is absolutely no difficulty with some future
> > enhancement to allow positional arguments after keyword arguments.
> >
> 
> We've already discussed in this thread that we shouldn't fear conflicting
> with other (real or hypothetical) proposals, even if they're likely. As I
> see it, the chance of allowing positional arguments after keyword arguments
> is basically zero. The restriction is intentionally there for a good reason.

Python already allows positional arguments after keyword 
arguments:

py> sorted(reverse=True, *([1, 4, 2, 3],))
[4, 3, 2, 1]



> And quoting your next message:
> 
> > All else being equal, we should prefer the syntax that doesn't rule 
> > out future development.
> 
> I don't think all else is equal.

That's a fair opinion.

[...]
> Also, the way you're arguing against possibly conflicting with some future
> enhancement, I'm not sure why you'd ever support said enhancement, given
> that it would still potentially conflict with other possible enhancements
> in the even more distant future.

There is a qualitative difference between:

"Your proposal will rule out this specific thing and should be weighed 
up in light of that"

and 

"Your proposal could rule out some unknown thing that nobody has thought 
of, so it should be rejected!"

I have an actual, concrete possible enhancement in mind: relaxing the 
restriction on parameter order. Do you have an actual, concrete 
future enhancement in mind that relaxing the restriction would conflict 
with?

-- 
Steven
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/UB6B6OQUEEFATF5INKESFQ5QECE4ZNZZ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread David Mertz
Nope, that's fine.

I reckon it's reasonable to call this inspecting the source code.  I
thought from your GH issue that you meant you read in a whole module of
code.

I don't want my Q(), or M(), or whatever letter comes after that, in the
standard library.  I don't even care about making a repo for it or
publishing it on PyPI.  Even if you can find a way to break it... which I'm
happy to stipulate you can, that doesn't matter a whit to the possible
utility... if the need was genuine.

If this were in the library I or my project used, whatever limitations and
edge cases exist wouldn't really matter.  If I REALLY cared about saving a
few duplicate names in function calls, I could easily include it with the
knowledge that it won't handle such-and-such edge cases. If the improvement
really mattered for normal, boring code that makes up 99% of the code I
write, I could use it in that 99%.  But I don't. And you don't. And no one
in this thread does so special syntax for something no one actually
does is foolish.

... that said, I like your latest suggestion best of what I've seen.  I.e.

built_dict = {**, foo, bar, baz}
my_func(**, foo, bar, baz)
my_other_func(**kws, foo, bar)

Those all read nicely, and in a consistent way.  You could even drop the
bare ** by using:

my_func(**{}, foo, bar, baz)

(if there was a reason someone was OK with self-naming values but not with
bare '**').

On Sun, Apr 19, 2020 at 5:01 PM Alex Hall  wrote:

> Per your wish, Eric, the glorious successor of Q() ... named M():
>>
>> >>> def M(*vals):
>> ... import sys
>> ... import inspect
>> ... caller = sys._getframe(1)
>> ... call = inspect.stack()[1].code_context[0]
>> ... _, call = call.split('M(')
>> ... call = call.strip()[:-1]
>> ... names = [name.strip() for name in call.split(',')]
>> ... dct = {}
>> ... for name in names:
>> ... dct[name] = eval(name, globals(), caller.f_locals)
>> ... return dct
>> ...
>> >>> x, y, z = range(3)
>> >>> M(x, y, z)
>> {'x': 0, 'y': 1, 'z': 2}
>>
>> OK, it's a little bit fragile in assuming the function must be called M
>> rather than trying to derive its name.  And maybe my string version of
>> finding the several args could be made more robust.  But anyone is welcome
>> to improve it, and the proof of concept shows that's all we need.
>> Basically, a "dict-builder from local names" is perfectly amenable to
>> writing as a Python function... and we don't need to inspect the underlying
>> source code the way I believe Alex' sorcery module does (other parts of it
>> might need that, but not this).
>>
>
> I can lay out all the issues with this if you want me to, but after my
> previous email I don't think I have to. I'm just wondering why you say it
> doesn't need to inspect the underlying source code. That's what
> `code_context` is and that's obviously the only place where a string like
> `'M('` could be found, unless you want to uncompile bytecode (which is not
> impossible either, but it's an additional mess).
>


-- 
Keeping medicines from the bloodstreams of the sick; food
from the bellies of the hungry; books from the hands of the
uneducated; technology from the underdeveloped; and putting
advocates of freedom in prisons.  Intellectual property is
to the 21st century what the slave trade was to the 16th.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/B7V5Y65Q7AFY6OWGEFTZJPG3OZMBPKWR/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread Alex Hall
On Sun, Apr 19, 2020 at 11:00 PM David Mertz  wrote:

> See this thread where I created M() as successor of Q().
>
>>
I saw, and I mentioned it:

I see you've tried while I wrote this, and it's pretty clear it's very far
> from robust.


It's really not that hard, I don't think. Probably there are edge cars I
> haven't addressed, but it's hardly intractable.
>

I promise, it really is that hard. It's doable, I've done it, but your
version is far from needing to address a few more edge cases. You *can*
write a decent version without too much difficulty that will work as long
as people follow certain obscure rules (i.e. stay away from the edge
cases). That's basically what sorcery's first version was. But that'd be a
very unusual user experience. It takes a whole lot more for something
robust that can't be accidentally misused. And you will certainly need
access to the source code.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/OCEDVA7NBTKOYSY5FUX3C6B3KOTNZFDI/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread Alex Hall
>
> Per your wish, Eric, the glorious successor of Q() ... named M():
>
> >>> def M(*vals):
> ... import sys
> ... import inspect
> ... caller = sys._getframe(1)
> ... call = inspect.stack()[1].code_context[0]
> ... _, call = call.split('M(')
> ... call = call.strip()[:-1]
> ... names = [name.strip() for name in call.split(',')]
> ... dct = {}
> ... for name in names:
> ... dct[name] = eval(name, globals(), caller.f_locals)
> ... return dct
> ...
> >>> x, y, z = range(3)
> >>> M(x, y, z)
> {'x': 0, 'y': 1, 'z': 2}
>
> OK, it's a little bit fragile in assuming the function must be called M
> rather than trying to derive its name.  And maybe my string version of
> finding the several args could be made more robust.  But anyone is welcome
> to improve it, and the proof of concept shows that's all we need.
> Basically, a "dict-builder from local names" is perfectly amenable to
> writing as a Python function... and we don't need to inspect the underlying
> source code the way I believe Alex' sorcery module does (other parts of it
> might need that, but not this).
>

I can lay out all the issues with this if you want me to, but after my
previous email I don't think I have to. I'm just wondering why you say it
doesn't need to inspect the underlying source code. That's what
`code_context` is and that's obviously the only place where a string like
`'M('` could be found, unless you want to uncompile bytecode (which is not
impossible either, but it's an additional mess).
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/4WQWZCC22L3E42L4SAJP3IYOMHEI3RHE/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread David Mertz
See this thread where I created M() as successor of Q().  It's really not
that hard, I don't think. Probably there are edge cars I haven't addressed,
but it's hardly intractable.

On Sun, Apr 19, 2020, 4:51 PM Alex Hall  wrote:

> On Sun, Apr 19, 2020 at 5:59 PM David Mertz  wrote:
>
>> On Sun, Apr 19, 2020 at 7:00 AM Chris Angelico  wrote:
>>
>>> Yes, exactly. One strike doesn't mean it's out, and with a proposal
>>> like this, it's a matter of looking at a whole lot of imperfect
>>> alternatives and seeing which tradeoffs we want to go with. (And
>>> status quo is one such alternative, with tradeoffs of "names need to
>>> be duplicated".)
>>>
>>
>> I think you've missed on alternative.  Well, it's a variation on "status
>> quo":  Use a silly magic helper function like my Q() or Alex' dict_of() in
>> his sorcery library.  (Albeit, I tried his library, and it seemed to have a
>> bug I filed an issue on, which might be fixed yesterday; I haven't tried
>> again).
>>
>> But if anyone really wants abbreviated calls with parameters now, they
>> can use:
>>
>> process_record(**Q(email, firstname, lastname, cellphone))
>>
>> That gets skipping `email=email, ...` if you really want.  And it's
>> within a character or two of the length of other proposals.
>>
>> Understand that I'm not really advocating for a magic function like Q().
>> I think it's important to keep in mind that anyone COULD create such a
>> thing for 20 years, and very few people bothered to.  If repeating names
>> was actually such a big pain point, a decent solution has been available
>> for a very long time, but it didn't itch enough for many people to write a
>> few lines with some slight magic to scratch it.
>>
>
> I think I'm uniquely qualified to say with certainty that this is 100% not
> true. A basic version like Q("email firstname lastname") like you wrote is
> indeed easy to do correctly, but I've said why I wouldn't want to use it
> and I think others would agree. The real thing, `Q(email, firstname,
> lastname, cellphone)`, is very hard to do correctly.
>
> Q was essentially requested in this question:
> https://stackoverflow.com/questions/18425225/getting-the-name-of-a-variable-as-a-string
>
>
>1. The question is very popular. People have wanted this feature for a
>long time. I'd say that's a strong point in favour of these proposals in
>general.
>2. The question was asked in 2013, and went a long time without a
>satisfying answer.
>3. Most answers either say it's not possible or give naive
>implementations that easily fail.
>4. The currently accepted answer (which only appeared in 2019) looks
>legitimate and some people probably trust it, but it's very shaky. [It uses
>a regex](
>
> https://github.com/pwwang/python-varname/blob/25785b6aab2cdffc71095642e4d48a52548bbdf1/varname.py#L61)
>to parse the Python, in much the same way that one shouldn't parse HTML. [I
>just told the author to use my library instead](
>https://github.com/pwwang/python-varname/issues/3), and he quickly
>agreed that was much better and made me a collaborator.
>
> Writing sorcery was hard. The first version was already hard enough, and
> [had several limitations](
> https://github.com/alexmojaki/sorcery/tree/7c85e5d802de26a435e4d190e02ca9326b6e7e57#rules-for-casting-spells).
> For example, you couldn't  use dict_of (i.e. Q()) twice in the same line.
>
> Some time later I discovered [icecream](https://github.com/gruns/icecream).
> It seemed to have solved this problem - it could detect the correct call
> when there were several on the same line. It had about a thousand stars,
> 150 commits, and claimed to be well tested. I thought it was the real deal,
> and clearly other people did too. It had a complicated implementation that
> analysed the bytecode and did lots of manual parsing.
>
> When I tried to incorporate this implementation into my own code, I
> realised that [it was in fact deeply broken and failed in many different
> simple cases](https://github.com/gruns/icecream/pull/33). People hadn't
> actually noticed because they rarely used it inside an expression, [they
> usually just wrote `ic(x)` on its own line](
> https://github.com/gruns/icecream/issues/39#issuecomment-552611756).
>
> But I used the idea of analysing bytecode to write my own implementation,
> [executing](https://github.com/alexmojaki/executing). It was extremely
> hard. At several points I thought it was unsolvable or that I'd fool myself
> into thinking I'd solved it when actually it was quietly broken. At one
> point I was going crazy trying to figure out why the peephole optimizer was
> behaving inconsistently; I think it was because I hadn't correctly copied
> locations between AST nodes. Ultimately it's one of my proudest
> achievements. I'm pretty sure no one else has gotten this far. I think some
> others (e.g. icecream, varname, and amusingly, [q](
> https://github.com/zestyping/q)) got quite far, with significant 

[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread Alex Hall
On Sun, Apr 19, 2020 at 5:59 PM David Mertz  wrote:

> On Sun, Apr 19, 2020 at 7:00 AM Chris Angelico  wrote:
>
>> Yes, exactly. One strike doesn't mean it's out, and with a proposal
>> like this, it's a matter of looking at a whole lot of imperfect
>> alternatives and seeing which tradeoffs we want to go with. (And
>> status quo is one such alternative, with tradeoffs of "names need to
>> be duplicated".)
>>
>
> I think you've missed on alternative.  Well, it's a variation on "status
> quo":  Use a silly magic helper function like my Q() or Alex' dict_of() in
> his sorcery library.  (Albeit, I tried his library, and it seemed to have a
> bug I filed an issue on, which might be fixed yesterday; I haven't tried
> again).
>
> But if anyone really wants abbreviated calls with parameters now, they can
> use:
>
> process_record(**Q(email, firstname, lastname, cellphone))
>
> That gets skipping `email=email, ...` if you really want.  And it's within
> a character or two of the length of other proposals.
>
> Understand that I'm not really advocating for a magic function like Q().
> I think it's important to keep in mind that anyone COULD create such a
> thing for 20 years, and very few people bothered to.  If repeating names
> was actually such a big pain point, a decent solution has been available
> for a very long time, but it didn't itch enough for many people to write a
> few lines with some slight magic to scratch it.
>

I think I'm uniquely qualified to say with certainty that this is 100% not
true. A basic version like Q("email firstname lastname") like you wrote is
indeed easy to do correctly, but I've said why I wouldn't want to use it
and I think others would agree. The real thing, `Q(email, firstname,
lastname, cellphone)`, is very hard to do correctly.

Q was essentially requested in this question:
https://stackoverflow.com/questions/18425225/getting-the-name-of-a-variable-as-a-string


   1. The question is very popular. People have wanted this feature for a
   long time. I'd say that's a strong point in favour of these proposals in
   general.
   2. The question was asked in 2013, and went a long time without a
   satisfying answer.
   3. Most answers either say it's not possible or give naive
   implementations that easily fail.
   4. The currently accepted answer (which only appeared in 2019) looks
   legitimate and some people probably trust it, but it's very shaky. [It uses
   a regex](
   
https://github.com/pwwang/python-varname/blob/25785b6aab2cdffc71095642e4d48a52548bbdf1/varname.py#L61)
   to parse the Python, in much the same way that one shouldn't parse HTML. [I
   just told the author to use my library instead](
   https://github.com/pwwang/python-varname/issues/3), and he quickly
   agreed that was much better and made me a collaborator.

Writing sorcery was hard. The first version was already hard enough, and
[had several limitations](
https://github.com/alexmojaki/sorcery/tree/7c85e5d802de26a435e4d190e02ca9326b6e7e57#rules-for-casting-spells).
For example, you couldn't  use dict_of (i.e. Q()) twice in the same line.

Some time later I discovered [icecream](https://github.com/gruns/icecream).
It seemed to have solved this problem - it could detect the correct call
when there were several on the same line. It had about a thousand stars,
150 commits, and claimed to be well tested. I thought it was the real deal,
and clearly other people did too. It had a complicated implementation that
analysed the bytecode and did lots of manual parsing.

When I tried to incorporate this implementation into my own code, I
realised that [it was in fact deeply broken and failed in many different
simple cases](https://github.com/gruns/icecream/pull/33). People hadn't
actually noticed because they rarely used it inside an expression, [they
usually just wrote `ic(x)` on its own line](
https://github.com/gruns/icecream/issues/39#issuecomment-552611756).

But I used the idea of analysing bytecode to write my own implementation,
[executing](https://github.com/alexmojaki/executing). It was extremely
hard. At several points I thought it was unsolvable or that I'd fool myself
into thinking I'd solved it when actually it was quietly broken. At one
point I was going crazy trying to figure out why the peephole optimizer was
behaving inconsistently; I think it was because I hadn't correctly copied
locations between AST nodes. Ultimately it's one of my proudest
achievements. I'm pretty sure no one else has gotten this far. I think some
others (e.g. icecream, varname, and amusingly, [q](
https://github.com/zestyping/q)) got quite far, with significant effort,
but still had a long way to go, and I'm not sure how much they're aware of
that, let alone their users. I see you've tried while I wrote this, and
it's pretty clear it's very far from robust.

And despite all that, as you've seen, sorcery still has limitations. It
clashes with magic like pytest, IPython, and birdseye, and the only way to
deal with that is with 

[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread David Mertz
On Sun, Apr 19, 2020 at 2:37 PM Eric V. Smith  wrote:

> So, if M() existed, you could say:
>
> d = M(telephone, name)
> func(**d)
>
> or
>
> func(**M(telephone, name))
>
Per your wish, Eric, the glorious successor of Q() ... named M():

>>> def M(*vals):
... import sys
... import inspect
... caller = sys._getframe(1)
... call = inspect.stack()[1].code_context[0]
... _, call = call.split('M(')
... call = call.strip()[:-1]
... names = [name.strip() for name in call.split(',')]
... dct = {}
... for name in names:
... dct[name] = eval(name, globals(), caller.f_locals)
... return dct
...
>>> x, y, z = range(3)
>>> M(x, y, z)
{'x': 0, 'y': 1, 'z': 2}

OK, it's a little bit fragile in assuming the function must be called M
rather than trying to derive its name.  And maybe my string version of
finding the several args could be made more robust.  But anyone is welcome
to improve it, and the proof of concept shows that's all we need.
Basically, a "dict-builder from local names" is perfectly amenable to
writing as a Python function... and we don't need to inspect the underlying
source code the way I believe Alex' sorcery module does (other parts of it
might need that, but not this).

-- 
Keeping medicines from the bloodstreams of the sick; food
from the bellies of the hungry; books from the hands of the
uneducated; technology from the underdeveloped; and putting
advocates of freedom in prisons.  Intellectual property is
to the 21st century what the slave trade was to the 16th.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/L4D47KAFLBYKW3EDTD5FAUPTHPJP6GNC/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Keyword arguments self-assignment

2020-04-19 Thread Rhodri James

On 19/04/2020 17:06, Alex Hall wrote:



  function(*, dunder, invert, private, meta, ignorecase)




No reader will ever have to think about the difference. They will simply
see the second version and know which arguments are being passed.


I seem to be immune to this magical knowledge.



Sorry, what? How is there any doubt that the arguments being passed are
dunder, invert, private, meta, and ignorecase? They're right there.


Oh, so that's what you meant.  But how is this different from

function(dunder, invert, private, meta, ignorecase)

if you trust yourself to get the argument order right, or

function(dunder=dunder,
 invert=invert,
 private=private,
 meta=meta,
 ignorecase=ignorecase)

if you don't?  I still don't get why you think that last form is a problem.


Now, which parameters those arguments are bound to is less obvious, but:


1. When you read the function call, you're thinking about the arguments,
not the parameters. You can see which information goes into the function,
and the first question you should ask yourself is 'is that the right
information?'.


Bitter experience has taught me to think about both the arguments and 
the parameters.  You can't answer the question "is that the right 
information?" until you know what the right information is.



2. Even if you have no idea what the parameters of the function are, you
can already reasonably guess that they match the argument names, and that
guess is correct! If you have some idea what the parameter names are, you
can be more confident in that guess. Or, if you didn't know the parameter
names, but you know what the `**` separator means, now you know the names.


All I can say is that I doubt I would make that association.  I 
certainly don't when similar things come up in function definitions.



3. You probably only start to think about parameter binding when you
open up the function definition, and when you do that, binding is still
probably not the first thing you look at. You're probably thinking about
what the function does in the body.


Well, no, that's not how I work at all.


4. If there are just a few arguments, you're less likely to miss or
ignore the `**`.


True.  But on the other hand, you have less excuse not to be explicit 
about which names are bound to which.



5. If there are many arguments, you're less likely to notice any
mismatch between argument and parameter positions that might falsely make
you think something is wrong. That is, you're less likely to either
remember the parameter order or to go through the trouble of inspecting and
comparing the orders.


In my experience, the more arguments there are, the more likely it is 
that something has been got wrong, so I'm actually more likely to go to 
the trouble of inspecting and comparing the orders.  Maybe I'm paranoid, 
but I've caught enough bugs that way to feel justified in my paranoia.



6. If you're thinking about parameter binding and argument order, you're
inspecting the arguments at least somewhat closely, and will almost
certainly notice that the `**` is present. If you know what it means,
problem solved. If you don't, you're at least likely to think about it and
try looking it up or ask someone. It takes a very specific kind of
skepticism/suspicion to think "the previous programmer messed up the
argument order so these parameters are definitely bound wrong, and also
that weird `**` that I don't know the meaning of has no bearing on that,
and I'm not going to check with a print() or a debugger".


If I have to go away and look some syntax up, that syntax has slowed me 
down.  This doesn't seem like a win to me.


--
Rhodri James *-* Kynesim Ltd
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/ZHP2YUFULMD53GAWN2D4QRNXPEAUQH33/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread Alex Hall
>
> So, if M() existed, you could say:
>
> d = M(telephone, name)
> func(**d)
>
> or
>
> func(**M(telephone, name))
>
> Or, you could just use "d" from the first example for your own purposes
> unrelated to function calling.
>
My point is: We already have a way to pass the items in a dictionary as
> keyword args: let's not invent another one. Instead, let's focus on a
> general purpose way of creating a dictionary that meets the requirements of
> being able to be passed as keyword args. That way we'd me making the
> language more expressive beyond just function calls.
>
Personally my favourite potential outcome from all this would be allowing
the `**` mode separator in both dicts and calls, so you could write:

d = {**, telephone, name}
func(**d)

or

func(**, telephone, name)

Also I think Dominik has made an excellent point that this would only be
needed if there were no kwargs already, so this would also be possible:

func(**kwargs, telephone, name)

assuming that some relevant kwargs exist. Then there isn't even any new
syntax, just a way to interpret something which is currently forbidden.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/HQOXHGRDUSX52VEN3SRHFYBU5QWZ4DRZ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Keyword arguments self-assignment

2020-04-19 Thread Alex Hall
On Sun, Apr 19, 2020 at 7:06 PM Stephen J. Turnbull <
turnbull.stephen...@u.tsukuba.ac.jp> wrote:

> Alex Hall writes:
>
>  > OK, that's fair. What about `{foo::}`?
>
> I don't like any of them.  People who are going to use the syntax
> should choose it, not those of us who won't.
>

First of all, if this proposal went through, even if you didn't write code
using it, you'd still have to read it.

Secondly these discussions are often not just about how we personally would
be affected by a proposal, but others too, especially beginners who haven't
seen a particular syntax beforehand.

So you don't have to tell us which one is your favourite, but I think it's
fair to ask if you have specific objections to a specific syntax, or if one
syntax (e.g. `foo::`) resolves the objection you had against another syntax
(`::foo`). Of course, if you don't want to spend energy or time explaining,
that's understandable too.


>
>  > I would personally be quite happy if I could replace:
>  >
>  > ```
>  > class A:
>  > def __init__(self, foo, bar, spam):
>  > self.foo = foo
>  > self.spam = spam
>  > self.bar = bar
>  > ```
>  >
>  > with something like:
>  >
>  > ```
>  > class A:
>  > def __init__(self, foo, bar, spam):
>  > setattrs(self, **, foo, bar, spam)
>  > ```
>  >
>  > Wouldn't you?
>
> No, I doubt I would use that.  It's not so much the repetition of
> identifiers alone, it's the combination with the repetition of self:
> two dimensional redundancy!


But...this solves exactly that! self went from three appearances to one
(not counting the signature). I don't get what you're saying.


> > Please make a PR showing how you would refactor some of these.
>
> Again, you must be joking.  You need to show that this is useful
> enough to be worth a syntax change, which is a high bar.  A dozen
> examples in the whole stdlib?  I'm not going to do hours of work
> understanding those modules to refactor perfectly good code.
>

Well, one of your original claims was that code that has these same-names
generally could have been written better to avoid it. When we tried to
provide counterexamples, you said:

I can't speak for your needs, only guess.  But these
> examples of function *calls* don't give me enough information to
> decide for myself whether I think there's a need to write them, much
> less show you how I would write the program without them.


So now I've given you examples where you can see the context and your
response is that it's "perfectly good code" that isn't worth the effort to
refactor. Even in your descriptions of what you 'would' do it sounds like
you'd pretty much leave them as they are in most cases. Therefore I think
it's safe to say that we're often stuck with this pattern, and we have
reason to try to make the best of it.


>
>
> *In code not intended to be maintained, I'd likely use positional
> arguments and just copy the prototypes (deleting defaults and type
> annotations).*
>

I'd like to highlight this in relation to my other messages about
positional arguments. The current syntax encourages dangerous judgements
like "this code probably doesn't need to be maintained, I'll take the easy
route".

Also I'm hearing that the redundancy bothers you enough that you'd like to
avoid it where you can, even at a cost. That suggests that there is a
problem worth fixing.


> That leaves four various other examples in the whole stdlib, not very
> many.  Although I'm sure you'd find more with a lower limit, I doubt
> they're as convincing as the ones with many same name arguments.
> We'll see what the senior committers have to say, but I think you have
> an uphill battle on your hands.


Well, here's some more data. If I take all the dicts and calls with
same-names and put the number of same-names into a Counter, here's what I
get for various projects:

CPython: Counter({1: 631, 2: 174, 3: 58, 4: 27, 5: 12, 6: 9, 8: 5, 7: 4,
10: 4})
pandas: Counter({1: 2785, 2: 864, 3: 363, 4: 165, 5: 86, 6: 55, 7: 48, 9:
23, 8: 20, 10: 11, 11: 8, 12: 7, 13: 7, 15: 4, 16: 2, 14: 2, 17: 2, 18: 2,
25: 1, 48: 1, 22: 1, 19: 1})
IPython: Counter({1: 1184, 2: 284, 3: 85, 4: 44, 5: 28, 6: 12, 7: 9, 11: 5,
10: 2, 8: 2, 14: 2})
scikit-learn: Counter({1: 817, 2: 188, 3: 81, 4: 30, 5: 27, 7: 15, 6: 14,
10: 10, 8: 10, 11: 7, 13: 5, 9: 5, 14: 4, 15: 4, 12: 3, 23: 3, 17: 3, 19:
3, 22: 1, 16: 1, 21: 1})
Django: Counter({1: 562, 2: 130, 3: 48, 5: 13, 4: 12, 7: 3, 6: 3, 10: 2, 9:
2, 18: 1, 12: 1, 8: 1})
matplotlib: Counter({1: 783, 2: 181, 3: 76, 4: 34, 6: 22, 5: 10, 7: 10, 9:
7, 10: 5, 13: 4, 12: 2, 15: 2, 8: 2, 25: 1, 16: 1, 14: 1, 17: 1})

Regarding the large number of calls with just a few same-names: yes, there
is less benefit to changing them to a new syntax, but there's similarly
less cost to doing so.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org

[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread Eric V. Smith

On 4/18/2020 2:03 PM, David Mertz wrote:

> f(**{u, v})

I think a fundamental point is that `**{identifier}` looks like
you are applying `**` unpacking to a set, but you actually aren't,
it is
a special syntactic form. If that disturbs you, I'm not going to
say you are wrong.


The special syntactic form doesn't bother me that much. '**dict' is 
already a syntax error in many places, but allowed in a few other places.


I also do not think the purpose served is important enough to warrant 
a new special form.  The actual same conciseness can be achieved with 
a function that does just a little bit of magic, e.g.:


    func(**Q(u, v))

Someone linked to a library that apparently does the magic a bit 
better than my 5-minute version (which required quoting the variable 
names).  I think it was you who complained that sys._getframe() might 
be CPython specific, which is true.  But probably other 
implementations could do different magic to make their own Q(), so 
that seems of little importance.


I'd be only -0.5 on any proposal from this thread (as opposed to -1000 
as I am now) if it were more general purpose than just function calls. 
Like David's "Q" function (which is an actual function), if we had some 
magic that said "create a dict from these names, where the values come 
from normal python scoping rules". Let's say that magic function is 
named M() (for magic). We might want it to be special syntax to make it 
clear it's magic (maybe "!": who knows, and it's unimportant 
here). But that's not the point: the point here is making something 
general purpose.


So, if M() existed, you could say:

d = M(telephone, name)
func(**d)

or

func(**M(telephone, name))

Or, you could just use "d" from the first example for your own purposes 
unrelated to function calling.


My point is: We already have a way to pass the items in a dictionary as 
keyword args: let's not invent another one. Instead, let's focus on a 
general purpose way of creating a dictionary that meets the requirements 
of being able to be passed as keyword args. That way we'd me making the 
language more expressive beyond just function calls.


Eric


___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/Z6UCCQKLAVWF2CMEULBZ5PGFGBQECKC6/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Keyword arguments self-assignment

2020-04-19 Thread Stephen J. Turnbull
Alex Hall writes:

 > OK, that's fair. What about `{foo::}`?

I don't like any of them.  People who are going to use the syntax
should choose it, not those of us who won't.

 > I would personally be quite happy if I could replace:
 > 
 > ```
 > class A:
 > def __init__(self, foo, bar, spam):
 > self.foo = foo
 > self.spam = spam
 > self.bar = bar
 > ```
 > 
 > with something like:
 > 
 > ```
 > class A:
 > def __init__(self, foo, bar, spam):
 > setattrs(self, **, foo, bar, spam)
 > ```
 > 
 > Wouldn't you?

No, I doubt I would use that.  It's not so much the repetition of
identifiers alone, it's the combination with the repetition of self:
two dimensional redundancy!  Probably a holdover from the implicit
'this' in C++.  Although, come to think of it, in C++ to assign to a
member with the same name as a formal argument you'd have to
explicitly use 'this'.

I apologize for wasting your time on that comment.  It turns out to be
incoherent and I shouldn't have mentioned it.

 > Please make a PR showing how you would refactor some of these.

Again, you must be joking.  You need to show that this is useful
enough to be worth a syntax change, which is a high bar.  A dozen
examples in the whole stdlib?  I'm not going to do hours of work
understanding those modules to refactor perfectly good code.

I will outline what I'd look at, though.  In general the vertically
formatted examples look fine to me, and I see no reason to refactor
them.  I'd reformat the others vertically.  In code not intended to be
maintained, I'd likely use positional arguments and just copy the
prototypes (deleting defaults and type annotations).

The two dicts look fine to me as they are.  But it's easy to say that
now I would design them using Enums.  For example:

class LogLevel(IntEnum):
CRITICAL = 6
FATAL = 5
ERROR = 4
WARN = 3
WARNING = 3
INFO = 2
DEBUG = 1
NOTSET = 0
# I wouldn't bother with this alias in my own code.
_nameToLevel = LogLevel.__members__

There are four calls to super (all in argparse), which seems to be due
to heavy use of mixins, and two calls to cls (in json/__init__.py).
Within the stdlib, the calls to super and to cls seem to be
idiosyncratic to the authors of those particular modules, but if the
plethora of same name arguments is typical of these techniques, that
would be some support for a syntax change.  I know those techniques
are commonly used, I just don't have use for them myself.

That leaves four various other examples in the whole stdlib, not very
many.  Although I'm sure you'd find more with a lower limit, I doubt
they're as convincing as the ones with many same name arguments.
We'll see what the senior committers have to say, but I think you have
an uphill battle on your hands.

Steve
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/UUN3SU2NSJIFAJOW7MQCJEXWPKIUVYWR/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Keyword arguments self-assignment

2020-04-19 Thread Richard Damon
On 4/19/20 12:04 PM, David Mertz wrote:
>
> Sure.  But what I gave was a simple case.  There are all kinds of
> complications like this person_record being passed around from call to
> call without actually accessing `.telephone` in a particular scope. 
> Or doing something dynamic with the attributes/keys that won't show up
> in a `grep telephone`.  Or the string telephone occurring lots of
> times in unrelated structures/objects.  Or lots of other cases where
> lots of name changes makes refactoring more difficult.  I mean, I've
> DONE it, and I'm sure you have as well.  Clearly refactoring isn't
> impossible with different names across scopes... and this goal is one
> of several in picking names, not the single predominant one.
>
>  

The fact that the name of the variable changes shouldn't affect the
refactoring. If the scope doesn't reference the telephone attribute,
then it shouldn't be affected by the refactoring. Yes, the dynamic cases
says we need to look for the string telephone as well as the direct
reference of the attribute telephone.

The fact that we get telephone showing up in unrelated structures is
likely a plus, as if we find that it isn't good enough to store just a
single phone number in this sort of record, we likely should be thinking
about how we did it elsewhere, especially the way it was described as
the data flowing through various forms and not just a single structure.

In some ways this show the danger of coercing the programmer to reuse
names for unrelated things, it encourages bad names. The mere fact that
the record had a single field called 'telephone', as even decades ago
many people had more than 1 phone number, they at least had a home_phone
and and work_phone (and later a cell_phone).

-- 
Richard Damon
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/V6MEQ2P43PZZAIUHIZEWRM7TANYKEEJT/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Keyword arguments self-assignment

2020-04-19 Thread Ricky Teachey
> And we're done, the problem is solved, and no new syntax is needed.
>
>
> That's bad, and we should discourage that. Encouraging people to safely
> pass named arguments instead of abusing positional arguments would improve
> the readability and correctness of code overall.
>

I have nothing significant to add, but want to emphasize this. I think it
is potentially a large point in favor of the syntax change: nudging people
away from abusing positional arguments.

---
Ricky.

"I've never met a Kentucky man who wasn't either thinking about going home
or actually going home." - Happy Chandler
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/FWXHNJO5CRQO3THKS5EN4YF2KPJB7HJR/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Keyword arguments self-assignment

2020-04-19 Thread Alex Hall
>
> >>  function(*, dunder, invert, private, meta, ignorecase)
> >>
> >
> >
> > No reader will ever have to think about the difference. They will simply
> > see the second version and know which arguments are being passed.
>
> I seem to be immune to this magical knowledge.
>

Sorry, what? How is there any doubt that the arguments being passed are
dunder, invert, private, meta, and ignorecase? They're right there.

Now, which parameters those arguments are bound to is less obvious, but:


   1. When you read the function call, you're thinking about the arguments,
   not the parameters. You can see which information goes into the function,
   and the first question you should ask yourself is 'is that the right
   information?'.
   2. Even if you have no idea what the parameters of the function are, you
   can already reasonably guess that they match the argument names, and that
   guess is correct! If you have some idea what the parameter names are, you
   can be more confident in that guess. Or, if you didn't know the parameter
   names, but you know what the `**` separator means, now you know the names.
   3. You probably only start to think about parameter binding when you
   open up the function definition, and when you do that, binding is still
   probably not the first thing you look at. You're probably thinking about
   what the function does in the body.
   4. If there are just a few arguments, you're less likely to miss or
   ignore the `**`.
   5. If there are many arguments, you're less likely to notice any
   mismatch between argument and parameter positions that might falsely make
   you think something is wrong. That is, you're less likely to either
   remember the parameter order or to go through the trouble of inspecting and
   comparing the orders.
   6. If you're thinking about parameter binding and argument order, you're
   inspecting the arguments at least somewhat closely, and will almost
   certainly notice that the `**` is present. If you know what it means,
   problem solved. If you don't, you're at least likely to think about it and
   try looking it up or ask someone. It takes a very specific kind of
   skepticism/suspicion to think "the previous programmer messed up the
   argument order so these parameters are definitely bound wrong, and also
   that weird `**` that I don't know the meaning of has no bearing on that,
   and I'm not going to check with a print() or a debugger".

In summary, I think that the vast majority of the time, the new syntax will
cause no confusion (even when it potentially could have) because people
will skim and follow their intuition. Occasionally, it might cause brief,
mild confusion, and that will mostly only be one or two times for each
programmer as they learn the new syntax. I can't see it causing serious
confusion outside of very specific and rare circumstances.

> Also, your examples are clearly demonstrating that using the shortcut
> makes
> > it easier to avoid mistakes.
>
> It shows that using positional parameters makes it easier to make
> mistakes, but that's not news.
>

Right, but people use them anyway, sometimes even to solve the exact
problem we're talking about. You're responding to me responding to Steven
D'Aprano, here's what he said just slightly earlier:

We're not talking about positional arguments here. If you want to
> include positional arguments in the analysis, then we already have a
> perfectly good way to write function calls without repeating outselves:
> # Instead of this:
> function(spam=spam, eggs=eggs, cheese=cheese)
> # Just do this:
> function(spam, eggs, cheese)
> And we're done, the problem is solved, and no new syntax is needed.


That's bad, and we should discourage that. Encouraging people to safely
pass named arguments instead of abusing positional arguments would improve
the readability and correctness of code overall.

Below are some cases from the CPython repo of people passing many
positional arguments. They could be improved by using keyword arguments
more, but with the currently available syntax, that would be very verbose
and undesirable, so it's understandable that it wasn't written that way in
the first place and hasn't been changed since then.

```
File "Lib/subprocess.py", line 947
self._execute_child(args, executable, preexec_fn, close_fds,
pass_fds, cwd, env,
startupinfo, creationflags, shell,
p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite,
restore_signals,
gid, gids, uid, umask,
start_new_session)

File "Lib/subprocess.py", line 1752
self.pid = _posixsubprocess.fork_exec(
args, executable_list,
close_fds, tuple(sorted(map(int, 

[Python-ideas] Re: Keyword arguments self-assignment

2020-04-19 Thread David Mertz
On Sun, Apr 19, 2020 at 11:54 AM Richard Damon 
wrote:

> > When it comes time to refactor—now we need to rename 'telephone' as
> > 'home_phone' and add 'cell_phone'—finding all the locations to change
> > is a PITA. If only we could grep 'person_record' globally, it would
> > have been easy.
>
> My personal thought on the case you are presenting, is that I would be
> tempted to grep for telephone, to change that because the change likely
> affects not just this given structure, but may also impact related
> structures which also assumed a single phone number.
>

Sure.  But what I gave was a simple case.  There are all kinds of
complications like this person_record being passed around from call to call
without actually accessing `.telephone` in a particular scope.  Or doing
something dynamic with the attributes/keys that won't show up in a `grep
telephone`.  Or the string telephone occurring lots of times in unrelated
structures/objects.  Or lots of other cases where lots of name changes
makes refactoring more difficult.  I mean, I've DONE it, and I'm sure you
have as well.  Clearly refactoring isn't impossible with different names
across scopes... and this goal is one of several in picking names, not the
single predominant one.



>
> --
> Richard Damon
> ___
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/PFSCBT3GATRPUPSQR4DFX4SVCJXFJUTH/
> Code of Conduct: http://python.org/psf/codeofconduct/
>


-- 
Keeping medicines from the bloodstreams of the sick; food
from the bellies of the hungry; books from the hands of the
uneducated; technology from the underdeveloped; and putting
advocates of freedom in prisons.  Intellectual property is
to the 21st century what the slave trade was to the 16th.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/NTGOZJB6QU2OUE2DICZB2ISW47M25PTB/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread David Mertz
On Sun, Apr 19, 2020 at 7:00 AM Chris Angelico  wrote:

> Yes, exactly. One strike doesn't mean it's out, and with a proposal
> like this, it's a matter of looking at a whole lot of imperfect
> alternatives and seeing which tradeoffs we want to go with. (And
> status quo is one such alternative, with tradeoffs of "names need to
> be duplicated".)
>

I think you've missed on alternative.  Well, it's a variation on "status
quo":  Use a silly magic helper function like my Q() or Alex' dict_of() in
his sorcery library.  (Albeit, I tried his library, and it seemed to have a
bug I filed an issue on, which might be fixed yesterday; I haven't tried
again).

But if anyone really wants abbreviated calls with parameters now, they can
use:

process_record(**Q(email, firstname, lastname, cellphone))

That gets skipping `email=email, ...` if you really want.  And it's within
a character or two of the length of other proposals.

Understand that I'm not really advocating for a magic function like Q().  I
think it's important to keep in mind that anyone COULD create such a thing
for 20 years, and very few people bothered to.  If repeating names was
actually such a big pain point, a decent solution has been available for a
very long time, but it didn't itch enough for many people to write a few
lines with some slight magic to scratch it.

In a number of similar discussion, someone has proposed new syntax to do
something.  And I have often written a little utility function to do
generally the same thing, perhaps with somewhat cryptic internals.  My 15
minute attempts at magic usually have some bugs or limitations, but that's
not really the point.  Many of the new syntax ideas COULD be done with an
arcane function that only needs to be written once (but better than my 15
minute versions). The fact that such magic functions are not in widespread
use, to my mind, argues quite strongly against them actually meriting new
syntax.

Just feeling like some syntax would be clever or cute should not be enough
motivation to add it, which a lot of proposals feel like to me.  We need a
real world advantage.  For that, the commonness of existing workarounds to
do near-equivalent things is very germane.

-- 
Keeping medicines from the bloodstreams of the sick; food
from the bellies of the hungry; books from the hands of the
uneducated; technology from the underdeveloped; and putting
advocates of freedom in prisons.  Intellectual property is
to the 21st century what the slave trade was to the 16th.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/XRGES5MQC4U64PVMAVS4X2MTLPJF4ZW3/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Keyword arguments self-assignment

2020-04-19 Thread Richard Damon
On 4/19/20 11:28 AM, David Mertz wrote:
> On Sun, Apr 19, 2020, 7:24 AM Richard Damon  > wrote:
>
> One of the key motivations of this proposal is to make nicer a
> call with a lot of key word arguments where the local
> variable name happens (intentionally) to match the keyword
> parameter name.
>
>
> I think Stephen said that this "same name across scopes" is an
> anti-pattern. I mostly disagree, though obviously agree that it varies
> between different code. He mentioned something like:
>
>     process_account(name=name, email=email)
>
> And that would be better with email_john and email_jane as names in
> outer scope.
>
> I've worked with large code bases where the equivalent complex object
> is used in many places. Not necessarily as a continuous life of an
> actual object, but sometimes sent as JSON, other times read from
> database, other times calculated dynamically, etc. 
>
> For example, maybe there is a 'person_record' that has as
> attributes/keys/whatever name and email. But in this existing code, a
> different name is used through a call chain and in different corners
> of the code. E.g. we read json_record, which calls something naming it
> dynamic_record, which eventually arrives at a function that saves
> db_record. But these are all actually the same object layout or even
> the same object.
>
> When it comes time to refactor—now we need to rename 'telephone' as
> 'home_phone' and add 'cell_phone'—finding all the locations to change
> is a PITA. If only we could grep 'person_record' globally, it would
> have been easy.

As with most anti-patterns, there tend to be cases where they actually
help (which is why some think of them as a useful pattern), but then it
get applied beyond the cases where it is actually useful, and then
becomes the anti-pattern.

My personal thought on the case you are presenting, is that I would be
tempted to grep for telephone, to change that because the change likely
affects not just this given structure, but may also impact related
structures which also assumed a single phone number.

-- 
Richard Damon
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/PFSCBT3GATRPUPSQR4DFX4SVCJXFJUTH/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Keyword arguments self-assignment

2020-04-19 Thread David Mertz
On Sun, Apr 19, 2020, 7:24 AM Richard Damon 
wrote:

> One of the key motivations of this proposal is to make nicer a call with a
> lot of key word arguments where the local variable name happens
> (intentionally) to match the keyword parameter name.


I think Stephen said that this "same name across scopes" is an
anti-pattern. I mostly disagree, though obviously agree that it varies
between different code. He mentioned something like:

process_account(name=name, email=email)

And that would be better with email_john and email_jane as names in outer
scope.

I've worked with large code bases where the equivalent complex object is
used in many places. Not necessarily as a continuous life of an actual
object, but sometimes sent as JSON, other times read from database, other
times calculated dynamically, etc.

For example, maybe there is a 'person_record' that has as
attributes/keys/whatever name and email. But in this existing code, a
different name is used through a call chain and in different corners of the
code. E.g. we read json_record, which calls something naming it
dynamic_record, which eventually arrives at a function that saves
db_record. But these are all actually the same object layout or even the
same object.

When it comes time to refactor—now we need to rename 'telephone' as
'home_phone' and add 'cell_phone'—finding all the locations to change is a
PITA. If only we could grep 'person_record' globally, it would have been
easy.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/XVI3TE6BMQJUD2IV2FDS4QUGHK35PWER/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread Greg Ewing

On 19/04/20 6:58 pm, Steven D'Aprano wrote:

There are three tokens there: `**{`, an identifier, and `}`. Adding an
optional comma makes four.

If this is your idea of "complicated syntax", I cannot imagine how you
cope with function definitions in their full generality:


What I mean is that much simpler syntaxes have been proposed
that achieve the same goal, and that don't look like something
they're not.

--
Greg
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/W5BS63DLRIK35GPIEJZBELVSJVJFTMO3/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Keyword arguments self-assignment

2020-04-19 Thread Eric V. Smith

On 4/19/2020 7:23 AM, Richard Damon wrote:

On 4/19/20 1:48 AM, Stephen J. Turnbull wrote:

Chris Angelico writes:

  > Except that render_template isn't one of my own functions. It's part
  > of the templating engine (this is a Flask web app). There is no
  > refactoring to do - that IS the correct way to call it.

So NOW you tell me! ;-)  Just kidding: of course I recognized that as a
library call.  Of course cases where one calls a library function with
a plethora of keyword arguments and large fraction of them are going
to take same name variables as keyword arguments are going to exist.
The question is are they frequent enough to justify an IMO ugly syntax
change.  There are a lot of other factors involved, such as why there
are so many randomly-assorted variables that are nevertheless related
by this function call, whether this particular call is repeated with
the same objects (so that it might be worth wrapping it in a
marshalling function with appropriate defaults), if it would be
conceptually useful to have a library manager object that collects all
of the assorted variables, and so on.

One thing that came to mind as I think about this proposal that may be
something to think about. One of the key motivations of this proposal is
to make nicer a call with a lot of key word arguments where the local
variable name happens (intentionally) to match the keyword parameter
name. IF we do something to make this type of call nicer, then there is
now an incentive to make your local variables that are going to be
passed into functions match the name of the keyword parameter. This
incentive might push us from using what be a more descriptive name,
which describes what we are doing in our particular case, to match the
more generic name from the library.

There is also the issue that if we are building a function that might be
used with another function, we will have an incentive to name our
keyword parameters that there is a reasonable chance would also be
passed to that other function with the same keyword name, even if that
might not be the most descriptive name.

This will cause a slight reduction in readability of code, as cases of
foo = phoo, start to stand out and get changed to just foo (by renaming
the variable phoo). It is a natural outcome of you get what you make
special cases for.


I agree: this is part of why I consider this whole proposal to be an 
anti-pattern. I'd expect a PEP to mention the above issues. Thanks for 
highlighting them.


Eric
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/KWJKUCRHDFOTX5HUFBNZ3JXB2QDM3UN7/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread Alex Hall
>
> And notice that there is absolutely no difficulty with some future
> enhancement to allow positional arguments after keyword arguments.
>

We've already discussed in this thread that we shouldn't fear conflicting
with other (real or hypothetical) proposals, even if they're likely. As I
see it, the chance of allowing positional arguments after keyword arguments
is basically zero. The restriction is intentionally there for a good reason.

And quoting your next message:

All else being equal, we should prefer the syntax that doesn't rule out
> future development.
>

I don't think all else is equal. I think the downside of a
pseudo-expression far, far outweighs the downside of conflicting with
unlikely hypothetical future proposals.

Also, the way you're arguing against possibly conflicting with some future
enhancement, I'm not sure why you'd ever support said enhancement, given
that it would still potentially conflict with other possible enhancements
in the even more distant future.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/6ATPF66QXFYPK4OQQ4TFWESLXOS5HZFM/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread Dominik Vilsmeier

On 19.04.20 12:57, Steven D'Aprano wrote:


On Sat, Apr 18, 2020 at 09:13:44PM +0200, Dominik Vilsmeier wrote:


     func(foo, **, bar)  vs.  func(foo, **{bar})

It's still a mode switch, only the beginning and end markers have
changed. Instead of `**,` (or `**mapping,`) we then have `**{` as the
opening marker and instead of `)` (the parenthesis that closes the
function call) we have `}` as the closing marker.

How do you define a mode switch?

I don't have a clear definition, instead my point was to show that there
is no substantial difference between `**` and `**{...}` (though you seem
to think differently).

Is a list display a mode? Is a string a mode? Is a float a mode?

I'd say yes, technically they are. There's a substantial difference
between writing `sys.exit()` and `"sys.exit()"`. Same for 'comment
mode': `# sys.exit()` , and most IDEs have shortcuts for switching it on
and off. However I think a major difference is that all these can exist
in different contexts, also in isolation, and hence we think of them as
self-contained entities. The modal aspect is only relevant to the compiler.

In some sense, maybe, but to me the critical factor is that nobody talks
about "list mode", "string mode", let alone "float mode". Its about the
mental model.

With `func(foo, **, bar, baz, quux)` if I use `**` as a pseudo-argument,
the interpreter switches to "auto-fill" mode and everything that follows
that (until the end of the function call) has to be interpreted
according to the mode.

With your proposal if I use `**{` then the interpreter similarly
switches to auto-fill mode and everything that follows until the next
`}` is affected by that mode. There's no big difference. The idea behind
`**` is that you could also use `**kwargs` instead and `**` is just the
case when you don't have anything to unpack (as an analogy to `*args`
vs. `*` in a function definition when you don't need to consume varargs).

A few people immediately started describing this as a mode, without
prompting. I think it is a very natural way of thinking about it.

I think what obscures the modal aspect of `**{...}` is the fact that it
somehow looks like an expression, but it isn't. It's special syntax that
can only be used in function calls, to tell the compiler that it should
autofill the parameter names. It's a mode in disguise.

And we have no way of turning the mode off. So if there is every a
proposal to allow positional arguments to follow keyword arguments, it
won't be compatible with auto-fill mode.

That is true, it doesn't have an explicit end token. However I'm not
convinced that ruling out the positional-after-keyword-arguments option
is a relevant argument against it.

With `func(foo, **{bar, baz, quux})` the mental model is closer to
ordinary argument or dict unpacking. Nobody refers to this:

 func(spam, *[eggs, cheese, aardvark], hovercraft)

as "list mode" or "argument unpacking mode". It's just "unpacking a
list" or similar. No-one thinks about the interpreter entering a special
"collect list mode" even if that's what the parser actually does, in
some sense. We read the list as an entity, which then gets unpacked.


In this example `*` and `[eggs, cheese, aardvark]` are distinct
entities, the latter can exist without the former and it has the exact
same meaning, independent of context. So we think about it as a list
that gets unpacked (and the list being a concept that can exist in
isolation, without unpacking).

With the proposed syntax we have `**{eggs, cheese, aardvark}` and here
the `**` and `{...}` parts are inseparable. Even though the latter could
exist in isolation but then it means something completely different. In
the `**{...}` listing of names these not only refer to their objects as
usual but also serve the purpose of identifying keyword parameter names.
This unusual extension of identifier meaning is limited by `**{` and `}`
and hence I consider it a mode, just like `**,` and `)`.


Likewise for dict unpacking: nobody thinks of `{'a': expr}` as entering
"dict mode". You just make a dict, then unpack it.

And nobody (I hope...) will think of keyword shortcut as a mode:

 func(foo, **{bar, baz}, quux=1)`

It's just unpacking an autofilled set of parameter names. Not a mode at
all. And notice that there is absolutely no difficulty with some future
enhancement to allow positional arguments after keyword arguments.

"unpacking an autofilled set of parameter names" implies that two
distinct actions take place. First the set of parameter names is
autofilled and converted into something that can be unpacked, and then
it actually gets unpacked. But that's not what is happening, you can't
have `**({bar, baz})`. What you *describe* is another proposal, namely
using e.g. `{:bar, :baz}` to construct the mapping and then `**` to
unpack it; `**({:bar, :baz})` works without problem. So the `**{bar,
baz}` syntax is not actually unpacking anything, it's a hint for the
compiler to treat `bar, baz` 

[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread Steven D'Aprano
On Sun, Apr 19, 2020 at 12:09:54PM +0200, Alex Hall wrote:

> > Please read what I said again, because that's a mischaracterisation of
> > what I said.
>
> I don't think it is. You said 'it ought to be something "like" an
> expression', and then that actually being an expression is not essential.
> How is it unfair to rephrase that as "something that looks like an
> expression even if it isn't"?

I don't *require* it to look like an expression when it's not. What I 
said was that it should look like an expression *rather than a mode*. 
But whatever -- if you want to stick with your wording, I'm not going to 
argue that point any further. There are more important things to 
discuss. Namely your side-note:


> > > Side note: what does this mean in your proposal? I'm guessing it's a
> > > SyntaxError?
> > >
> > > foo(a, b, **{u, v}, c, d)
> >
> > Yes, because we still have a restriction that positional arguments come
> > before keyword arguments. If that restriction is ever relaxed, then this
> > may become legal.
> >
> 
> So, as Dominik pointed out, why keep this restriction?

Because that's the conservative choice that doesn't lock out future 
language development unnecessarily.

Today, we allow positional unpacking after keyword arguments:

func(a, b=1, c=2, *args)

Perhaps some day we will want to allow regular positional arguments 
after keywords too. If we don't *need* to rule that out, why do so 
unnecessarily?

All else being equal, we should prefer the syntax that doesn't rule out 
future development.


-- 
Steven
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/WW7BRWULC33PH7YKWABHDHFOJKIYMQXQ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Keyword arguments self-assignment

2020-04-19 Thread Richard Damon
On 4/19/20 1:48 AM, Stephen J. Turnbull wrote:
> Chris Angelico writes:
>
>  > Except that render_template isn't one of my own functions. It's part
>  > of the templating engine (this is a Flask web app). There is no
>  > refactoring to do - that IS the correct way to call it.
>
> So NOW you tell me! ;-)  Just kidding: of course I recognized that as a
> library call.  Of course cases where one calls a library function with
> a plethora of keyword arguments and large fraction of them are going
> to take same name variables as keyword arguments are going to exist.
> The question is are they frequent enough to justify an IMO ugly syntax
> change.  There are a lot of other factors involved, such as why there
> are so many randomly-assorted variables that are nevertheless related
> by this function call, whether this particular call is repeated with
> the same objects (so that it might be worth wrapping it in a
> marshalling function with appropriate defaults), if it would be
> conceptually useful to have a library manager object that collects all
> of the assorted variables, and so on.

One thing that came to mind as I think about this proposal that may be
something to think about. One of the key motivations of this proposal is
to make nicer a call with a lot of key word arguments where the local
variable name happens (intentionally) to match the keyword parameter
name. IF we do something to make this type of call nicer, then there is
now an incentive to make your local variables that are going to be
passed into functions match the name of the keyword parameter. This
incentive might push us from using what be a more descriptive name,
which describes what we are doing in our particular case, to match the
more generic name from the library.

There is also the issue that if we are building a function that might be
used with another function, we will have an incentive to name our
keyword parameters that there is a reasonable chance would also be
passed to that other function with the same keyword name, even if that
might not be the most descriptive name.

This will cause a slight reduction in readability of code, as cases of
foo = phoo, start to stand out and get changed to just foo (by renaming
the variable phoo). It is a natural outcome of you get what you make
special cases for.

-- 
Richard Damon
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/GB2IZAFLXMFI2KSWJFIGHLKIIFPREWKS/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread Steven D'Aprano
On Sat, Apr 18, 2020 at 09:13:44PM +0200, Dominik Vilsmeier wrote:

> 
>     func(foo, **, bar)  vs.  func(foo, **{bar})
> 
> It's still a mode switch, only the beginning and end markers have
> changed. Instead of `**,` (or `**mapping,`) we then have `**{` as the
> opening marker and instead of `)` (the parenthesis that closes the
> function call) we have `}` as the closing marker.

How do you define a mode switch?

Is a list display a mode? Is a string a mode? Is a float a mode?

In some sense, maybe, but to me the critical factor is that nobody talks 
about "list mode", "string mode", let alone "float mode". Its about the 
mental model.

With `func(foo, **, bar, baz, quux)` if I use `**` as a pseudo-argument, 
the interpreter switches to "auto-fill" mode and everything that follows 
that (until the end of the function call) has to be interpreted 
according to the mode.

A few people immediately started describing this as a mode, without 
prompting. I think it is a very natural way of thinking about it.

And we have no way of turning the mode off. So if there is every a 
proposal to allow positional arguments to follow keyword arguments, it 
won't be compatible with auto-fill mode.

With `func(foo, **{bar, baz, quux})` the mental model is closer to 
ordinary argument or dict unpacking. Nobody refers to this:

func(spam, *[eggs, cheese, aardvark], hovercraft)

as "list mode" or "argument unpacking mode". It's just "unpacking a 
list" or similar. No-one thinks about the interpreter entering a special 
"collect list mode" even if that's what the parser actually does, in 
some sense. We read the list as an entity, which then gets unpacked.

Likewise for dict unpacking: nobody thinks of `{'a': expr}` as entering 
"dict mode". You just make a dict, then unpack it.

And nobody (I hope...) will think of keyword shortcut as a mode:

func(foo, **{bar, baz}, quux=1)`

It's just unpacking an autofilled set of parameter names. Not a mode at 
all. And notice that there is absolutely no difficulty with some future 
enhancement to allow positional arguments after keyword arguments.


-- 
Steven
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/TAWUKFIFC5TG7EEYFR6H4SH3ZASH3FAT/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread Chris Angelico
On Sun, Apr 19, 2020 at 5:46 PM Steven D'Aprano  wrote:
>
> On Sun, Apr 19, 2020 at 01:24:14AM +1000, Chris Angelico wrote:
>
> [...]
> > Alex referred to refactoring "text that looks like an expression", and
> > on that point, I absolutely agree with Steven here: there are MANY
> > places where "text that looks like an expression" can have vastly
> > different meanings in different contexts.
>
> [...]
> > So I think that the false parallel here IS a strike against the proposal.
>
> I don't deny it. I just hope people can understand that language design
> should not be "one strike and you're out". Sometimes compromises are
> needed.

Yes, exactly. One strike doesn't mean it's out, and with a proposal
like this, it's a matter of looking at a whole lot of imperfect
alternatives and seeing which tradeoffs we want to go with. (And
status quo is one such alternative, with tradeoffs of "names need to
be duplicated".)

> It would be good if we had something that was neither excessive verbose
> nor painfully terse, required nothing but ASCII, that was similar enough
> to dict unpacking to suggest a connection, but without being confusable
> to anything else even to newbies, was self-descriptive without needing
> much or any explanation, cured Covid-19, brought peace to the Middle
> East, ended poverty, and improved the level of political discourse on
> social media.
>
> But I fear we may have to relax the requirements somewhat :-)

Agreed. And not everyone will have the same preferences - the "nothing
but ASCII" option means more to some than to others, and peace in the
Middle East would be really nice but not if it means a 0.001%
performance hit in microbenchmarks. :)

> My requirements for this syntax are:
>
> - it's a form of dict unpacking, so it ought to use `**` rather than
>   overloading some other, unrelated, symbol like (say) `@` or `%`;
>
> - it ought to use a simple list of identifiers without needing extra
>   sigils or markers on each one, say:
>
>   `meta, dunder, private`
>
>   rather than
>
>   `:meta, :dunder, :private` or `meta=, dunder=, private=`

I'm actually fine with the "meta=, dunder=, private=" myself, but
that's because I'm mixing and matching so much.

> - it ought to be something "like" an expression, rather than a mode
>   that has to be turned on and then applies to the end of the function
>   call;
>
> - if it actually is an expression, that's a nice bonus, but it's
>   not essential;
>

Given that the existing keyword argument syntax isn't exactly an
expression already, I'm fine with it not being perfectly an
expression. We already use the equals sign to indicate the separation
between target and value, so it's fine IMO to use that as the
notation.

> - it ought to look Pythonic, which is subjective;
>
> - or at least not look like "line noise", which is still subjective
>   but it's probably easier to get agreement on what is ugly than on
>   what is beautiful :-)
>
> It is a lot to ask.
>
> If anyone else can think of an alternative, please do speak up!
>

Indeed. And this is why I think we need a PEP that has the
alternatives laid out with the various arguments for and against. If
someone thinks of an alternative that isn't listed, it can be added.

ChrisA
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/3U4CLHQNLZSJ4XLLWF7N6J63XBJO2KDB/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Keyword arguments self-assignment

2020-04-19 Thread Alex Hall
On Sun, Apr 19, 2020 at 7:58 AM Stephen J. Turnbull <
turnbull.stephen...@u.tsukuba.ac.jp> wrote:

> Alex Hall writes:
>
>  > > And now Lisp bites me, because '::a' means ...
>
>  > And a single colon also means something else in Lisp.
>
> Yeah, and I already pointed that out myself in this subthread.  I
> don't like these notations, and the conflict with Lisp (which I read a
> lot of) is part of why.  My taste, or the existence of Lisp, doesn't
> rule the issue, but it's input.
>
>  > Does it matter much what that notation means in a different
>  > language?
>
> Of course it might.  That's why we use the usual arithmetic operators
> for their usual meanings.  :: is not a universally used notation, but
> if we can find an alternative that's even less used, why not use that
> alternative?
>
>  > Python will struggle to evolve if it can't conflict with other
>  > languages.
>
> Strawman.  Nobody said "can't".  The question is "better".
>

OK, that's fair. What about `{foo::}`?

 > > I myself am rarely annoyed by this issue, with
>  > > the single exception of "self.foo = foo" in __init__() defs (which
>  > > can't be handled by these notations).
>  > >
>  >
>  > It can be handled:
>  >
>  > ```
>  > self.__dict__.update(**, foo, bar, spam)
>  > ```
>
> I hope you're kidding.
>
>  > And here is some actual code of mine using it:
>  >
>  > ```
>  > setattrs(cls,
>  >  text=text,
>  >  program=program,
>  >  messages=messages,
>  >  hints=hints)
>  > ```
>
> I once wrote code like that as needed; my point was that I now rarely
> need it.  There are already more concise, clearer, less ugly
> alternatives available, at least for the cases where *I* wrote code
> like that.
>

I don't understand what's happening. You clearly said you are still annoyed
by `self.foo = foo`, but that this proposal doesn't address that. I pointed
out that the proposal does address it. There's one way which is slightly
ugly but requires no setup. There's another way that's prettier and just
requires introducing one simple function.

I would personally be quite happy if I could replace:

```
class A:
def __init__(self, foo, bar, spam):
self.foo = foo
self.spam = spam
self.bar = bar
```

with something like:

```
class A:
def __init__(self, foo, bar, spam):
setattrs(self, **, foo, bar, spam)
```

Wouldn't you? Of course there's also dataclasses, but there's plenty of
places where those don't apply so nicely.

(the name 'setattrs' may not be the best for the purpose)

I can't speak for your needs, only guess.  But these
> examples of function *calls* don't give me enough information to
> decide for myself whether I think there's a need to write them, much
> less show you how I would write the program without them.
>

I provided a script to help find such cases. Let's make this more concrete.
Here is the script again, slightly improved:

```
import ast
import linecache
import sys
from collections import Counter
from pathlib import Path

root = Path(sys.argv[1])


def main():
counts = Counter()
for path in root.rglob("**/*.py"):
if 'test' in str(path):
continue
try:
source = path.read_text()
tree = ast.parse(source)
except (SyntaxError, UnicodeDecodeError):
continue

for node in ast.walk(tree):
if isinstance(node, ast.Call):
def is_same_name(keyword: ast.keyword):
return (
isinstance(keyword.value, ast.Name)
and keyword.value.id == keyword.arg
)

args = node.keywords
elif isinstance(node, ast.Dict):
def is_same_name(pair):
key, value = pair
return (
isinstance(value, ast.Name) and
isinstance(key, (ast.Constant, ast.Str)) and
value.id == key.s
)

args = zip(node.keys, node.values)
else:
continue

count = sum(map(is_same_name, args))
if count:
counts[count] += 1
if count < 7:
continue

print(f'File "{path}", line {node.lineno}')
for lineno in range(node.lineno, node.end_lineno + 1):
print(linecache.getline(str(path), lineno), end="")
print()
print("Counts:", counts)


main()
```

I ran this on master of the cpython repo. Here is the output with all the
cases with at least 7 same-named values:

```
File "setup.py", line 2232
self.add(Extension('_decimal',
   include_dirs=include_dirs,
   libraries=libraries,
   define_macros=define_macros,
   undef_macros=undef_macros,
  

[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread Alex Hall
On Sun, Apr 19, 2020 at 11:49 AM Steven D'Aprano 
wrote:

> On Sun, Apr 19, 2020 at 10:19:41AM +0200, Alex Hall wrote:
>
> > But the problem here is not that your proposal doesn't meet all the
> > requirements, it's that you have different requirements from us. You are
> > requiring something that looks like an expression even if it isn't.
>
> Please read what I said again, because that's a mischaracterisation of
> what I said.
>

I don't think it is. You said 'it ought to be something "like" an
expression', and then that actually being an expression is not essential.
How is it unfair to rephrase that as "something that looks like an
expression even if it isn't"? Note the 'if' - I didn't say "something that
looks like an expression but isn't". I did say that shortly after, but
that's specifically referring to your current proposal, of which I think
it's a fair description.


> > Side note: what does this mean in your proposal? I'm guessing it's a
> > SyntaxError?
> >
> > foo(a, b, **{u, v}, c, d)
>
> Yes, because we still have a restriction that positional arguments come
> before keyword arguments. If that restriction is ever relaxed, then this
> may become legal.
>

So, as Dominik pointed out, why keep this restriction? Why not say that
every lone name after the `**` is an auto-named keyword? What is the
advantage of being able to turn the mode off with `}`? More concretely,
what is the advantage of your proposal in these pairs?

```
foo(bar, spam=True, **{thing, stuff})
foo(bar, spam=True, **, thing, stuff)

foo(bar, spam=True, **{thing, stuff}, other=False)
foo(bar, spam=True, **, thing, stuff, other=False)

foo(bar, spam=True, **{thing, stuff}, other=False, **{baz})
foo(bar, spam=True, **, thing, stuff, other=False, baz)
```
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/NWBIZF5DHKL3B5OEEMTBOUV3HBQMKF4M/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread Steven D'Aprano
On Sun, Apr 19, 2020 at 10:19:41AM +0200, Alex Hall wrote:

> But the problem here is not that your proposal doesn't meet all the
> requirements, it's that you have different requirements from us. You are
> requiring something that looks like an expression even if it isn't.

Please read what I said again, because that's a mischaracterisation of 
what I said.


> Side note: what does this mean in your proposal? I'm guessing it's a
> SyntaxError?
> 
> foo(a, b, **{u, v}, c, d)

Yes, because we still have a restriction that positional arguments come 
before keyword arguments. If that restriction is ever relaxed, then this 
may become legal.

-- 
Steven
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/NBSFYOCOMU2RMKWCHNZZECDJVD5N6UFP/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread Alex Hall
>
> It would be good if we had something that was neither excessive verbose
> nor painfully terse, required nothing but ASCII, that was similar enough
> to dict unpacking to suggest a connection, but without being confusable
> to anything else even to newbies, was self-descriptive without needing
> much or any explanation, cured Covid-19, brought peace to the Middle
> East, ended poverty, and improved the level of political discourse on
> social media.
>
> But I fear we may have to relax the requirements somewhat :-)
>
> My requirements for this syntax are:
>
> ...
>
> - it ought to be something "like" an expression, rather than a mode
>   that has to be turned on and then applies to the end of the function
>   call;

- if it actually is an expression, that's a nice bonus, but it's
>   not essential;


But the problem here is not that your proposal doesn't meet all the
requirements, it's that you have different requirements from us. You are
requiring something that looks like an expression even if it isn't. Chris,
Andrew and I see "something that's like an expression but isn't" as a point
against, not a point in favour.

Side note: what does this mean in your proposal? I'm guessing it's a
SyntaxError?

foo(a, b, **{u, v}, c, d)
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/KO7XD4JXS7RADW3OW2ZCCK3T3FQ6ULE7/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread Steven D'Aprano
On Sun, Apr 19, 2020 at 01:24:14AM +1000, Chris Angelico wrote:

[...]
> Alex referred to refactoring "text that looks like an expression", and
> on that point, I absolutely agree with Steven here: there are MANY
> places where "text that looks like an expression" can have vastly
> different meanings in different contexts.

[...]
> So I think that the false parallel here IS a strike against the proposal.

I don't deny it. I just hope people can understand that language design 
should not be "one strike and you're out". Sometimes compromises are 
needed.

It would be good if we had something that was neither excessive verbose 
nor painfully terse, required nothing but ASCII, that was similar enough 
to dict unpacking to suggest a connection, but without being confusable 
to anything else even to newbies, was self-descriptive without needing 
much or any explanation, cured Covid-19, brought peace to the Middle 
East, ended poverty, and improved the level of political discourse on 
social media.

But I fear we may have to relax the requirements somewhat :-)

My requirements for this syntax are:

- it's a form of dict unpacking, so it ought to use `**` rather than 
  overloading some other, unrelated, symbol like (say) `@` or `%`;

- it ought to use a simple list of identifiers without needing extra
  sigils or markers on each one, say:

  `meta, dunder, private`

  rather than 

  `:meta, :dunder, :private` or `meta=, dunder=, private=`
  
- it ought to be something "like" an expression, rather than a mode
  that has to be turned on and then applies to the end of the function 
  call;

- if it actually is an expression, that's a nice bonus, but it's
  not essential;

- it ought to look Pythonic, which is subjective;

- or at least not look like "line noise", which is still subjective 
  but it's probably easier to get agreement on what is ugly than on 
  what is beautiful :-)


It is a lot to ask.

If anyone else can think of an alternative, please do speak up!



-- 
Steven
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/5NCX5433KDEFTPM5Q6BBB75SQPBKOPYH/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Proposal: Keyword Unpacking Shortcut [was Re: Keyword arguments self-assignment]

2020-04-19 Thread Steven D'Aprano
On Sun, Apr 19, 2020 at 02:30:21PM +1200, Greg Ewing wrote:
> On 19/04/20 7:17 am, Alex Hall wrote:
> >there 
> >is something about all these examples (plausibility?) that feels 
> >distinctly different from your proposal.
> 
> To me it seems like an unnecessarily complicated syntax that goes
> out of its way to look deceptively like something else.

Are we still talking about `**{identifier}`?

There are three tokens there: `**{`, an identifier, and `}`. Adding an 
optional comma makes four.

If this is your idea of "complicated syntax", I cannot imagine how you 
cope with function definitions in their full generality:

def name(arg, /, a:str='', *args, b:float=-0.0, **kw) -> str:

> >     f(a, b, c)
> >
> >     x = a, b, c
> >     f(x)
> >
> >This imagined refactoring doesn't feel as plausible. A complete beginner 
> >might think that they can do that, but a programmer who knows what 
> >tuples are can reason that it doesn't make sense.
> 
> Fun fact -- I gather there was a very early version of Python
> in which this refactoring *did* work. But it was quickly changed
> because people found it too confusing!

I can confirm your fun fact is true in Python 0.9.1, at least the first 
part. I don't know if it was changed because people were confused, or if 
they just didn't like it, or because it made it troublesome to pass a 
tuple as argument.


> I think what's happening here is that long experience with
> other languages has ingrained in us the idea that commas
> separate arguments to a function without creating tuples,
> so when we see a comma-separated list in the context of a
> function call we instinctively think "argument list" and
> not "tuple".
> 
> But there is no such precedent for the OP's proposal.

You just spent an entire paragraph describing such a precedent.



-- 
Steven
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/MFTR4XJQSXRSOOKAJBRQXXAFOMWZOUZ3/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Keyword arguments self-assignment

2020-04-19 Thread Stephen J. Turnbull
Alex Hall writes:

 > > And now Lisp bites me, because '::a' means ...

 > And a single colon also means something else in Lisp.

Yeah, and I already pointed that out myself in this subthread.  I
don't like these notations, and the conflict with Lisp (which I read a
lot of) is part of why.  My taste, or the existence of Lisp, doesn't
rule the issue, but it's input.

 > Does it matter much what that notation means in a different
 > language?

Of course it might.  That's why we use the usual arithmetic operators
for their usual meanings.  :: is not a universally used notation, but
if we can find an alternative that's even less used, why not use that
alternative?

 > Python will struggle to evolve if it can't conflict with other
 > languages.

Strawman.  Nobody said "can't".  The question is "better".

 > > I myself am rarely annoyed by this issue, with
 > > the single exception of "self.foo = foo" in __init__() defs (which
 > > can't be handled by these notations).
 > >
 > 
 > It can be handled:
 > 
 > ```
 > self.__dict__.update(**, foo, bar, spam)
 > ```

I hope you're kidding.

 > And here is some actual code of mine using it:
 > 
 > ```
 > setattrs(cls,
 >  text=text,
 >  program=program,
 >  messages=messages,
 >  hints=hints)
 > ```

I once wrote code like that as needed; my point was that I now rarely
need it.  There are already more concise, clearer, less ugly
alternatives available, at least for the cases where *I* wrote code
like that.  I can't speak for your needs, only guess.  But these
examples of function *calls* don't give me enough information to
decide for myself whether I think there's a need to write them, much
less show you how I would write the program without them.

You can continue to write such code if you want to.  The question is,
should Python add new syntax that a lot of people dislike so that you
can write code in a style that may not be necessary any more?  It's
not possible to decide whether it's necessary without seeing the rest
of the program.  (Of course "necessary" is a value judgment, not an
objective and absolute fact.  Still need to see much more of the
program to decide.)

Steve


___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/SPAV4PLQWXYBDNLWJZUNBNWXCR4B3FWO/
Code of Conduct: http://python.org/psf/codeofconduct/