On Wed, May 25, 2016 at 5:26 AM, Paul Moore <p.f.moore@gmail.com> wrote:
On 25 May 2016 at 10:04, Franklin? Lee <leewangzhong+python@gmail.com> wrote:
Problem: `Point(x, y, ...)` is a legitimate function call, so if `Point(x, 0)` is a legal pattern (i.e. no distinguishing syntax between values and bindnames), you'd need the syntax to be `Point(x, y, *...)`. Personally, I'd require that everything is a bindname (unless it looks like a constructor call), and require checks to be in guards.
With the above syntax, "bare" values aren't a valid match, so in a match, Point(x, y) can never be a function call, it must be a match "Object of type Point, with x and y attributes (which we check for but don't bind)".
I mean a function call, in particular a constructor call. Take these examples, written as constructor destructure assignment: Point(x, y) = obj Point(x=_, y=_) = obj I'd say that Point(x, y) binds two positional constructor arguments, and Point(x=_, y=_) binds attributes .x and .y to throwaway variables. (`object` takes no positional args, and I want it to start allowing keyword args.) Here's my proposed implementation again: Call Point.__asmatch__(obj, nargs, keys, args, kwargs) (where "asmatch" might be an enhanced "__getnewargs__"), with these params: - obj: The object to destructure, which is an instance of Point (possibly typechecked by the match engine before calling). (Note that we're not calling obj.__asmatch__(nargs, ...), to give superclasses a chance to destructure a subclass instance.) - nargs: Number of positional args. - keys: Keyword args specified. - args: Whether or not *rest was used. (Extension: Whether or not splat was used, and whether to discard them.) - kwargs: Whether or not **rest was used. (Extension: and whether to discard them.) It will return (args: tuple, kwargs: dict) if the match is possible. It will check whether there are enough positional args, and whether all keys were valid, and perform the logic about the optional params (giving up as few args and kwargs as possible). Contract: The returned tuple and dict _should_ be valid for Point(*args, **kwargs). This constraint is not necessary if "discard" was specified for anything. My problem is, this would then be ambiguous: Point(0, ...) = obj # Match if the first arg is 0 and the second is `...`? while this would not, but might be ugly. Point(0, *...) = obj