On Wed, Jun 13, 2012 at 5:29 AM, Andreas Rossberg <[email protected]>wrote:
> On 12 June 2012 23:57, Russell Leggett <[email protected]> wrote: > > This thread gave me an interesting idea on how to possibly attack pattern > > matching in ES6 with no new syntax, and still leave room for more sugar > > later. It actually comes from thinking about the original issue with > > function.length and using it for arity-based dispatch. What if we just > gave > > a better method than length? What if we had something like > > function.matches(args)? Where it would return true if all arguments were > > bound, and no parameters resulted in an undefined binding. > > function add(a,b){ > > return a + b; > > } > > > > add.matches(1,2); // => true > > add.matches(1); // => false > > add.matches(1,2,3); => false > > OK, I'll bite. I see lots of problems and unnecessary complexity here. > > If I understand this correctly, then it will require every function > closure to include meta information for performing the associated > pattern match. Or, when you actually want this to be optimised, the > ability to generate (probably lazily) and attach pattern matching code > to _every_ function closure. That seems pretty intrusive. > I'll respond a little out of order by saying that you believe patterns independently implemented would be simple and efficient. If that is the case (and I would think it was), then I don't really see how your argument holds water. Let's just say we actually had patterns. I'll make an imaginary syntax for them. let pattern = #({x,y}); pattern.matches({x:1,y:2}); If my example pattern could be done simply and efficiently, then why couldn't the same be done for function arguments. The only meta-data you would need to store is exactly the pattern that is in the function parameters. The body of the function provides no additional data. You could either eagerly generate the pattern, or simply keep the parameter pattern ast in the most efficient form to generate it lazily. The simple (and overwhelmingly most common case) would just be a list of parameters with no rest and no destructuring. Matching against this would reduce to a simple arity check. > > Also, the programmer would have to create a closure for every match > arm you ever want to use (unless the compiler is "sufficiently clever" > to recognise rather non-trivial patterns, which I doubt). That is > likely to be pretty costly. I guess to me this is just functional programming - its effectively a callback for each pattern. The one which matches gets called. I don't see why its so different than using forEach instead of a for loop. One is more expressive and functional style, the other is more efficient. > I'm also not sure how you envision > actually binding variables during a match. Are you suggesting that one > does something like: > > if (f.matches(x, y)) f(x, y) > Even if this is abstracted into some 'match' function, a match would > redundantly decompose x, y for f twice. > That is true. Perhaps a builtin Object.match function could optimize? Still, it does not seem overwhelmingly inefficient, just not as nice as built in pattern matching. > > And just to be clear, this feature also reveals implementation details > of a function that it shouldn't. For example, it allows you to observe > cases where a function ignores some of its documented arguments, or > some parts of its arguments. So it has all the bad properties of the > 'isBound' function we discussed earlier. > I mostly disagree. The signature of a function is it's interface. Even Java let's you reflectively ask about a method's signature. In reality, it is almost no different than function.length in terms of revealing implementation details. My major problem with isBound is that it required looking at the body of the function, because |this| isn't something you'll see in a parameter list. However, as I said, I only *mostly* disagree. The same reason I initially cringed at Irakli's function.length request because I worried how it would be abused, I have some of the same worries here. It could make for some pretty subtle code to change what arguments you send a callback based on its signature – but unlike function.isBound which I think had fewer appropriate use cases and looked at the method body, I think function.matches has a much clearer use case and does not expose too much. I especially like it in the case of using it with arrow functions, which have no |this| and no access to an arguments object. I debated about suggesting it only be available on arrow functions, but I think there are some big downsides to that too. > > I'd say (despite being part of the pattern matching choir) that this > is not the proper way to introduce a feature that, as a proper > language construct, would be relatively simple, efficient, and > independent of anything else. I would much prefer to have it as a full, proper language construct, and I would not have suggested function.matches if I thought it would be future unfriendly to adding them. On the contrary, my hope is that this would be a low footprint feature, but would provide the tool missing to allow for the community to play with patterns. One of the great things about JavaScript is its flexibility, and the community has really used that to create the cowpaths we later pave. As a way of figuring out the best way to add full patterns to the language, wouldn't it be helpful to give people this small feature and see what the result is? The more pattern-like destructuring becomes, the more people will want to use it for that purpose. This is the hook needed to easily expose that. And even if pattern-matching becomes first class, I think there will still be cases when functions-as-patterns would still be useful. - Russ
_______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

