I see a little problem if we want to match more cases:
from destructure import Binding, Switch
o = Binding()
schema1 = [2, o.x, 3]
schema2 = [2, 4, o.x]
s = Switch([2, 4, 3])
if s.case(schema1):
print(o.x)
if s.case(schema2):
print(o.x)
4
---------------------------------------------------------------------------
BindError Traceback (most recent call last)
[...]
BindError: name 'x' has already been bound to 3
I prefer to enable multiple matches.
But if you really like to forbid it then you would probably like to
change next line ->
raise BindError(fmt.format(name=name, value=value))
to line ->
raise BindError(fmt.format(name=name, value=getattr(self, name)))
Anyway I really like your proof of concept! :)
To improve it maybe you could distinguish cases in readme.rst. For example:
schema1 = [1, o.x, 3]
schema2 = [2, 4, o.x]
s = Switch([2, 4, 6])
if s.case(schema1):
print(o.x)
elif s.case(schema2):
print(o.x)
else:
print('otherwise')
6
2016-05-30 8:52 GMT+02:00, Michael Selik
I'm sure y'all are too busy with PyCon to be checking email. But if you're curious, I added attribute unpacking and post-binding guards ( https://github.com/selik/destructure).
The object unpacking works as most folks have suggested, via kwargs. The guards unfortunately need to be functions that take no parameters.
match(schema=Foo(a=1, b=bind.x), data=Foo(a=1, b=2), lambda : bind.x > 0)
On Sat, May 28, 2016 at 6:26 AM Paul Moore
wrote: On 28 May 2016 at 08:22, Michael Selik
wrote: My original dict unpacking proposal was very short and lacked a motivating usage. Toy examples made my proposal look unnecessarily verbose and suggested obvious alternatives with easy current syntax.
Nested/recursive unpacking is much more troublesome, especially when combined with name-binding. I wrote an example to compare my proposal with current syntax.
Example usage. https://github.com/selik/destructure/blob/master/examples/fips.py
Implementation. https://github.com/selik/destructure/blob/master/destructure.py
The design of my module I'm least happy with is the name-binding. I extended a SimpleNamespace to create an Erlang-style distinction between bound and unbound names. Though the API is a bit awkward, now that the module is built, I'm less enthusiastic about introducing new syntax. Funny how that works.
I haven't yet decided how to add post-binding guards to the cases.
Interesting! Thanks for taking the time to make a real-world use case. I haven't looked at the module yet, just the example, but the code does look pretty clean and readable. The example is certainly complex enough that I'd probably end up with pretty messy and fragile code if I just tried to put something together with pure Python code.
And yes, it's interesting how finding a good API for a module can make the need for a dedicated syntax less pressing. But working out that good API can be really hard (I don't think I'd ever have thought of doing it the way you did).
Paul