On 19 May 2016 at 14:15, Guido van Rossum <gu...@python.org> wrote:
> The attribute idea would be similar to a duck-type check, though more
> emphasizing data attributes. It would be nice if we could write a
> match that said "if it has attributes x and y, assign those to local
> variables p and q, and ignore other attributes".
If we went down that path, then the "assign if you can, execute this
case if you succeed" options would presumably need an explicit prefix
to indicate they're not normal expressions, perhaps something like
"?=":
switch expr as arg:
case ?= (.x as p, .y as q): print('x=', p, 'y=', q)
Which would then have the further implication that it might also make
sense to support attribute unpacking as the LHS of normal assignment
statements:
(.x as p, .y as q) = expr
I think there should be different syntaxes for matching equality and
binding patterns, and definitely different syntax for singular and
plural cases.
Let's try this:
- Equality:
`case 5:`
- Conditional:
`case if predicate(obj):`
- Pattern-matching:
`case as [a, b, *_]:`
`case as Point(x, y):`
Slightly-more-explicit checks, instead of simply `case 5:`.
- `case == 5:`
- `case is _sentinel:`
- `case is None:`
- `case < 6:`
- `case in (1,2,3):`
- `case in range(2, 5):`
- `case in int:`
On Mon, May 23, 2016 at 11:45 AM, Joao S. O. Bueno
<jsb...@python.org.br> wrote:
> I still fail to see what justifies violating The One Obvious Way to Do It which uses an if/elif sequence
Honestly I'm not at all convinced either! If it was easy to do all
this with a sequence of if/elif clauses we wouldn't need it. The
problem is that there are some types of matches that aren't so easy to
write that way, e.g. combining an attempted tuple unpack with a guard,
or "instance unpack" (check whether specific attributes exist)
possibly combined with a guard. (The tricky thing is that the guard
expression often needs to reference to the result of the unpacking.)
On Mon, May 23, 2016 at 3:49 PM, Michael Selik <michae...@gmail.com> wrote:
>
>
> On Mon, May 23, 2016 at 3:58 PM Guido van Rossum <gu...@python.org> wrote:
>>
>> On Mon, May 23, 2016 at 11:45 AM, Joao S. O. Bueno
>> <jsb...@python.org.br> wrote:
>> > I still fail to see what justifies violating The One Obvious Way to Do
>> > It which uses an if/elif sequence
>>
>> Honestly I'm not at all convinced either! If it was easy to do all
>> this with a sequence of if/elif clauses we wouldn't need it. The
>> problem is that there are some types of matches that aren't so easy to
>> write that way, e.g. combining an attempted tuple unpack with a guard,
>> or "instance unpack" (check whether specific attributes exist)
>> possibly combined with a guard. (The tricky thing is that the guard
>> expression often needs to reference to the result of the unpacking.)
>
> I figure it's better to solve the category of problems -- exception-catching
> expressions -- rather than the single problem of catching exceptions in an if/elif/else chain.
People are likely either going to put in exceptions that don't catch
enough (e.g. IndexError isn't the only exception that example can
throw) or, overreacting to that problm, that catch everything ("except
Exception:" is an anti-pattern that's hard to fight).
No, what I'm saying is that seeing it as sugar for exception handing
is the wrong way to look at it.
def demo(arg):
if given p, q = arg.x, arg.y:
# do something
elif given x = arg.x and isinstance(x, int):
# do something
elif given a, b, *_ = arg:
# do something
elif isinstance(arg, Mapping):
# do something
def demo2(arg): global important_value if not given important_value:important_value = compute_important_value()
> On Mon, May 23, 2016 at 7:57 PM, Michael Selik <michae...@gmail.com> wrote:
>
>>def demo(arg):
>> if p, q ?= arg.x, arg.y: # dict structure
>> elif x ?= arg.x and isinstance(x, int) # assignment + guard
>> elif a, b, *_ ?= arg: # tuple structure
>> elif isinstance(arg, Mapping): # nothing new here
I'm unenthusiastic about this -- the above looks like
an unreadable mess to me.
Some other worries:
* It appears that this would have to work by means of
exception-catching in the rhs, so it's really a
disguised form of the except: expression proposal;
is that intentional?
* It could also be abused to get an assigment-in-
expression anywhere you wanted. Such things have
been rejected before; are we changing our mind
on that?
* THere would be no hope of checking for coverage
of all cases in a static checker.
I feel like we've wandered a long way from the idea
we started with, which is something to facilitate
a Haskell-like case-analysis style of programming,
and ended up with something much looser that tries
to be all things to everyone.
Michael Selik wrote:
> My main point is
> that switch/case/matching is semantically identical to if/elif, so why
> use something different?
But then you say
> No, using the assign-if-can operator would be syntax error outside of an
> if/elif, the reverse of how an assign operator is a syntax error inside
> an if/elif.
So what you're proposing is *not* semantically equivalent
to composing the existing if/elif with a new pattern matching
assignment, which means re-using the existing keywords for
it is misleading.
> The exception-catching expression is not meant to be available in
> any other context. However, exception-catching is an essential feature
> to matching via destructuring. I believe it's unavoidable, though
> *which* exceptions are suppressed could be made more clear.
my assumption was that there was nothing special about
the right hand side, so the implementation would have to
just evaluate all of it and catch any AttribteErrors,
KeyErrors, IndexErrors, etc. emanating from it, which is
much looser and prone to catching too much.
But if the right hand side is special, all bets are off
and you'll have to explain exactly what would be allowed
and how to interpret it.
What about making it a function ?
Pattern matching is complex, it can be like a mini language inside the
language, just like regex.
My feeling is that the patterns should look like
constructors. The archetypal constructor for a mapping
object is the dict display, so a pattern that matches
a mapping having particular keys would be
case {"x": p, "y": q}:
Or maybe:
if <thing> ...
matches <matcher>:
pass
matches <matcher>:
pass
Where "..." is an actual syntactic element that replaces the ":" in a
regular if.
Best,
-Nikolaus
--
GPG encrypted emails preferred. Key id: 0xD113FCAC3C4E599F
Fingerprint: ED31 791B 2C5C 1613 AF38 8B8A D113 FCAC 3C4E 599F
»Time flies like an arrow, fruit flies like a Banana.«
I think all the ideas with "as" are difficult to read. I think its much
better to embed the target variables in the pattern - we just need a way
to mark them as such.
Mathematica has the same problem and solves it with a trailing _, but we
can't do that because our variables names may contain them. But maybe we
could use $? Most people already strongly associate this with variables.
Example:
given foo
case (x,y):
# matches if foo == (x,y)
case (x, $y):
# matches if len(foo) == 2 and foo[0] == x,
# and assigns y = foo[1]
case {'bar': $x, y: $z}:
# matches if foo is a map that has 'bar' and y keys
# and assigns x = foo['bar'], z = foo[y]
case $x.bar:
# matches if hasattr(foo, 'bar') and assigns x = foo
Best,
-Nikolaus
--
GPG encrypted emails preferred. Key id: 0xD113FCAC3C4E599F
Fingerprint: ED31 791B 2C5C 1613 AF38 8B8A D113 FCAC 3C4E 599F
»Time flies like an arrow, fruit flies like a Banana.«
On 26 May 2016 at 17:21, Sven R. Kunze <srk...@mail.de> wrote:I think "test one thing against multiple conditions" is a quite abstract thing to do. I would like to see some real-world use-case for this kind of syntaxToday, I was parsing a job output file. For each line in the file, I tested it against various patterns/conditions to see what type of line it was. Depending on the type of line, I did something different. I used a chain of if/elif statements, because that's what Python currently (3.5) provides, but it would have been an obvious case for a match/switch statement. If the important thing here is *structural* matching then what I actually did was call split() on the line to get a list of elements, then wanted some to be constants, and I picked data out of others. Something like match line_parts: case _, 'Job', 'Start', start_time: do_something1(start_time) case _, 'Job', 'End', end_time: do_something2(end_time) case view, 'size', 'is', kb, 'KB': do_something3(view, kb) Is that the type of example you had in mind? Paul
it is the nested case where I would really like destructuring.
I think that's a little confusing (but I don't have a better idea).
Assuming you have this class:
class Point:
def __init__(self, y, x):
self.y = y
self.x = x
would your first example assign x == obj.x or x = obj.y? In
ML-like languages these constructs typically match against the
"constructor", so you would expect x == obj.y. But I think the mechanics
of Python would force a translation to x == obj.x.
Best,
-Nikolaus
--
GPG encrypted emails preferred. Key id: 0xD113FCAC3C4E599F
Fingerprint: ED31 791B 2C5C 1613 AF38 8B8A D113 FCAC 3C4E 599F
»Time flies like an arrow, fruit flies like a Banana.«
On 25 May 2016 at 15:11, Chris Angelico <ros...@gmail.com> wrote:
> On Wed, May 25, 2016 at 3:03 PM, Stephen J. Turnbull <ste...@xemacs.org> wrote:
>> How about
>>
>> for <thing>:
>> try <matcher>:
>> pass
>> try <matcher>:
>> pass
>>
>> Look Ma! No new keywords! Yeah, I know, "for" and "try" both have
>> very strong connotations in Python already, so this may be a "not even
>> the Dutch could like it" automatic-parser-only syntax.
>
> I'd much prefer a different keyword instead of 'for'. If 'with' hadn't
> been used, that would be a better choice. Maybe 'using'... or
> 'switch'. But without iteration, 'for' is going to be very confusing.
As a variant on Guido's original switch/case idea:
given EXPR [as TARGET]:
case MATCH_PATTERN [as TARGET] [and CONDITION]:
...
case MATCH_PATTERN [as TARGET] [and CONDITION]:
...
case if CONDITION:
...
case MATCH_PATTERN [as TARGET]:
...
else:
On May 28, 2016 4:48 AM, "Greg Ewing" <greg....@canterbury.ac.nz> wrote:
>
> Ethan Furman wrote:
>>
>> Meaning we can *only* match on constructor arguments? What about attributes that are not set in the constructor, are we just out of luck for those?
>
>
> No, keyword pattern args should probably match either
> keyword constructor args or attributes.
That would make things ambiguous and tricky, wouldn't it?
Any criticism for using
object(attrname0=v0, attrname1=v1)
for generalized attribute unpacking?
Franklin? Lee wrote:
> On May 28, 2016 4:48 AM, "Greg Ewing" <greg....@canterbury.ac.nz
> <mailto:greg....@canterbury.ac.nz>> wrote:
> >
> > No, keyword pattern args should probably match either
> > keyword constructor args or attributes.
>
> That would make things ambiguous and tricky, wouldn't it?
My feeling is that for any well-designed object they
should be compatible. If an object has a constructor
keyword arg and an attribute with the same name but
they mean different things, that object is confusing
to begin with.