[Python-ideas] Re: The Pattern Matching Wildcard Is A Bad Idea

2021-06-01 Thread Steven D'Aprano
Hi Julia, and welcome!

On Wed, Jun 02, 2021 at 05:16:29AM +0200, Julia Schmidt wrote:

> The wildcard idea looks just wrong and confusing. What if I want to use it
> as a variable and match against it like _ = 504?

Don't do that.

There is a very strong convention in Python that a single underscore is 
to be used for two purposes (and a third in the interactive interpreter 
only):

(1) For "don't care" variables; anything that you don't care about and 
aren't intending to use should be named `_`.

first, *_, last = sequence

This tells me that I am only using the first and last items, everything 
else is ignored.


(2) For internationalisation. This is a convention that comes from other 
languages, but it is so widespread that we're kinda stuck with it.

print(_("Try again."))

By convention, the underscore function is used to translate messages 
into the current location's language.


(3) And in the interactive interpreter, underscore is a special variable 
which captures the previous result. This doesn't work in scripts.

>>> 5 + 4
9
>>> _*10
90


So aside from localisation, the Pythonic convention is that a name 
consisting only of an underscore alone is something to be ignored.

There is no shortage of names. (However, good, informative, self- 
descriptive names are harder to come by.) If you really must name 
something with an underscore, instead of giving it an informative name, 
you can just use two underscores. Three or more would be better, to make 
it more visually distinctive.

 = 504  # Why not HTTP_GATEWAY_TIMEOUT ???

But for what it's worth, if I were doing a code review and saw somebody 
using underscore-only names for anything but "ignore this", I would 
likely be asking some pointed questions about why it was using such 
obfuscated names.


-- 
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/4ACXY4POBSHKXMHBWLV7PFENXKYMPESS/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] The Pattern Matching Wildcard Is A Bad Idea

2021-06-01 Thread Julia Schmidt
>From https://docs.python.org/3.10/whatsnew/3.10.html:

def http_error(status):
match status:
case 400:
return "Bad request"
case 404:
return "Not found"
case 418:
return "I'm a teapot"
case _:
return "Something's wrong with the Internet"

The wildcard idea looks just wrong and confusing. What if I want to use it
as a variable and match against it like _ = 504? This is how it should be
done:

def http_error(status):
_ = 504
match status:
case 400:
return "Bad request"
case 404:
return "Not found"
case 418:
return "I'm a teapot"
case _:
return "Gateway Timeout"
else:
return "Something's wrong with the Internet"
___
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/EJE2T26LP3JPWK3YHGZVQFRRMOPKOQDL/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add "try: stmt except: stmt" syntax to Python

2021-06-01 Thread Chris Angelico
On Wed, Jun 2, 2021 at 10:59 AM Steven D'Aprano  wrote:
>
> On Wed, Jun 02, 2021 at 10:47:46AM +1000, Chris Angelico wrote:
>
> > I can understand the confusion though, given that the parallel
> > constructs cited for justification are all expressions.
>
> "conditional statement, list comprehensions, dict comprehensions"
>
> Two out of three is not bad. Conditional statements are not expressions
> :-)
>

Yes but I suspect that the OP actually was thinking about the if/else
expression. Otherwise it's not much of a parallel... is it? I am
confused.

But the OP has a bit of a history of posting unrefined ideas with
sloppy justifications so we can't really read too much into it.

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/AICY7ZWQX4DEEY2NRSKA26V5E46QEUAI/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add "try: stmt except: stmt" syntax to Python

2021-06-01 Thread Steven D'Aprano
On Wed, Jun 02, 2021 at 10:47:46AM +1000, Chris Angelico wrote:

> I can understand the confusion though, given that the parallel
> constructs cited for justification are all expressions.

"conditional statement, list comprehensions, dict comprehensions"

Two out of three is not bad. Conditional statements are not expressions 
:-)



-- 
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/BVNHCH6KOI5O4TVA2EB65KHDVN7EFUHC/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add "try: stmt except: stmt" syntax to Python

2021-06-01 Thread Steven D'Aprano
Why do you want this?

Is there a shortage of newlines in your country? Maybe the Enter key is 
broken on your keyboard? *wink*

Writing a proposal without a motivation is not very likely to get very 
far. "Put the code on one line" is not an acceptable motivation; *why* 
do you want to put it on one line?

A one-line try...except is not more readable or understandable than a 
two-line version. It doesn't give us any more programming power or new 
functionality. It doesn't even help in the interactive interpreter.

Just write it on two lines. Or better still, four.

"One liners" are not Pythonic and the culture of Python programming does 
not consider it a virtue to cram as much code into one line as we can 
possibly fit.

Comprehensions were not invented so we can squeeze a for-loop into one 
line, we could already do that:

for x in items: print(x)

They were invented as an expression form of for-loops. Many 
comprehensions are written over two lines, or more.


-- 
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/NADLFTTJ7JXBOSQW47QXUETSYVB56BAH/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add "try: stmt except: stmt" syntax to Python

2021-06-01 Thread Chris Angelico
On Wed, Jun 2, 2021 at 10:40 AM Steven D'Aprano  wrote:
>
> On Tue, Jun 01, 2021 at 04:30:25PM -0400, Steele Farnsworth wrote:
>
> > This was proposed in 2014 and was rejected:
> > https://www.python.org/dev/peps/pep-0463/
>
> No, that's a proposal for a Python *expression* that can be imbedded in
> another expression.
>
> Shreyan's proposal here is just to allow fitting both the try and except
> one-line statements on the same line.

I can understand the confusion though, given that the parallel
constructs cited for justification are all expressions.

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/GIPX7C4YCCUMQVP5J3ISJ3RYMZV7FA3K/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add "try: stmt except: stmt" syntax to Python

2021-06-01 Thread Steven D'Aprano
On Tue, Jun 01, 2021 at 04:30:25PM -0400, Steele Farnsworth wrote:

> This was proposed in 2014 and was rejected:
> https://www.python.org/dev/peps/pep-0463/

No, that's a proposal for a Python *expression* that can be imbedded in 
another expression.

Shreyan's proposal here is just to allow fitting both the try and except 
one-line statements on the same line. Instead of:

try: n = len(obj)
except TypeError: n = -1

Shreyan wants to cram both statements on a single line:

try: n = len(obj); except TypeError: n = -1



-- 
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/FOLLP2EOM7PD3CRDBRF7R5U2OLUBBJ5H/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: A __decoration_call__ method for Callable objects (WAS: Decorators on variables)

2021-06-01 Thread Steven D'Aprano
On Tue, Jun 01, 2021 at 10:17:32PM +1000, Chris Angelico wrote:

> My understanding is that it would attempt to invoke
> __detonation_call__ (err, I mean, __decoration_call__, but just think
> how awesome the other would be) first, and if it can't find it, it
> falls back on regular __call__. That would parallel how most other
> things are done - repr falling back to str, iadd falling back to add,
> etc.

Sure, but the analogy is more like trying repr first to produce a 
string, and if that doesn't work, trying iter to produce a list.

Function/class decoration shares little with "variable decoration" 
except the name and (proposed) use of the @ syntax. It seems to me that 
they are only the most loosely related concepts.

Ricky's proposal to use a new dunder magnifies the differences and 
obfuscates the similarities.


> That said, I still don't like the idea of decorating a bare name. A
> magic "assignment target" token that translates into the string form
> of the thing being assigned to is far more useful and far less
> magical.

Obviously I agree, given that I proposed a special @@ symbol to do that  
however Stéfane's real-world example of chaining variable decorators has 
forced me to take that idea seriously.

@acl(READ, WRITE)
@constraint(10 < _ < 100)
@not_null
@indexed
@depends_on(whatever)
@inject
@...
first_name: str


https://mail.python.org/archives/list/python-ideas@python.org/message/DCKFMWRKUQ5G2GDN6Z2DLJRKQ4LDVRIQ/


-- 
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/5XQOIVW7XYT7QLHSC5BWW3LJ4GIPEWHX/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add "try: stmt except: stmt" syntax to Python

2021-06-01 Thread Steele Farnsworth
This was proposed in 2014 and was rejected:
https://www.python.org/dev/peps/pep-0463/

That being said, I would support such a thing being added to the language.
My preferred syntax would be `try expression except ExceptionType [as e]
with alternative`, or even `expression except ExceptionType [as e] with
alternative`.

Steele

On Tue, Jun 1, 2021 at 4:11 PM Shreyan Avigyan <
shreyan.avigya...@outlook.com> wrote:

> Python has support for conditional statement, list comprehensions, dict
> comprehensions, etc. So we can write these in mere one or two lines. But
> for try-except it's not possible to write it one or two lines. Many a
> times, we have one stmt that we want to check and if it raises error then
> do nothing or just execute one stmt. This idea proposes to add a way to
> write try-except for one stmt in one line.
>
> Thanking you,
>
> With Regards
> ___
> 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/T7UKDECCKNXPWIJ6VLCDGAVSXRJQVZ7W/
> 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/DK45GOPP2BJEGQQWS63O6EKIQITEPDZM/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Add "try: stmt except: stmt" syntax to Python

2021-06-01 Thread Shreyan Avigyan
Python has support for conditional statement, list comprehensions, dict 
comprehensions, etc. So we can write these in mere one or two lines. But for 
try-except it's not possible to write it one or two lines. Many a times, we 
have one stmt that we want to check and if it raises error then do nothing or 
just execute one stmt. This idea proposes to add a way to write try-except for 
one stmt in one line.

Thanking you,

With Regards
___
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/T7UKDECCKNXPWIJ6VLCDGAVSXRJQVZ7W/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: The name Ellipsis should be a constant

2021-06-01 Thread Christopher Barker
One other note that I'm surprised hasn't been brought up:

In another thread, there is a discussion about what to use as
sentinel objects -- often to indicate non-specified parameters, when None
is a valid value.

A number of people have proposed using the ellipses as such a value, as it
already exists, is built in, is a singleton, has only specialized uses at
the moment in different contexts, and is a good mnemonic for "missing".

Apparently a number of people already use it that way.

If Ellipses that does become a standard recommend sentinel object -- that
might be a motivator for making it a special word, like None.

However, I"m still a bit confused as to why the rep of the ellipses object
isn't it's literal already. Is there any other example of this?

In [1]: repr(list())
Out[1]: '[]'

In [2]: repr(dict())
Out[2]: '{}'

Hmm -- there is set:

In [3]: repr(set())
Out[3]: 'set()'

which breaks eval if you rebind it.

Though it doesn't use the name if it's not empty:

In [16]: s = {1,2,3}

In [17]: repr(s)
Out[17]: '{1, 2, 3}'

In the end, I think this is an argument for not using ellipses as a
standard sentinel, rather than an argument for making "Ellipses" more
special.

-CHB



On Tue, Jun 1, 2021 at 4:33 AM Steven D'Aprano  wrote:

> On Tue, Jun 01, 2021 at 08:28:56PM +1000, Steven D'Aprano wrote:
>
> > One easy change would be to just drop the capital E and call it
> > "ellipsis" (without the quotes), or even "the ellipsis symbol". To my
> > mind, that makes it clear we're talking about the symbol, not the
> > builtin name.
>
> https://bugs.python.org/issue44278
>
> Thanks Serhiy!
>
> --
> 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/MRCYKQODI2FYG6AYFRBS3PBMQCBWRONL/
> Code of Conduct: http://python.org/psf/codeofconduct/
>


-- 
Christopher Barker, PhD (Chris)

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython
___
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/FCCS3UYIIGBEXAVGWNQNUM7LRLK3ZAUH/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: A __decoration_call__ method for Callable objects (WAS: Decorators on variables)

2021-06-01 Thread Paul Moore
On Tue, 1 Jun 2021 at 13:16, Steven D'Aprano  wrote:

> We can distinguish the two contexts by using different signatures. The
> signature used depends entirely on the call site, not the decorator, so
> it is easy for the interpreter to deal with.
>
> If the decorator is called on a function or class statement, a single
> argument is always passed, no exceptions:
>
> # always calls decorate with one argument
> @decorate
> def func():  # or class
> pass
>
> # --> func = decorate(func)
>
> If called on a variable, the number of arguments depends on whether it
> is a bare name, or a value and annotation are provided. There are
> exactly four cases:
>
> # bare name
> @decorate
> var
> # --> var = decorate('var')
>
> # name with annotation
> @decorate
> var: annot
> # --> var = decorate('var', annotation=annot)
>
> # name bound to value
> @decorate
> var = x
> # --> var = decorate('var', value=x)
>
> # name with annotation and value
> @decorate
> var: annot = x
> # --> var = decorate('var', annotation=annot, value=x)
>
>
> Keyword arguments are used because one or both of the value and the
> annotation may be completely missing. The decorator can either provide
> default values or collect keyword arguments with `**kwargs`.

I've yet to be convinced that variable annotations are sufficiently
useful to be worth all of this complexity (and by "this" I mean any of
the proposals being made I'm not singling out Steven's suggestion
here).

But if we do need this, I quite like the idea of making the
distinction based on signature.

> The only slightly awkward case is the bare variable case. Most of the
> time there will be no overlap between the function/class decorators and
> the bare variable decorator, but in the rare case that we need to use a
> single function in both cases, we can easily distinguish the two cases:
>
> def mydecorator(arg, **kwargs):
> if isinstance(arg, str):
> # must be decorating a variable
> ...
> else:
> # decorating a function or class
> assert kwarg == {}
>
> So it is easy to handle both uses in a single function, but I emphasise
> that this would be rare. Normally a single decorator would be used in
> the function/class case, or the variable case, but not both.

You don't need to do this. Just add another keyword argument "name":

# bare name
@decorate
var
# --> var = decorate(name='var')

# name with annotation
@decorate
var: annot
# --> var = decorate(name='var', annotation=annot)

# name bound to value
@decorate
var = x
# --> var = decorate(name='var', value=x)

# name with annotation and value
@decorate
var: annot = x
# --> var = decorate(name='var', annotation=annot, value=x)

The single positional argument is reserved for function/class
annotations, and will always be None for variable annotations.

Paul
___
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/NJTZRP64SBWP5SJMKAGPNAYJ7MK6IKQO/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] channel or message queue in asyncio

2021-06-01 Thread zhongquan789
Functionalities are similar to Go channel but with topics or consumers like a 
message queue.

Possible syntax:

```python
async def main():
ch = Channel()
await ch.put(1)   # put
await ch.get() # get
await ch.close()  # close
c1 = ch.consumer()
c2 = ch.consumer()
async for data in c1:   # two consumer are indpendent
  ...
async for data in c2:   # async for syntax
  ...
```

Related project:
https://github.com/Drakkar-Software/Async-Channel
https://github.com/tbug/aiochannel
https://github.com/ebb29c/asyncio-channel
https://github.com/navytux/pygolang

Though it can be implemented by using asyncio.Queue,If this can be added into 
the asyncio library?
___
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/ZJOHPP4XNPLNMKPDB2COJ7XHNT755LOW/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: A __decoration_call__ method for Callable objects (WAS: Decorators on variables)

2021-06-01 Thread Chris Angelico
On Tue, Jun 1, 2021 at 10:16 PM Steven D'Aprano  wrote:
> The only slightly awkward case is the bare variable case. Most of the
> time there will be no overlap between the function/class decorators and
> the bare variable decorator, but in the rare case that we need to use a
> single function in both cases, we can easily distinguish the two cases:
>
> def mydecorator(arg, **kwargs):
> if isinstance(arg, str):
> # must be decorating a variable
> ...
> else:
> # decorating a function or class
> assert kwarg == {}
>
> So it is easy to handle both uses in a single function, but I emphasise
> that this would be rare. Normally a single decorator would be used in
> the function/class case, or the variable case, but not both.
>

I can't imagine any situation where you would *want* this, but it is
actually possible for a decorator to be given a string:

>>> def mydecorator(arg, **kwargs):
... if isinstance(arg, str):
... print("Decorating a variable can't happen, right?")
... else:
... print("Good, we're decorating a function.")
... return arg
...
>>> @mydecorator
... @str
... def f(): ...
...
Decorating a variable can't happen, right?
>>>

This probably falls under "you shot yourself in the foot, so now you
have a foot with a hole in it".

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/YAQENPUEEOQGPUUHG6ST3L4IEXOQM4X4/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: A __decoration_call__ method for Callable objects (WAS: Decorators on variables)

2021-06-01 Thread Chris Angelico
On Tue, Jun 1, 2021 at 9:57 PM Steven D'Aprano  wrote:
>
> On Thu, May 27, 2021 at 12:33:20PM -0400, Ricky Teachey wrote:
>
> > On Thu, May 27, 2021 at 10:25 AM Steven D'Aprano 
> > wrote:
> > >
> > > Okay. Without reading the source code, does this code snippet use the
> > > old `__call__` protocol or the new `__decoration_call__` protocol?
> > >
> > >
> > > @flambé
> > > class Banana_Surprise:
> > > pass
> > >
> >
> > Invoking @flambé causes:
> >
> > flambé.__decoration_call__(Banana_Surprise, "Banana_Surprise")
> >
> > ...to be used, if flambé has that method.
>
> Right: you can't tell from the code you are looking at whether flambé is
> being called as a new or old style decorator. You have to dig into the
> definition of flambé to work out the meaning of the code.
>
> On the one hand we have the current decorator protocol, where the object
> flambé is called with a single argument, the class Banana_Surprise.

My understanding is that it would attempt to invoke
__detonation_call__ (err, I mean, __decoration_call__, but just think
how awesome the other would be) first, and if it can't find it, it
falls back on regular __call__. That would parallel how most other
things are done - repr falling back to str, iadd falling back to add,
etc.

That said, I still don't like the idea of decorating a bare name. A
magic "assignment target" token that translates into the string form
of the thing being assigned to is far more useful and far less
magical.

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/NN5BVKDUHPXJCHGGM7OFTFJHEVE3GDBZ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: A __decoration_call__ method for Callable objects (WAS: Decorators on variables)

2021-06-01 Thread Steven D'Aprano
Another problem I have with this proposal is the new dunder method. Why 
do we need a new dunder? We're probably never going to "decorate" a 
variable and function with the same callable, the two use-cases are very 
different. But even if we do, we can easily distinguish the two cases.

Let's dump the `__decorate_call__` dunder and just use normal call 
syntax. That will be a HUGE win for useability: any function, class or 
callable object can be used as the decorator, it doesn't have to be a 
custom object with a custom class that defines a special dunder.

We can distinguish the two contexts by using different signatures. The 
signature used depends entirely on the call site, not the decorator, so 
it is easy for the interpreter to deal with.

If the decorator is called on a function or class statement, a single 
argument is always passed, no exceptions:

# always calls decorate with one argument
@decorate
def func():  # or class
pass

# --> func = decorate(func)

If called on a variable, the number of arguments depends on whether it 
is a bare name, or a value and annotation are provided. There are 
exactly four cases:

# bare name
@decorate
var
# --> var = decorate('var')

# name with annotation
@decorate
var: annot
# --> var = decorate('var', annotation=annot)

# name bound to value
@decorate
var = x
# --> var = decorate('var', value=x)

# name with annotation and value
@decorate
var: annot = x
# --> var = decorate('var', annotation=annot, value=x)


Keyword arguments are used because one or both of the value and the 
annotation may be completely missing. The decorator can either provide 
default values or collect keyword arguments with `**kwargs`.

The only slightly awkward case is the bare variable case. Most of the 
time there will be no overlap between the function/class decorators and 
the bare variable decorator, but in the rare case that we need to use a 
single function in both cases, we can easily distinguish the two cases:

def mydecorator(arg, **kwargs):
if isinstance(arg, str):
# must be decorating a variable
...
else:
# decorating a function or class
assert kwarg == {}

So it is easy to handle both uses in a single function, but I emphasise 
that this would be rare. Normally a single decorator would be used in 
the function/class case, or the variable case, but not both.


-- 
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/3VAC7Y6DYL77EPB6X6XS3AGIAZX22MOG/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: A __decoration_call__ method for Callable objects (WAS: Decorators on variables)

2021-06-01 Thread Steven D'Aprano
On Thu, May 27, 2021 at 12:33:20PM -0400, Ricky Teachey wrote:

> On Thu, May 27, 2021 at 10:25 AM Steven D'Aprano 
> wrote:
> >
> > Okay. Without reading the source code, does this code snippet use the
> > old `__call__` protocol or the new `__decoration_call__` protocol?
> >
> >
> > @flambé
> > class Banana_Surprise:
> > pass
> >
> 
> Invoking @flambé causes:
> 
> flambé.__decoration_call__(Banana_Surprise, "Banana_Surprise")
> 
> ...to be used, if flambé has that method.

Right: you can't tell from the code you are looking at whether flambé is 
being called as a new or old style decorator. You have to dig into the 
definition of flambé to work out the meaning of the code.

On the one hand we have the current decorator protocol, where the object 
flambé is called with a single argument, the class Banana_Surprise.

I can only think of three cases where something similar occurs, but the 
differences are critical.

- Binary operators can call either or both of two reflected dunders,
  such as `__add__` and `__radd__`.

- Iteration normally calls `__next__`, but it can fall back on 
  the old sequence protocol that relies on `__getitem__`.

- Augmented assignment calls the augmented assignment method, such
  as `__iadd__`, but may fall back on the regular `+` operator.

In all of these cases, the intended semantics are the same and the 
arguments passed are (almost) the same. E.g. normally we would use the 
same signatures for each of the operators:

def __add__(self, other): ...
def __radd__(self, other): ...
def __iadd__(self, other): ... 

and if fact for many purposes, add and radd will be the same function 
object.

The old sequence protocol is a minor exception, because `__getitem__` 
requires an argument (it is called with 0, 1, 2, 3, ... until IndexError 
occurs). But that's almost an implementation detail. The fact that 
`__next__` takes no explicit enumeration, but `__getitem__` does, can be 
ignored when we think about the high-level concept of iteration.

Conceptionally, at a high-level, the sequence and iterator protocols 
operate the same way:

call the dunder repeatedly until an exception occurs

and the details of which dunder and which exception don't matter. 
Iteration is iteration.

But here, the details *do* matter. Old classic decorators and this 
proposed new decorator syntax do not share a high-level concept. There 
is a certain relationship in the sense that both the new and old 
protocols involve calling a function, but the details are very 
different:

- old decorator protocol is a normal function call with a single 
  argument;

- new protocol uses a different method, with two arguments, 
  one of which is implicit.

Old decorator protocol is about *decorating* a function or class object 
with new functionality (wrapping it in a wrapper function, say, or 
modifying it in place).

New decorator protocol and variable decoration doesn't decorate 
anything: there's nothing to decorate when used with a bare name:

@decorate
var

which presumably evaluates to:

var = decorate.__decorate_call__('var')

So we're not decorating an object. There's no object to decorate!

With a binding:

@decorate
var = expression

var = decorate.__decorate_call__('var', expression)

Again, conceptually we're not decorating anything. We're just reusing 
the `@` syntax for something that is not conceptually related to old 
style decorators. This is just a syntax for *implicitly* getting access 
to the left hand side assignment target name as a string.

[...]
> > I just don't know whether or not the decorator `flambé` receives the
> > name or not.
> >
> 
> If you wrote the decorator, you know.
> 
> If you didn't, why does it matter if it is being passed? Why do you need to
> know that?

Because I don't know the meaning of the code. Am I decorating an object 
or doing something with the target name? I can't interpret the code 
until I know what protocol was supported by the decorator object.

Let me give you an analogy: the `with` statement has a context manager 
protocol that uses an `__enter__` and `__exit__` pair of methods. With 
statements are awesome! They're so awesome that we should use the 
exact same "with" syntax for Pascal-style implicit attribute access, 
using a different protocol.

https://docs.python.org/3/faq/design.html#why-doesn-t-python-have-a-with-statement-for-attribute-assignments


with myobject:
do_something()

with myotherobj:
do_something()


There is no visible difference between the two pieces of code, 
but one is an old style enter/exit context manager, the other is our 
hypothetical new style with syntax that does something completely 
different and calls different dunder methods.

One of them is calling the global do_something and one is calling the 
object's do_something method. Which is which?

Code that is different should look different.


-- 
Steve
___

[Python-ideas] Re: The name Ellipsis should be a constant

2021-06-01 Thread Steven D'Aprano
On Tue, Jun 01, 2021 at 08:28:56PM +1000, Steven D'Aprano wrote:

> One easy change would be to just drop the capital E and call it 
> "ellipsis" (without the quotes), or even "the ellipsis symbol". To my 
> mind, that makes it clear we're talking about the symbol, not the 
> builtin name.

https://bugs.python.org/issue44278

Thanks Serhiy!

-- 
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/MRCYKQODI2FYG6AYFRBS3PBMQCBWRONL/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: symbolic math in Python

2021-06-01 Thread Neil Girdhar
Oh, and I see you're a sympy developer!  I hope I'm not coming across
as critical in any way.  I love that sympy exists and thought it was a
really cool project when I first learned about what it can do.

Perhaps we should move our discussion to a "Github discussion" under
the sympy Github?

We might be able to build a toy example that takes functions, inspects
the signature, and converts it into a traditional sympy expression.
Then we could examine a variety of examples in the docs to see whether
the function-based symbols are easier or harder to use in general.

Best,

Neil

On Tue, Jun 1, 2021 at 6:47 AM Neil Girdhar  wrote:
>
> On Tue, Jun 1, 2021 at 6:28 AM Oscar Benjamin
>  wrote:
> >
> > On Tue, 1 Jun 2021 at 10:53, Neil Girdhar  wrote:
> > >
> > > On Tue, Jun 1, 2021 at 5:39 AM Oscar Benjamin
> > >  wrote:
> > > >
> > > > On Tue, 1 Jun 2021 at 05:16, Neil Girdhar  wrote:
> > > > >
> > > > > Hi Oscar,
> > > > >
> > > > > The problem that the original poster was trying to address with
> > > > > additional syntax is the automatic naming of symbols.  He wants to
> > > > > omit this line:
> > > > >
> > > > > x = symbols("x")
> > > > >
> > > > > You're right that if you have many one-character symbol names, you can
> > > > > use a shortcut, but this benefit is lost if you want descriptive names
> > > > > like:
> > > > >
> > > > > momentum = symbols('momentum')
> > > > >
> > > > > He is proposing new syntax to eliminate the repeated name.  The
> > > > > function approach specifies each name exactly once.  This is one of
> > > > > the benefits of JAX over TensorFLow.
> > > > >
> > > > > Second, the function approach allows the function to be a single
> > > > > object that can be used in calcuations.   You might ask for:
> > > > >
> > > > > grad(equation, 2)(2, 3, 4 5)  # derivative with respect to parameter 2
> > > > > of equation evaluated at (2, 3, 4, 5)
> > > > >
> > > > > With the symbolic approach, you need to keep the equation object as
> > > > > well as the symbols that compose it to interact with it.
> > > >
> > > > This makes more sense in a limited context for symbolic manipulation
> > > > where symbols only represent function parameters so that all symbols
> > > > are bound. How would you handle the situation where the same symbols
> > > > are free in two different expressions that you want to manipulate in
> > > > tandem though?
> > > >
> > > > In this example we have two different equations containing the same
> > > > symbols and we want to solve them as a system of equations:
> > > >
> > > > p, m, h = symbols('p, m, h')
> > > > E = p**2 / 2*m
> > > > lamda = h / p
> > > >
> > > > E1 = 5
> > > > lamda1 = 2
> > > > [(p1, m1)] = solve([Eq(E, E1), Eq(lamda, lamda1)], [p, m])
> > > >
> > > > I don't see a good way of doing this without keeping track of the
> > > > symbols as separate objects. I don't think this kind of thing comes up
> > > > in Jax because it is only designed for the more limited symbolic task
> > > > of evaluating and differentiating Python functions.
> > >
> > > This is a really cool design question.
> > >
> > > One of the things I like about JAX is that they stayed extremely close
> > > to NumPy's interface.  In NumPy, comparison operators applied to
> > > matrices return Boolean matrices.
> > >
> > > I would ideally express what you wrote as
> > >
> > > def E(p, m): ...
> > >
> > > def lamda(h, p): ...
> > >
> > > def f(p, m):
> > > return jnp.all(E(p, m) == E1) and jnp.all(lamda(h, p) == lamda1)
> > >
> > > p1, m1 = solve(f)
> >
> > So how does solve know to solve for p and m rather than h?
>
> Because those are the parameters of f.
> >
> > Note that I deliberately included a third symbol and made the
> > parameter lists of E and lamda inconsistent.
> >
> > Should Jax recognise that the 2nd parameter of lamda has the same name
> > as the 1st parameter of E? Or should symbols at the same parameter
> > index be considered the same regardless of their name?
>
> It doesn't need to because the same variable p (which will ultimately
> point to a tracer object) is passed to the functions E and lamda.
> It's not using the names.
> >
> > In Jax everything is a function so I would expect it to ignore the
> > symbol names so that if
> > args = solve([f1, f2])
> > then f1(*args) == f2(*args) == 0.
> >
> > This is usually how the API works for numerical rather than symbolic
> > root-finding algorithms. But then how do I solve a system of equations
> > that has a symbolic parameter like `h`?
>
> I assumed that h was a constant and was being closed over by f.  If h
> is a symbol, I think to stay consistent with functions creating
> symbols, we could do:
>
>
> def f(p, m, h):
> return E(p, m) == E1 and lamda(h, p) == lamda1
>
> def g(h):
> return solve(partial(f, h=h))
>
> g is now a symbolic equation that returns p, m in terms of h.
>
> By the way, it occured to me that it might be reasonable to build a
> system like this fairly quickly using sympy as a backend.
>
> 

[Python-ideas] Re: The name Ellipsis should be a constant

2021-06-01 Thread Jonathan Fine
We have the following.

>>> 12 = True
SyntaxError: can't assign to literal

>>> True = False
SyntaxError: can't assign to keyword

>>> ... = False
SyntaxError: can't assign to Ellipsis

We also have (works better in monospaced font)

>>> d[] = True
d[] = True
  ^
SyntaxError: invalid syntax

Beginners might appreciate having instead as error messages:

SyntaxError: can't assign to literal: 12
SyntaxError: can't assign to keyword: True
SyntaxError: can't assign to literal: ...

-- 
Jonathan
___
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/4SHBUENP7TAMXZVN6VK26I6MXWXFBKJM/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: symbolic math in Python

2021-06-01 Thread Neil Girdhar
On Tue, Jun 1, 2021 at 6:28 AM Oscar Benjamin
 wrote:
>
> On Tue, 1 Jun 2021 at 10:53, Neil Girdhar  wrote:
> >
> > On Tue, Jun 1, 2021 at 5:39 AM Oscar Benjamin
> >  wrote:
> > >
> > > On Tue, 1 Jun 2021 at 05:16, Neil Girdhar  wrote:
> > > >
> > > > Hi Oscar,
> > > >
> > > > The problem that the original poster was trying to address with
> > > > additional syntax is the automatic naming of symbols.  He wants to
> > > > omit this line:
> > > >
> > > > x = symbols("x")
> > > >
> > > > You're right that if you have many one-character symbol names, you can
> > > > use a shortcut, but this benefit is lost if you want descriptive names
> > > > like:
> > > >
> > > > momentum = symbols('momentum')
> > > >
> > > > He is proposing new syntax to eliminate the repeated name.  The
> > > > function approach specifies each name exactly once.  This is one of
> > > > the benefits of JAX over TensorFLow.
> > > >
> > > > Second, the function approach allows the function to be a single
> > > > object that can be used in calcuations.   You might ask for:
> > > >
> > > > grad(equation, 2)(2, 3, 4 5)  # derivative with respect to parameter 2
> > > > of equation evaluated at (2, 3, 4, 5)
> > > >
> > > > With the symbolic approach, you need to keep the equation object as
> > > > well as the symbols that compose it to interact with it.
> > >
> > > This makes more sense in a limited context for symbolic manipulation
> > > where symbols only represent function parameters so that all symbols
> > > are bound. How would you handle the situation where the same symbols
> > > are free in two different expressions that you want to manipulate in
> > > tandem though?
> > >
> > > In this example we have two different equations containing the same
> > > symbols and we want to solve them as a system of equations:
> > >
> > > p, m, h = symbols('p, m, h')
> > > E = p**2 / 2*m
> > > lamda = h / p
> > >
> > > E1 = 5
> > > lamda1 = 2
> > > [(p1, m1)] = solve([Eq(E, E1), Eq(lamda, lamda1)], [p, m])
> > >
> > > I don't see a good way of doing this without keeping track of the
> > > symbols as separate objects. I don't think this kind of thing comes up
> > > in Jax because it is only designed for the more limited symbolic task
> > > of evaluating and differentiating Python functions.
> >
> > This is a really cool design question.
> >
> > One of the things I like about JAX is that they stayed extremely close
> > to NumPy's interface.  In NumPy, comparison operators applied to
> > matrices return Boolean matrices.
> >
> > I would ideally express what you wrote as
> >
> > def E(p, m): ...
> >
> > def lamda(h, p): ...
> >
> > def f(p, m):
> > return jnp.all(E(p, m) == E1) and jnp.all(lamda(h, p) == lamda1)
> >
> > p1, m1 = solve(f)
>
> So how does solve know to solve for p and m rather than h?

Because those are the parameters of f.
>
> Note that I deliberately included a third symbol and made the
> parameter lists of E and lamda inconsistent.
>
> Should Jax recognise that the 2nd parameter of lamda has the same name
> as the 1st parameter of E? Or should symbols at the same parameter
> index be considered the same regardless of their name?

It doesn't need to because the same variable p (which will ultimately
point to a tracer object) is passed to the functions E and lamda.
It's not using the names.
>
> In Jax everything is a function so I would expect it to ignore the
> symbol names so that if
> args = solve([f1, f2])
> then f1(*args) == f2(*args) == 0.
>
> This is usually how the API works for numerical rather than symbolic
> root-finding algorithms. But then how do I solve a system of equations
> that has a symbolic parameter like `h`?

I assumed that h was a constant and was being closed over by f.  If h
is a symbol, I think to stay consistent with functions creating
symbols, we could do:


def f(p, m, h):
return E(p, m) == E1 and lamda(h, p) == lamda1

def g(h):
return solve(partial(f, h=h))

g is now a symbolic equation that returns p, m in terms of h.

By the way, it occured to me that it might be reasonable to build a
system like this fairly quickly using sympy as a backend.

Although, there are some other benefits of Jax's symbolic
expression-builder that might be a lot harder to capture: Last time I
used sympy though (years ago), I had a really hard time making
matrices of symbols, and there were some incongruities between numpy
and sympy functions.

Best,

Neil
>
> --
> Oscar
___
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/AN37BNIJQNVFEW27CQ5T5RJJHKGLCD3H/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: symbolic math in Python

2021-06-01 Thread Oscar Benjamin
On Tue, 1 Jun 2021 at 10:53, Neil Girdhar  wrote:
>
> On Tue, Jun 1, 2021 at 5:39 AM Oscar Benjamin
>  wrote:
> >
> > On Tue, 1 Jun 2021 at 05:16, Neil Girdhar  wrote:
> > >
> > > Hi Oscar,
> > >
> > > The problem that the original poster was trying to address with
> > > additional syntax is the automatic naming of symbols.  He wants to
> > > omit this line:
> > >
> > > x = symbols("x")
> > >
> > > You're right that if you have many one-character symbol names, you can
> > > use a shortcut, but this benefit is lost if you want descriptive names
> > > like:
> > >
> > > momentum = symbols('momentum')
> > >
> > > He is proposing new syntax to eliminate the repeated name.  The
> > > function approach specifies each name exactly once.  This is one of
> > > the benefits of JAX over TensorFLow.
> > >
> > > Second, the function approach allows the function to be a single
> > > object that can be used in calcuations.   You might ask for:
> > >
> > > grad(equation, 2)(2, 3, 4 5)  # derivative with respect to parameter 2
> > > of equation evaluated at (2, 3, 4, 5)
> > >
> > > With the symbolic approach, you need to keep the equation object as
> > > well as the symbols that compose it to interact with it.
> >
> > This makes more sense in a limited context for symbolic manipulation
> > where symbols only represent function parameters so that all symbols
> > are bound. How would you handle the situation where the same symbols
> > are free in two different expressions that you want to manipulate in
> > tandem though?
> >
> > In this example we have two different equations containing the same
> > symbols and we want to solve them as a system of equations:
> >
> > p, m, h = symbols('p, m, h')
> > E = p**2 / 2*m
> > lamda = h / p
> >
> > E1 = 5
> > lamda1 = 2
> > [(p1, m1)] = solve([Eq(E, E1), Eq(lamda, lamda1)], [p, m])
> >
> > I don't see a good way of doing this without keeping track of the
> > symbols as separate objects. I don't think this kind of thing comes up
> > in Jax because it is only designed for the more limited symbolic task
> > of evaluating and differentiating Python functions.
>
> This is a really cool design question.
>
> One of the things I like about JAX is that they stayed extremely close
> to NumPy's interface.  In NumPy, comparison operators applied to
> matrices return Boolean matrices.
>
> I would ideally express what you wrote as
>
> def E(p, m): ...
>
> def lamda(h, p): ...
>
> def f(p, m):
> return jnp.all(E(p, m) == E1) and jnp.all(lamda(h, p) == lamda1)
>
> p1, m1 = solve(f)

So how does solve know to solve for p and m rather than h?

Note that I deliberately included a third symbol and made the
parameter lists of E and lamda inconsistent.

Should Jax recognise that the 2nd parameter of lamda has the same name
as the 1st parameter of E? Or should symbols at the same parameter
index be considered the same regardless of their name?

In Jax everything is a function so I would expect it to ignore the
symbol names so that if
args = solve([f1, f2])
then f1(*args) == f2(*args) == 0.

This is usually how the API works for numerical rather than symbolic
root-finding algorithms. But then how do I solve a system of equations
that has a symbolic parameter like `h`?

--
Oscar
___
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/EIJSNETBN7H4TVK3DYW6UN4ULBBVX44X/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: The name Ellipsis should be a constant

2021-06-01 Thread Steven D'Aprano
On Tue, Jun 01, 2021 at 05:48:34AM -0300, André Roberge wrote:

> Actually, the very first observation I made is that, if you try to assign a
> value to '...', the traceback includes the message:
> 
> SyntaxError: cannot assign to Ellipsis
> 
> which is clearly wrong.

It is not _clearly_ wrong. Ellipsis is the name of the `...` symbol. 
Regardless of the state of the built-in name Ellipsis, whether it has 
been shadowed or monkey-patched, the symbol is still called Ellipsis. 
You would have to grossly misread or misinterpret the traceback:

  ... = 42
  ^
SyntaxError: cannot assign to Ellipsis

as referring to the *name* Ellipsis rather than the symbol as shown. So 
I would say its not wrong at all: it is technically and pedantically 
correct, which is the best kind of correct.

So it is not *wrong*, but it does require a moderately subtle 
understanding of Python symbols, names, and values (objects).

One easy change would be to just drop the capital E and call it 
"ellipsis" (without the quotes), or even "the ellipsis symbol". To my 
mind, that makes it clear we're talking about the symbol, not the 
builtin name.

I dislike these:

SyntaxError: cannot assign to '...'
SyntaxError: cannot assign to ...

I'm not assigning to the string '...'; the second one looks like the 
error message has been partially elided. So both are just as problematic 
as the error message we are trying to improve.


[...]
> the only inconsistency left would be a more minor one, that is of the repr
> of '...' stating that it is Ellipsis which can be incorrect if Ellipsis is
> bound to a different value.

And that I don't think we should bother changing. It is completely 
normal for the names of certain classes, functions and other values to 
refer to the original name rather than the shadowing name. Ellipsis is 
just another one of them.


-- 
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/MSWOPKBRPALBPNCJ76MVPEIYJG6AXPJC/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: symbolic math in Python

2021-06-01 Thread Neil Girdhar
On Tue, Jun 1, 2021 at 5:39 AM Oscar Benjamin
 wrote:
>
> On Tue, 1 Jun 2021 at 05:16, Neil Girdhar  wrote:
> >
> > Hi Oscar,
> >
> > The problem that the original poster was trying to address with
> > additional syntax is the automatic naming of symbols.  He wants to
> > omit this line:
> >
> > x = symbols("x")
> >
> > You're right that if you have many one-character symbol names, you can
> > use a shortcut, but this benefit is lost if you want descriptive names
> > like:
> >
> > momentum = symbols('momentum')
> >
> > He is proposing new syntax to eliminate the repeated name.  The
> > function approach specifies each name exactly once.  This is one of
> > the benefits of JAX over TensorFLow.
> >
> > Second, the function approach allows the function to be a single
> > object that can be used in calcuations.   You might ask for:
> >
> > grad(equation, 2)(2, 3, 4 5)  # derivative with respect to parameter 2
> > of equation evaluated at (2, 3, 4, 5)
> >
> > With the symbolic approach, you need to keep the equation object as
> > well as the symbols that compose it to interact with it.
>
> This makes more sense in a limited context for symbolic manipulation
> where symbols only represent function parameters so that all symbols
> are bound. How would you handle the situation where the same symbols
> are free in two different expressions that you want to manipulate in
> tandem though?
>
> In this example we have two different equations containing the same
> symbols and we want to solve them as a system of equations:
>
> p, m, h = symbols('p, m, h')
> E = p**2 / 2*m
> lamda = h / p
>
> E1 = 5
> lamda1 = 2
> [(p1, m1)] = solve([Eq(E, E1), Eq(lamda, lamda1)], [p, m])
>
> I don't see a good way of doing this without keeping track of the
> symbols as separate objects. I don't think this kind of thing comes up
> in Jax because it is only designed for the more limited symbolic task
> of evaluating and differentiating Python functions.

This is a really cool design question.

One of the things I like about JAX is that they stayed extremely close
to NumPy's interface.  In NumPy, comparison operators applied to
matrices return Boolean matrices.

I would ideally express what you wrote as

def E(p, m): ...

def lamda(h, p): ...

def f(p, m):
return jnp.all(E(p, m) == E1) and jnp.all(lamda(h, p) == lamda1)

p1, m1 = solve(f)

>
> Also for simple expressions like this I think that a decorated
> function seems quite cumbersome:
>
> @symbolic
> def E(p, m):
> return p**2 / (2*m)
>
> @symbolic
> def lamda(h, p):
> return h / p

I guess we don't need the decorator unless we want to memoize some
results.  JAX uses a decorator to memoize the jitted code, for
example.  I thought it might be nice for example to memoize the parse
tree so that the function doesn't have to be called every time it's
used.
>
> > Finally, the function can just be called with concrete values:
> >
> > equation(2, 3, 4, 5)  # gives 25
> >
> > which is convenient.
>
> That is convenient but I think again this only really makes sense if
> all of your expressions are really just functions and all of your
> symbols are bound symbols representing function parameters. It is
> possible in sympy to convert an expression into a function but you
> need to specify the ordering of the symbols as function parameters:
>
> expression = p**2 / (2*m)
> function = lambdify([p, m], expression)
> function(1, 2)  # 0.25
>
> The need to specify the ordering comes from the fact that the
> expression itself is not conceptually a function and does not have an
> ordered parameter list.

Right.  I think it's simpler to just specify symbolic functions as
Python functions, but I can see why that does make the very simplest
cases slightly more wordy.

>
> --
> Oscar
___
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/Z6C5HVMJMDG7EMGHVRFPWPPL5KNZ2Y5K/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: symbolic math in Python

2021-06-01 Thread Oscar Benjamin
On Tue, 1 Jun 2021 at 05:16, Neil Girdhar  wrote:
>
> Hi Oscar,
>
> The problem that the original poster was trying to address with
> additional syntax is the automatic naming of symbols.  He wants to
> omit this line:
>
> x = symbols("x")
>
> You're right that if you have many one-character symbol names, you can
> use a shortcut, but this benefit is lost if you want descriptive names
> like:
>
> momentum = symbols('momentum')
>
> He is proposing new syntax to eliminate the repeated name.  The
> function approach specifies each name exactly once.  This is one of
> the benefits of JAX over TensorFLow.
>
> Second, the function approach allows the function to be a single
> object that can be used in calcuations.   You might ask for:
>
> grad(equation, 2)(2, 3, 4 5)  # derivative with respect to parameter 2
> of equation evaluated at (2, 3, 4, 5)
>
> With the symbolic approach, you need to keep the equation object as
> well as the symbols that compose it to interact with it.

This makes more sense in a limited context for symbolic manipulation
where symbols only represent function parameters so that all symbols
are bound. How would you handle the situation where the same symbols
are free in two different expressions that you want to manipulate in
tandem though?

In this example we have two different equations containing the same
symbols and we want to solve them as a system of equations:

p, m, h = symbols('p, m, h')
E = p**2 / 2*m
lamda = h / p

E1 = 5
lamda1 = 2
[(p1, m1)] = solve([Eq(E, E1), Eq(lamda, lamda1)], [p, m])

I don't see a good way of doing this without keeping track of the
symbols as separate objects. I don't think this kind of thing comes up
in Jax because it is only designed for the more limited symbolic task
of evaluating and differentiating Python functions.

Also for simple expressions like this I think that a decorated
function seems quite cumbersome:

@symbolic
def E(p, m):
return p**2 / (2*m)

@symbolic
def lamda(h, p):
return h / p

> Finally, the function can just be called with concrete values:
>
> equation(2, 3, 4, 5)  # gives 25
>
> which is convenient.

That is convenient but I think again this only really makes sense if
all of your expressions are really just functions and all of your
symbols are bound symbols representing function parameters. It is
possible in sympy to convert an expression into a function but you
need to specify the ordering of the symbols as function parameters:

expression = p**2 / (2*m)
function = lambdify([p, m], expression)
function(1, 2)  # 0.25

The need to specify the ordering comes from the fact that the
expression itself is not conceptually a function and does not have an
ordered parameter list.

--
Oscar
___
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/MHM2NZLQWPL4YCOX2KPXFWJ6CKI7MNQX/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: The name Ellipsis should be a constant

2021-06-01 Thread Serhiy Storchaka
31.05.21 22:24, André Roberge пише:
> 
> 
> On Mon, May 31, 2021 at 4:17 PM Serhiy Storchaka
>  > wrote:
> 31.05.21 17:37, André Roberge пише:
> > For consistency, `Ellipsis` (the name) should **always** refer to the
> > same object that `...` refers to, so that both could not be assigned a
> > new value.
> 
> Making Ellipsis a keyword will break ast.Ellipsis (and maybe some
> third-party libraries).
> 
> I realized that after my initial post which is why I subsequently
> suggested that its repr should perhaps be "Ellipsis (...)".

It does not help. If Ellipsis is a keyword, it is not possible to have
ast.Ellipsis. Not mentioned that it would be pretty confusing by itself
-- why you need to write Ellipsis(), but not None() or True()?

___
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/FVRCVWYYX2AHO3YLNEEEPQWKZAUDIAMX/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: The name Ellipsis should be a constant

2021-06-01 Thread André Roberge
On Tue, Jun 1, 2021 at 1:46 AM David Mertz  wrote:

> On Mon, May 31, 2021 at 11:41 PM Steven D'Aprano 
> wrote:
>
>>
>>
>
>> Not every builtin needs a mollyguard to protect against misuse.
>>
>
> I'm not likely to rebind `Ellipsis` so that's not really my concern.
> Rather, I'm interested in the point André Roberge started the thread with.
>

Actually, the very first observation I made is that, if you try to assign a
value to '...', the traceback includes the message:

SyntaxError: cannot assign to Ellipsis

which is clearly wrong. If it would state:

SyntaxError: cannot assign to '...'

the only inconsistency left would be a more minor one, that is of the repr
of '...' stating that it is Ellipsis which can be incorrect if Ellipsis is
bound to a different value.

Sorry for opening what became a rabbit hole of a discussion.

André




> The repr of '...' should be more self-explanatory to beginners.  It's
> basically co-opting the square brackets or parenthesis to mean something
> that doesn't really have anything to do with calling or indexing in order
> to have a repr—in tracebacks specifically, but elsewhere also—that reminds
> users of the connection between `...` and `Ellipsis`.
>
> --
> The dead increasingly dominate and strangle both the living and the
> not-yet born.  Vampiric capital and undead corporate persons abuse
> the lives and control the thoughts of homo faber. Ideas, once born,
> become abortifacients against new conceptions.
> ___
> 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/USE2ICT6CVRFNINM4S5O3FOWEO3ZSVUP/
> 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/YHVCJVOE4INWV5D3RIW5TM23VYLGDLND/
Code of Conduct: http://python.org/psf/codeofconduct/