alternatives to custom notations
Pattern matching of general data structures is an elegant and powerful
programming technique, that is being used since a long time in
(mostly) research programming languages such as ML, Prolog, Erlang,
and many others. In spite of the clear advantages of pattern matching,
this technology still hasn't reached mainstream languages, used by the
vast majority of programmers, not even the most recent languages such
as Java, JavaScript, or C#.
There are however some well-known technologies that achieve some
effects similar to the pattern matching offered by myPatterns. These
are briefly discussed here.
regular expressions
Pattern matching of strings, using regular expressions, is readily
available in all mainstream languages, either within the language or
as a library. Regular expressions are very useful when manipulating
text, but they are not applicable to programs using general data
structures such as lists, arrays, or objects. Stringifying a data
structure and matching it with regular expressions is not nearly
enough, because regular expressions are fundamenatlly limited in that
they do not cover (recursively) nested constructs (such as data
structures).
For instance, say you want to match a Person object of the form
{... age: 18 ...}. There is no way using regular expressions to do
this in all cases. For instance, the regular expression /{.*
age:([0-9]*).*}/ works just fine for the object {name: "Bill", age:
18}, but not for the object:
{name: "Bill", father: {name: "Ben", age: 49}, age: 18, friend: {name: "Bob", age:16}}
for which it will match either the age of Bill's father or Bill's
friend (depending whether you are using shortest match or longest
match), instead of matching Bill's age. This is because regular
expressions cannot express something like "any substring containing
well-nested braces".
In turn, myPatterns allows you to simply write "{age: 18}" for
matching exactly the intended objects. On the other hand myPatterns
include support for regular expression matching. For instance, the
pattern "{author:/^(.*)ski$/}" matches any (say) book written by an
author whose name ends in "ski", and returns the stem of that name.
XPath
Matching of XML documents using pattern (and query) languages such as
XPath or XQuery is available in all mainstream languages, either
within the language (e.g. the E4X extension in JavaScript) or as a
library. XPath-style matching is very useful when manipulating XML
data or HTML documents, but is of no help when manipulating
user-defined or system-defined data structures used everywhere in most
programs, that do not come from parsing an XML source. Although there
is a recent trend for technologies allowing to see data structures as
XML, and thereby allowing to use XPath-style matching for general data
structures, XPath notations are much more verbose and cumbersome
compared to notations specifically designed for lists, terms,
etc.
For example, consider the following native JavaScript object:
var john =
{name: {firstname: "John", lastname: "Smith"},
children:[{firstname: "Eric", gender: "male", born: 1991},
{firstname: "Deborah", gender: "female", born: 1996}]};
and say you want to check if the first kid of this person is 18, and
at the same time get the father's name and the list of
brothers/sisters of the teenager.
When using myPatterns/JS, this is done very simply as a single test,
using a JSON pattern complemented by a boolean expression:
(s = match(x, "{name:{lastname: %l}, children:[{gender: 'male', born: %b} | %x]}"))
&& new Date().getFullYear() - s.b == 18
In turn, for using XPath on this data, the solution is much more
elaborate, involving converting the data to XML (for example the XML
type of E4X), via an XML serialization using some O/X mapper (for
example OBJtree):
// Convert john from JSON to XML string
var xotree = new XML.ObjTree();
xotree.xmlDecl = '';
var johnxs = xotree.writeXML( john );
// Parse back XML string as E4X
johnx = new XML("" + johnxs + "");
// Extract subdata as variables
var l = johnx.name.lastname;
var b = johnx.children[0].born;
var x = new Array();
for(var i = 1; i < johnx.children.length(); i++)
x.push(johnx.children[i]);
// Compute the result of matching
johnx.children[0].gender == "male"
&& new Date().getFullYear() - b == 18;
Note: if you are aware of a simpler solution than that, please
let us know.
Other than being so verbose, this solution is also very
inefficient, as it requires to serialize completely the data, that may
be huge. In constrast, myPatterns only traverses the data as needed by
the pattern. There is also the problem of circular data, that makes
OBJTree hang, while myPatterns handles such data just fine.
Finally, even if all these issues are solved, myPatterns brings you
the comfort and conciseness of a "concrete syntax" notation, allowing
to both recognize and decompose data declaratively, in a single
step. In this example, the notation was JSON-like. Furthermore and
most importantly, myPatterns lets you redefine new notations as you
wish, if JSON is not adequate for your specific data or application.
XLST
XLST is a general-purpose XML to XML transformer that also includes
XPath as a query language. The relation between concrete syntax
patterns and XPath patterns has been discussed above. Beyond this
difference, the main difference between XSLT itself and myPatterns is
that the former is working on external XML data while the latter is
working on native data structures.
However, there are some scenarios where either one of the two
technologies could be used, for example when extracting data into a
HTML table.
The following myPatterns/JS query extracts information from a table
of Person objects like the one above:
tableMatching(persons, "{name:{lastname:%l, firstname:%f}, [{born: %x}, {born:%y}]}");
into an HTML table such as the following:
l | f | x | y |
Smith | John | 1991 | 1996 |
Johnson | Matt | 1978 | 1979 |
Of course, such an HTML table can be also generated very naturally
using XSLT from persons information (supposing the data were stored in
an XML file), but the XLST stylesheet is considerably more verbose.
LINQ
See myPatterns & LINQ.
JSONPath & JSONQuery
See myPatterns & JSONQuery.
language pre-processors
Matching in convenient concrete syntaxes of general data structures
such as objects is now available using non-standard extensions of
mainstream languages, such as Java pre-processors (for
example, JMatch). These
technologies provide effective pattern matching solutions, but require
programmers to adopt non-standard tools, thereby endorsing the
associated risks, among which: incompatibility with the rest of the
world, non-optimal debugging support, etc.
As opposed to that, custom notations are a technology for pattern
matching of general data structures that can be used in mainstream
languages such as C and JavaScript, without changing anything to the
development environment. Programmers may continue using their favorite
compiler or interpreter, debugger, IDE, etc. They only have to include
in their application the myPatterns library -- a minimal, free, open
source library.
But custom notations go far beyond providing pattern matching
features for data structures. As their name suggests, the custom
notations technology allows programmers defining their own
notations for data structures, to be used in patterns.
conclusion
myPatterns/JS is not meant to replace technologies such as regular
expressions, XPath, or LINQ, but rather complement them by offering
pattern matching of native data structures in the concrete syntax of
your choice.