Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plan for pattern matching? (PEP636) #1090

Closed
ariebovenberg opened this issue Oct 1, 2021 · 3 comments
Closed

Plan for pattern matching? (PEP636) #1090

ariebovenberg opened this issue Oct 1, 2021 · 3 comments

Comments

@ariebovenberg
Copy link
Contributor

ariebovenberg commented Oct 1, 2021

👋 Hi there. Great work on this library! Do you have some thoughts on supporting pattern matching (upcoming feature in Python 3.10)? I can foresee a few issues if we don't give this some thought.

The 'default' approach would probably be something like:

match myvalue:
    case Some(6): print('six!')
    case Some(x): print(x)
    case Nothing: print("nothing to see here")

(This currently does not work, but would probably be possible to implement without changes to the API)

The problem is the last case. It only appears like it only matches Nothing instances. In actuality, it matches anything. Misspelling it asNohting would pass the type checker as well! This is because python handles case <any variable name>: as the 'fallback' case.

Problem? You cannot handle the Nothing case first:

match myvalue:
    case Nothing: print('nothing to see here')  # python interprets this as the 'fallback' case
    case Some(x): print(x)  # cases after the 'fallback case' are not allowed!
File "foo.py", line 6
    case Nothing: print('nothing to see here')
         ^^^^^^^
SyntaxError: name capture 'Nothing' makes remaining patterns unreachable

There are a few ways to address this:

option 1: Do not address this. In the end the functionality works...sort of

problems:
I. It's confusing because pattern matching is not actually occurring
II. You don't allow matching on Nothing first
III. You get problems when you want to handle more cases. It's a bit contrived, but you could want to handle myvalue of type Union[list, Maybe[int]]. In that case you could not:

match myvalue:
    case Some(x): print(x)
    case Nothing: print('nothing to see here')  # this is handled as the fallback case and ruins everything
    case []: print('empty list')
    case _: print('something random')

You would have to explain to everyone that Nothing must be matched last

option 2: Follow the advice of PEP636

Patterns may use named constants. These must be dotted names to prevent them from being interpreted as capture variable:

match myvalue:
    case maybe.Nothing: print('nothing to see here')
    case maybe.Some(x): print(x)

This is a bit clunky though... 🤔

Option 3: Somehow enable Nothing() as a pattern match:

match myvalue:
    case Nothing(): print('nothing to see here')
    case Some(x): print(x)

This is confusing because this usage is different from using Nothing in any other context. Other alternative is to break the API by mandating Nothing() instead of Nothing (not something you'd like, I think)

Option 4: something I'm not thinking of

I probably missed another option, but I'm curious what you feel is the best way going forward.

@sobolevn
Copy link
Member

sobolevn commented Oct 1, 2021

@ariebovenberg
Copy link
Contributor Author

ariebovenberg commented Oct 1, 2021

@sobolevn woops, looks like I didn't keep up-to-date on your pace of development 😅. Nice work!

Time for weekend...

edit: 🤦 I should have searched the PRs, not just the issues...

@sobolevn
Copy link
Member

sobolevn commented Oct 1, 2021

@ariebovenberg I appreciate your report! Have a great weekend! 👍

I will try to sync next returns release with 3.10 release.
So, PM will be available to everyone from the very start!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants