Prev: How to Pump $1,000s in CASH & Checks to your door.
Next: Suggestion for FAQ, *OR* has it been done (URL?)
From: Alex Shabanov on 14 May 2010 06:45 Several days ago I needed an easy to use and easy to extend facility that performs pattern matching. I ended up with the following interface: // matcher function. To prevent situations when no pattern matches the object given, // it might be initialized as follows: // matcher = function() { throw new Error("no applicable pattern found") } var matcher matcher = combine(PATTERN1, CALLBACK1(OBJ, .. OPTIONAL_ARGS){...}, matcher) matcher = combine(PATTERN2, CALLBACK2(OBJ, .. OPTIONAL_ARGS){...}, matcher) // the result of combine method shall be immediately callable to perform pattern matching matcher = combine(PATTERN3, CALLBACK3(OBJ, .. OPTIONAL_ARGS){...}, matcher) .... // perform pattern matching matcher(OBJ, ... OPTIONAL_ARGS) Here is a sample usage: var matcher = function(val, arg) { print("matcher fallback: val = " + val + ", arg = " + arg) } matcher = pm.combine({type: "string"}, function(val, arg) { print({expr: "matcher(stringVal, arg)", value: "val = " + val + ", arg = " + arg}) }, matcher) matcher = pm.combine({instanceOf: Function}, function(val, arg) { print({expr: "matcher(functionVal, arg)", value: "val = " + val + ", arg = " + arg}) }, matcher) matcher = pm.combine({scheme: {key: "number", value: "any"}}, function(val, arg) { print({expr: "matcher({key:number, value:any}, arg)", value: "val = (" + val.key + "," + val.value + "), arg = " + arg}) }, matcher) matcher(5, "one") matcher("str", "two") matcher(new Function("return 1"), "three") matcher({key: 12, value: 34}, "four") matcher({key: "some", value: "unk"}, "five") Here is an implementation: // namespace var pm = {} /** * Matcher functions constructors are used in pm.combine method. * Each key in this object corresponds to the certain pattern member. */ pm._matcherConstructors = { instanceOf: function (matcher, instanceTarget) { return function (obj) { if (obj instanceof instanceTarget) { return matcher.apply(this, arguments) } return false } }, type: function (matcher, typeId) { return function (obj) { if (typeof(obj) === typeId) { return matcher.apply(this, arguments) } return false } }, scheme: function (matcher, scheme) { return function (obj) { if (typeof(obj) !== "object") { return false } for (var i in scheme) { if (i in obj) { var target = obj[i] var source = scheme[i] var sourceType = typeof(source) if (sourceType === "string") { if (source === "any" || source == typeof(target)) { continue } return false } if (source !== target) { return false } } else { return false } } return matcher.apply(this, arguments) } } } /** * Creates pattern matching function that accepts the pattern given. * The latter combined patterns takes priority over the previously declared ones. * @param pattern Pattern to match the target object. * @param callback User-defined callback to accept target object as well as the accompanying arguments. * @param prevMatcher Previous matcher function created by combine method or null or undefined. * @returns Matcher function to be used as follows: matcher.call(objectToBeMatched, optionalArguments...). */ pm.combine = function(pattern, callback, prevMatcher) { var matcher = function() { callback.apply(this, arguments) return true } // join visitor function according to the pattern given for (var i in pattern) { if (!(i in pm._matcherConstructors)) { throw new Error("unexpected pattern tag: " + i) } matcher = pm._matcherConstructors[i](matcher, pattern[i]) } // if prev matcher either undefined or null - create new function if (prevMatcher == null) { return matcher } else { return function() { if (matcher.apply(this, arguments)) { return true } return prevMatcher.apply(this, arguments) } } } /** * Helper function that initializes matcher for all the types of objects with * the callback that throws an error. */ pm.unknownObjectMatcher = function() { throw new Error("unknown object matched") } Comments appreciated :)
From: Thomas 'PointedEars' Lahn on 14 May 2010 08:20 Alex Shabanov wrote: > Several days ago I needed an easy to use and easy to extend facility > that performs pattern matching. > > I ended up with the following interface: > > [...] > > Comments appreciated :) Looks like an awful lot of code to do what could probably be done in one line. Perhaps you could explain why one would use your approach instead? PointedEars -- Use any version of Microsoft Frontpage to create your site. (This won't prevent people from viewing your source, but no one will want to steal it.) -- from <http://www.vortex-webdesign.com/help/hidesource.htm> (404-comp.)
From: Alex Shabanov on 14 May 2010 11:07 On May 14, 4:20 pm, Thomas 'PointedEars' Lahn <PointedE...(a)web.de> wrote: > Alex Shabanov wrote: > > Several days ago I needed an easy to use and easy to extend facility > > that performs pattern matching. > > > I ended up with the following interface: > > > [...] > > > Comments appreciated :) > > Looks like an awful lot of code to do what could probably be done in one > line. Perhaps you could explain why one would use your approach instead? This is to avoid using lots of typeofs and ifs to analyze certain incoming object. You can think of using this approach as of visitor pattern. In contrast to visitor pattern, pattern-matching approach deals with object type or with it's structure or with both. A benefit to hand-written approach is that pattern matching provides a kind of abstraction layer to the code what deals with the object's structure. > > PointedEars > -- > Use any version of Microsoft Frontpage to create your site. > (This won't prevent people from viewing your source, but no one > will want to steal it.) > -- from <http://www.vortex-webdesign.com/help/hidesource.htm> (404-comp.)
From: Thomas 'PointedEars' Lahn on 14 May 2010 13:50 Alex Shabanov wrote: > Thomas 'PointedEars' Lahn wrote: >> Alex Shabanov wrote: >> > Several days ago I needed an easy to use and easy to extend facility >> > that performs pattern matching. >> > >> > I ended up with the following interface: >> > >> > [...] >> > >> > Comments appreciated :) >> >> Looks like an awful lot of code to do what could probably be done in one >> line. Perhaps you could explain why one would use your approach instead? > > This is to avoid using lots of typeofs By making a lot of comparably more expensive calls instead. The requirements being made to the capabilities of the implementation are also more than with `typeof' -- which is not a function, BTW -- and friends. > and ifs to analyze certain incoming object. Note that 5 and "str" are primitive values. > You can think of using this approach as of visitor pattern. In > contrast to visitor pattern, pattern-matching approach deals with > object type or with it's structure or with both. > > A benefit to hand-written approach is that pattern matching provides a > kind of abstraction layer to the code what deals with the object's > structure. I still do not see the problem this is supposed to solve; except perhaps extensive method overloading, which is inherently flawed and so should be designed out of an API to begin with. PointedEars -- Prototype.js was written by people who don't know javascript for people who don't know javascript. People who don't know javascript are not the best source of advice on designing systems that use javascript. -- Richard Cornford, cljs, <f806at$ail$1$8300dec7(a)news.demon.co.uk>
From: Alex Shabanov on 14 May 2010 15:29 On May 14, 9:50 pm, Thomas 'PointedEars' Lahn <PointedE...(a)web.de> wrote: > Alex Shabanov wrote: > > Thomas 'PointedEars' Lahn wrote: > >> Alex Shabanov wrote: > >> > Several days ago I needed an easy to use and easy to extend facility > >> > that performs pattern matching. > > >> > I ended up with the following interface: > > >> > [...] > > >> > Comments appreciated :) > > >> Looks like an awful lot of code to do what could probably be done in one > >> line. Perhaps you could explain why one would use your approach instead? > > > This is to avoid using lots of typeofs > > By making a lot of comparably more expensive calls instead. The > requirements being made to the capabilities of the implementation are also > more than with `typeof' -- which is not a function, BTW -- and friends. > > > and ifs to analyze certain incoming object. > > Note that 5 and "str" are primitive values. Yep, I know. The "matcher" function given above does understand primitives as well as objects. > > > You can think of using this approach as of visitor pattern. In > > contrast to visitor pattern, pattern-matching approach deals with > > object type or with it's structure or with both. > > > A benefit to hand-written approach is that pattern matching provides a > > kind of abstraction layer to the code what deals with the object's > > structure. > > I still do not see the problem this is supposed to solve; except perhaps > extensive method overloading, which is inherently flawed and so should be > designed out of an API to begin with. This is exactly the case I dealt with. I needed to write a sort of print function that takes one parameter and prints it in a way that depends on type and structure of the object given. E.g. strings shall be printed as is, objects with expr and value properties shall be represented as two differently colored elements, the object with snippet property shall be represented within an expandable element, etc. The other sample is when I needed to display a widget that intended to show a particular object in particular state. The problem was that there were too much objects and their states so I ended up with a mess of numerous if-expressions. Of course, most of the real life problems are trivial and can be best expressed with just built-in means but not all of them. It is funny - I never ever needed to use regular expressions during my professional career though I wrote literally hundreds of them in academic years. I wouldn't say that regular expressions are useless but I've just never encountered a task that'd require them. > > PointedEars > -- > Prototype.js was written by people who don't know javascript for people > who don't know javascript. People who don't know javascript are not > the best source of advice on designing systems that use javascript. > -- Richard Cornford, cljs, <f806at$ail$1$8300d...(a)news.demon.co.uk>
|
Next
|
Last
Pages: 1 2 3 Prev: How to Pump $1,000s in CASH & Checks to your door. Next: Suggestion for FAQ, *OR* has it been done (URL?) |