Hi Tobias,
In future, could you avoid editing emails when replying to them?
A lot of context can get lost.
On 14/07/2020 5:25 pm, Tobias Kohn wrote:
Hi Mark,
Thank you for your message. I might be able to answer some of the
questions and also address some issues with the underlying assumptions
in your email---after all, we would most certainly want to avoid
discussing and reasoning about straw men, as you yourself have
repeatedly pointed out.
> Why the use of "shape" in "scare quotes"?
Because the `shape' of an object is not something that is a well-defined
term, but rather addresses the intuitive understanding to explain what
we are talking about. It is usually the intention of the abstract to
give a rough overview, before delving into the details and more formal
descriptions.
You ignore my point about explaining PEP 622 directly. Sure, the
abstract must give a high level overview, but it should be able to do
that without so much hand waving.
> Using a contrived example like this seems like a straw man. It feels
like it is constructed to favour the PEP, whilst being unlike any real code.
It is a trait of many (good) tutorials to present a new structure with
an example that highlights its feature in an approachable way rather
than coming up with `real code'---particularly given that real code is
always surrounded by a larger context, which rather clouds any
understanding. And it would only be a straw man had we constructed a
contrived example of unrealistic code that we then showed to be
simplified by pattern matching. That's not the case: it really is just
a simple educational example to present the idea.
The example given in the PEP does seems like a "contrived example of
unrealistic code", as you put it. Is there real code like this?
BTW: as a matter of course, it is constructed in favour of the PEP!
> There seem to be three things you want to enhance here:
> Unpacking; to avoid calls to `len`
> Type checking; to avoid calls to `isinstance`.
> To avoiding nesting by using complex lvalues.
Actually, no. Pattern matching is not about _avoiding_ anything, it is
about a more concise syntax. The suggestion that we wanted to avoid
calls to `len` or `isinstance` is similar to the idea of using a lambda
to avoid a function. The objective of pattern matching is to introduce
a more succinct and readable way to express structure. It's all still
there but we want to focus on the structure rather than `isinstance` calls.
I should have been clearer. Avoiding *explicit* calls to `len` and
`isinstance`. Yes, the pattern matching syntax is more concise in some
circumstances, but there still needs to be justification why a
combination of simpler language changes is insufficient.
Pattern matching already exists in some limited way in Python. Even
today you can write:
`a, b = value`
I think most of us are aware of unpacking in Python ;)
instead of:
`a = value[0]
b = value[1]`
The idea of this is, of course, not so much about avoiding item access,
but about having a more concise syntax for it. Moreover, saying this
only saves a single line and is therefore rather useless is quite beside
the point. It is about a better representation of what the code is
supposed to do and not about saving lines.
How do you quantify "better representation" then?
> Saves two lines of code, but introduces two bugs!
> (Assuming that the original behavior should be preserved)
Thank you for pointing out the bug in our example. This highlights,
however, rather the difficulty of refactoring (did I already mention the
issue of the 'context' that real code is embedded in?), than any
shortcoming of pattern matching as a tool. And by the way: constructive
critisism would perhaps include explicitly naming the two bugs.
I'm not sure it would be more constructive, this is not a bug report or
code review after all.
The point I am making is this:
It is far too easy to make mistakes using the constructs proposed in PEP
622.
> For example, by adding a simple "matches" method to Node and Leaf,
`is_tuple` can be rewritten as something like:
This assumes that you have full control over the entire code. But if
you are using some third-party library, you cannot "simply add a
`matches` method" (without some substantial trickery). Moreover, there
is quite some work needed to define such a `matches` function as you
propose it (including support for the ellipsis as wildcard). In effect,
you would have to implement large parts of the pattern matching for just
this simple example. Whereas we believe that it has merit enough to
have the compiler do it for a wide range of possible use cases.
You wouldn't have to implement large parts of the pattern matching,
because this would be specific to one class. There are only two or three
cases to deal with.
If you don't have access to the original source, then it can be made a
function, not a method.
> I really don't see you how you can claim that
> `case 406:`
> is more readable than
> `elif response == HTTP_UPGRADE_REQUIRED:`
> ?
> Preventing the use of symbolic constants or other complex rvalues is
a impairment to usability.
First, let me quote what the PEP has to say on that exact example:
> Although this will work, it's not necessarily what the proposal is
focused on.
So why does the PEP include it as one of just three examples?
Moreover, it is usually a good idea to put constants into a separate
namespace that further describes their meaning and intended use. And
that is fully supported by the syntax as proposed in the PEP.
```
match response.status:
case HTTP_RESPONSE.UPGRADE_REQUIRED:
...
```
Are you suggesting that all constants live in a separate module?
That no module can contain both constants and code?
> For a PEP to succeed it needs to show two things.
>
> 1. Exactly what problem is being solved, or need is to be fulfilled,
and that is a sufficiently large problem, or need, to merit the proposed
change.
>
> 2. That the proposed change is the best known solution for the
problem being addressed.
>
> IMO, PEP 622 fails on both counts.
This seems fair enough as far as the two issues are concerned. It might
seem indeed as if pattern matching does not add anything that could not
be done already in Python. Part of the problem is that pattern matching
starts to really shine when the objects and data get more
complex---which requires a lot of built-up and context just to get to
the point. This is similar to OOP: as long as you stick with the easy
introductory examples, OOP does not really provide anything that you
could not solve using procedural programming. For instance, I often see
critisism of Java based on some simple hello-world examples, which
completely misses the point of OOP in the first place, of course.
There are legitimate reasons to criticize OOP, especially Java.
Like when it becomes an ideal, not a tool, and we drown in
AbstractObjectFactoryManagers.
I worry that the PEP is treating pattern matching as an ideal which we
should be striving towards. That is a bad thing, IMO.
The PEP needs to convince us that it is a useful tool.
Providing compelling real world examples is necessary.
As far as referring to the best solution: may I humbly point out that
pattern matching has been around for some 40 years now and has been
adopted by an increasing number of languages lately. We put a lot of
effort into designing a version of it that fits well with Python and
covered a huge design space, while also taking all the lessons of those
who came before us to heart. This is not just a new feature we propose
on a whim.
I think we can all name program language features that have been around
for 40 years and that we definitely don't want in Python :)
Age is not always an indicator of quality.
Pattern matching is well suited to statically typed functional
languages. Python is, at its heart, a dynamically typed procedural language.
(By procedural, I mean step-by-step as opposed to functional, nothing to
do with whether it is OO or not).
In the end, pattern matching is an increasingly popular feature that
favours higher-level declarative expressiveness over spelling out all
the details of how to check the structure of data and extract
information from it.
Higher-level more declarative programming is great, but there are many
ways to do it. List comprehensions, dataclasses, and f-strings are examples.
Each of those adds a clear benefit without being overly complex.
It was also clear what code patterns they streamlined.
PEP 622 fails to make clear which code patterns it streamlines.
It definitely feels overly complex.
Think of it perhaps this way: pattern matching is
like introducing grammars and parser generators instead of writing a new
parser each time. It answers the question of: could we have something
like regular expressions for graph-like objects instead of only text...?
Objects are about encapsulation. They may be graphs internally but that
should be hidden.
Objects should be able to provide an interface without exposing their
internals, which means you can't efficiently pattern match on them.
Pattern matching is for Algebraic Data Types, not Objects.
Cheers,
Mark.
Kind regards,
Tobias
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at
https://mail.python.org/archives/list/python-dev@python.org/message/ASIZPHOEMSZH4KAZQXJYIBUL7CU752X3/
Code of Conduct: http://python.org/psf/codeofconduct/