1 .. title:: MochiKit.Base - functional programming and useful comparisons
6 MochiKit.Base - functional programming and useful comparisons
14 myObjectRepr = function () {
15 // gives a nice, stable string representation for objects,
16 // ignoring any methods
17 var keyValuePairs = [];
20 if (typeof(v) != 'function') {
21 keyValuePairs.push([k, v]);
24 keyValuePairs.sort(compare);
27 return map(repr, pair).join(":");
33 // repr() will look for objects that have a repr method
35 {"a": 3, "b": 2, "repr": myObjectRepr},
36 {"a": 1, "b": 2, "repr": myObjectRepr}
39 // sort it by the "a" property, check to see if it matches
40 myObjectArray.sort(keyComparator("a"));
41 expectedRepr = '[{"a": 1, "b": 2}, {"a": 3, "b": 2}]';
42 assert( repr(myObjectArray) == expectedRepr );
44 // get just the "a" values out into an array
45 sortedAValues = map(itemgetter("a"), myObjectArray);
46 assert( compare(sortedAValues, [1, 3]) == 0 );
48 // serialize an array as JSON, unserialize it, expect something equivalent
49 myArray = [1, 2, "3", null, undefined];
50 assert( objEqual(evalJSON(serializeJSON(myArray)), myArray) );
56 :mochiref:`MochiKit.Base` is the foundation for the MochiKit suite.
59 - An extensible comparison facility
60 (:mochiref:`compare`, :mochiref:`registerComparator`)
61 - An extensible programmer representation facility
62 (:mochiref:`repr`, :mochiref:`registerRepr`)
63 - An extensible JSON [1]_ serialization and evaluation facility
64 (:mochiref:`serializeJSON`, :mochiref:`evalJSON`,
65 :mochiref:`registerJSON`)
66 - A simple adaptation facility (:mochiref:`AdapterRegistry`)
67 - Convenience functions for manipulating objects and Arrays
68 (:mochiref:`update`, :mochiref:`setdefault`, :mochiref:`extend`, etc.)
69 - Array-based functional programming
70 (:mochiref:`map`, :mochiref:`filter`, etc.)
71 - Bound and partially applied functions
72 (:mochiref:`bind`, :mochiref:`method`, :mochiref:`partial`)
74 Python users will feel at home with :mochiref:`MochiKit.Base`, as the
75 facilities are quite similar to those available as part of Python and
76 the Python standard library.
91 The comparators (operators for comparison) in JavaScript are deeply
92 broken, and it is not possible to teach them new tricks.
94 MochiKit exposes an extensible comparison facility as a simple
95 :mochiref:`compare(a, b)` function, which should be used in lieu of
96 JavaScript's operators whenever comparing objects other than numbers
97 or strings (though you can certainly use :mochiref:`compare` for
100 The :mochiref:`compare` function has the same signature and return
101 value as a sort function for ``Array.prototype.sort``, and is often
102 used in that context.
104 Defining new comparators for the :mochiref:`compare` function to use
105 is done by adding an entry to its :mochiref:`AdapterRegistry` with the
106 :mochiref:`registerComparator` function.
109 Programmer Representation
110 -------------------------
112 JavaScript's default representation mechanism, ``toString``, is
113 notorious for having terrible default behavior. It's also very unwise
114 to change that default, as other JavaScript code you may be using may
117 It's also useful to separate the concept of a "string representation"
118 and a "string representation for programmers", much like Python does
119 with its str and repr protocols.
121 :mochiref:`repr` provides this programmer representation for
122 JavaScript, in a way that doesn't require object prototype hacking:
123 using an :mochiref:`AdapterRegistry`.
125 Objects that implement the repr protocol can either implement a
126 ``.repr()`` or ``.__repr__()`` method, or they can simply have an
127 adapter setup to generate programmer representations. By default, the
128 registry provides nice representations for ``null``, ``undefined``,
129 ``Array``, and objects or functions with a ``NAME`` attribute that use
130 the default ``toString``. For objects that ``repr`` doesn't already
131 understand, it simply defaults to ``toString``, so it will integrate
132 seamlessly with code that implements the idiomatic JavaScript
135 To define a programmer representation for your own objects, simply add
136 a ``.repr()`` or ``.__repr__()`` method that returns a string. For
137 objects that you didn't create (e.g., from a script you didn't write,
138 or a built-in object), it is instead recommended that you create an
139 adapter with :mochiref:`registerRepr`.
145 JSON [1]_, JavaScript Object Notation, is a widely used serialization
146 format in the context of web development. It's extremely simple,
147 lightweight, and fast. In its essence, JSON is a restricted subset of
148 JavaScript syntax suitable for sending over the wire that can be
149 unserialized with a simple eval. It's often used as an alternative to
150 XML in "AJAX" contexts because it is compact, fast, and much simpler
151 to use for most purposes.
153 To create a JSON serialization of any object, simply call
154 :mochiref:`serializeJSON()` with that object. To unserialize a JSON
155 string, simply call :mochiref:`evalJSON()` with the serialization.
157 In order of precedence, :mochiref:`serializeJSON` coerces the given
158 argument into a JSON serialization:
160 1. Primitive types are returned as their JSON representation:
161 ``string``, ``number``, ``boolean``, ``null``.
162 2. If the object has a ``__json__`` or ``json`` method, then it is
163 called with no arguments. If the result of this method is not the
164 object itself, then the new object goes through rule processing
165 again (e.g. it may return a string, which is then serialized in
167 3. If the object is ``Array``-like (has a ``length`` property that is
168 a number, and is not a function), then it is serialized as a JSON
169 array. Each element will be processed according to these rules in
170 order. Elements that can not be serialized (e.g. functions) will
171 be replaced with ``undefined``.
172 4. The ``jsonRegistry`` :mochiref:`AdapterRegistry` is consulted for
173 an adapter for this object. JSON adapters take one argument (the
174 object), and are expected to behave like a ``__json__`` or
175 ``json`` method (return another object to be serialized, or
177 5. If the object is ``undefined``, a ``TypeError`` is thrown. If you
178 wish to serialize ``undefined`` as ``null`` or some other value, you
179 should create an adapter to do so.
180 6. If no adapter is available, the object is enumerated and
181 serialized as a JSON object (name:value pairs). All names are
182 expected to be strings. Each value is serialized according to
183 these rules, and if it can not be serialized (e.g. methods), then
184 that name:value pair will be skipped.
190 MochiKit makes extensive use of adapter registries, which enable you
191 to implement object-specific behaviors for objects that you do not
192 necessarily want to modify, such as built-in objects. This is
193 especially useful because JavaScript does not provide a method for
194 hiding user-defined properties from ``for propName in obj``
197 :mochiref:`AdapterRegistry` is simply an encapsulation for an ordered
198 list of "check" and "wrap" function pairs. Each
199 :mochiref:`AdapterRegistry` instance should perform one function, but
200 may have multiple ways to achieve that function based upon the
201 arguments. One way to think of it is as a poor man's generic function,
202 or multiple dispatch (on arbitrary functions, not just type!).
204 Check functions take one or more arguments, and return ``true`` if the
205 argument list is suitable for the wrap function. Check functions
206 should perform "cheap" checks of an object's type or contents, before
207 the "expensive" wrap function is called.
209 Wrap functions take the same arguments as check functions and do some
210 operation, such as creating a programmer representation or comparing
214 Convenience Functions
215 ---------------------
217 Much of :mochiref:`MochiKit.Base` is there to simply remove the grunt
218 work of doing generic JavaScript programming.
220 Need to take every property from one object and set them on another?
221 No problem, just call :mochiref:`update(dest, src)`! What if you just
222 wanted to update keys that weren't already set? Look no further than
223 :mochiref:`setdefault(dest, src[, ...])`.
225 Want to return a mutable object, but don't want to suffer the
226 consequences if the user mutates it? Just :mochiref:`clone(it)` and
227 you'll get a copy-on-write clone. Cheaper than a copy!
229 Need to extend an ``Array`` with another array? Or even an
230 ``Array``-like object such as a ``NodeList`` or the special
231 ``arguments`` object? Even if you need to skip the first few elements
232 of the source ``Array``-like object, it's no problem with
233 :mochiref:`extend(dstArray, srcArrayLike[, skip])`!
235 Wouldn't it be convenient to have all of the JavaScript operators were
236 available as functions somewhere? That's what the
237 :mochiref:`operators` table is for, and it even comes with additional
238 operators based on the :mochiref:`compare` function.
240 Need to walk some tree of objects and manipulate or find something in
241 it? A DOM element tree perhaps? Use :mochiref:`nodeWalk(node,
244 There's plenty more, so check out the `API Reference`_ below.
247 Functional Programming
248 ----------------------
250 Functional programming constructs such as :mochiref:`map` and
251 :mochiref:`filter` can save you a lot of time, because JavaScript
252 iteration is error-prone and arduous. Writing less code is the best
253 way to prevent bugs, and functional programming can help you do that.
255 :mochiref:`MochiKit.Base` ships with a few simple Array-based
256 functional programming constructs, namely :mochiref:`map` and
257 :mochiref:`filter`, and their "extended" brethren, :mochiref:`xmap`
258 and :mochiref:`xfilter`.
260 :mochiref:`map(func, arrayLike[, ...])` takes a function and an
261 ``Array``-like object, and creates a new ``Array``. The new ``Array``
262 is the result of ``func(element)`` for every element of ``arrayLike``,
263 much like the ``Array.prototype.map`` extension in Mozilla. However,
264 :mochiref:`MochiKit.Base` takes that a step further and gives you the
265 full blown Python version of :mochiref:`map`, which will take several
266 ``Array``-like objects, and calls the function with one argument per
267 given ``Array``-like, e.g.::
269 var arrayOne = [1, 2, 3, 4, 5];
270 var arrayTwo = [1, 5, 2, 4, 3];
271 var arrayThree = [5, 2, 1, 3, 4];
272 var biggestElements = map(objMax, arrayOne, arrayTwo, arrayThree);
273 assert( objEqual(biggestElements, [5, 5, 3, 4, 5]) );
275 :mochiref:`filter(func, arrayLike[, self])` takes a function and an
276 ``Array``-like object, and returns a new ``Array``. This is basically
277 identical to the ``Array.prototype.filter`` extension in
278 Mozilla. self, if given, will be used as ``this`` in the context of
281 :mochiref:`xmap` and :mochiref:`xfilter` are just special forms of
282 :mochiref:`map` and :mochiref:`filter` that accept a function as the
283 first argument, and use the extra arguments as the ``Array``-like. Not
284 terribly interesting, but a definite time-saver in some cases.
286 If you appreciate the functional programming facilities here, you
287 should definitely check out :mochiref:`MochiKit.Iter`, which provides
288 full blown iterators, :mochiref:`MochiKit.Iter.range`,
289 :mochiref:`MochiKit.Iter.reduce`, and a near-complete port of Python's
290 itertools [2]_ module, with some extra stuff thrown in for good
294 Bound and Partial Functions
295 ---------------------------
297 JavaScript's method-calling special form and lack of bound functions
298 (functions that know what ``this`` should be) are one of the first
299 stumbling blocks that programmers new to JavaScript face. The
300 :mochiref:`bind(func, self)` method fixes that right up by returning a
301 new function that calls func with the right ``this``.
303 In order to take real advantage of all this fancy functional
304 programming stuff, you're probably going to want partial
305 application. This allows you to create a new function from an existing
306 function that remembers some of the arguments. For example, if you
307 wanted to compare a given object to a slew of other objects, you could
308 do something like this::
310 compareWithOne = partial(compare, 1);
311 results = map(compareWithOne, [0, 1, 2, 3]);
312 assert( objEqual(results, [-1, 0, 1, 1]) );
314 One of the better uses of partial functions is in
315 :mochiref:`MochiKit.DOM`, which is certainly a must-see for those of
316 you creating lots of DOM elements with JavaScript!
325 :mochidef:`NotFound`:
327 A singleton error raised when no suitable adapter is found
330 Available in MochiKit 1.3.1+
336 :mochidef:`AdapterRegistry`:
338 A registry to facilitate adaptation.
340 All ``check``/``wrap`` function pairs in a given registry should
341 take the same number of arguments.
344 Available in MochiKit 1.3.1+
347 :mochidef:`AdapterRegistry.prototype.register(name, check, wrap[, override])`:
350 a unique identifier used to identify this adapter so that it
354 function that should return ``true`` if the given arguments
355 are appropriate for the ``wrap`` function.
358 function that takes the same parameters as ``check`` and does
359 the adaptation. Every ``wrap``/``check`` function pair in the
360 registry should have the same number of arguments.
363 if ``true``, the ``check`` function will be
364 given highest priority. Otherwise, the lowest.
367 Available in MochiKit 1.3.1+
370 :mochidef:`AdapterRegistry.prototype.match(obj[, ...])`:
372 Find an adapter for the given arguments by calling every ``check``
373 function until one returns ``true``.
375 If no suitable adapter is found, throws :mochiref:`NotFound`.
378 Available in MochiKit 1.3.1+
381 :mochidef:`AdapterRegistry.prototype.unregister(name)`:
383 Remove a named adapter from the registry
386 Available in MochiKit 1.3.1+
389 :mochidef:`NamedError`:
391 Convenience constructor for creating new errors
392 (e.g. :mochiref:`NotFound`)
395 Available in MochiKit 1.3.1+
401 :mochidef:`arrayEqual(self, arr)`:
403 Compare the arrays ``self`` and ``arr`` for equality using
404 ``compare`` on each element. Uses a fast-path for length
408 Available in MochiKit 1.3.1+
411 :mochidef:`average(lst[, ...])`:
413 This function is an alias of :mochiref:`mean()`.
416 Available in MochiKit 1.3.1+
419 :mochidef:`bind(func, self[, arg, ...])`:
421 Return a copy of ``func`` bound to ``self``. This means whenever
422 and however the returned function is called, ``this`` will always
423 reference the given ``self``. ``func`` may be either a function
424 object, or a string. If it is a string, then ``self[func]`` will
425 be used, making these two statements equivalent::
427 bind("method", self);
428 bind(self.method, self);
430 Calling :mochiref:`bind(func, self)` on an already bound function
431 will return a new function that is bound to the new ``self``! If
432 ``self`` is ``undefined``, then the previous ``self`` is used. If
433 ``self`` is ``null``, then the ``this`` object is used (which may
434 or may not be the global object). To force binding to the global
435 object, you should pass it explicitly.
437 Additional arguments, if given, will be partially applied to the
438 function. These three expressions are equivalent and return
439 equally efficient functions (:mochiref:`bind` and
440 :mochiref:`partial` share the same code path):
442 - :mochiref:`bind(oldfunc, self, arg1, arg2)`
443 - :mochiref:`bind(partial(oldfunc, arg1, arg2), self)`
444 - :mochiref:`partial(bind(oldfunc, self), arg1, arg2)`
447 Available in MochiKit 1.3.1+
450 :mochidef:`bindMethods(self)`:
452 Replace all functions ``meth`` on ``self`` with
453 :mochiref:`bind(meth, self)`. This emulates Python's bound
454 instance methods, where there is no need to worry about preserving
455 ``this`` when the method is used as a callback.
458 Available in MochiKit 1.3.1+
461 :mochidef:`camelize(str)`:
463 Converts hyphenated strings to camelCase::
465 assert( camelize("border-left") == "borderLeft" );
468 Available in MochiKit 1.4+
471 :mochidef:`clone(obj)`:
473 Return a new object using ``obj`` as its prototype. Use this if
474 you want to return a mutable object (e.g. instance state), but
475 don't want the user to mutate it. If they do, it won't have any
476 effect on the original ``obj``.
478 Note that this is a shallow clone, so mutable properties will have
479 to be cloned separately if you want to "protect" them.
482 Available in MochiKit 1.3.1+
485 :mochidef:`compare(a, b)`:
487 Compare two objects in a sensible manner. Currently this is:
489 1. ``undefined`` and ``null`` compare equal to each other
490 2. ``undefined`` and ``null`` are less than anything else
491 3. If JavaScript says ``a == b``, then we trust it
492 4. comparators registered with registerComparator are used to
493 find a good comparator. Built-in comparators are currently
494 available for ``Array``-like and ``Date``-like objects.
495 5. Otherwise hope that the built-in comparison operators do
496 something useful, which should work for numbers and strings.
497 6. If neither ``a < b`` or ``a > b``, then throw a ``TypeError``
499 Returns what one would expect from a comparison function:
501 +-----------+---------------+
502 | Value | Condition |
503 +-----------+---------------+
504 | ``0`` | ``a == b`` |
505 +-----------+---------------+
506 | ``1`` | ``a > b`` |
507 +-----------+---------------+
508 | ``-1`` | ``a < b`` |
509 +-----------+---------------+
512 Available in MochiKit 1.3.1+
515 :mochidef:`compose(f1, f2, ..., fN)`:
517 Return a new function as the combination of the given function
518 arguments, equivalent to ``f1(f2(arguments))``.
521 Available in MochiKit 1.4+
524 :mochidef:`concat(lst[, ...])`:
526 Concatenates all given ``Array``-like arguments and returns
529 var lst = concat(["1","3","5"], ["2","4","6"]);
530 assert( lst.toString() == "1,3,5,2,4,6" );
533 Available in MochiKit 1.3.1+
536 :mochidef:`counter(n=1)`:
538 Returns a function that will return a number one greater than
539 the previous returned value, starting at ``n``. For example::
542 assert( nextId() == 1 )
543 assert( nextId() == 2 )
545 For an iterator with this behavior, see
546 :mochiref:`MochiKit.Iter.count`.
549 Available in MochiKit 1.3.1+
552 :mochidef:`extend(self, obj, skip=0)`:
554 Mutate the array ``self`` by extending it with an ``Array``-like
555 ``obj``, starting from index ``skip``. If ``null`` is given as the
556 initial array, a new one will be created.
558 This mutates *and returns* ``self``, be warned.
561 Available in MochiKit 1.3.1+
564 :mochidef:`evalJSON(aJSONString)`:
566 Unserialize a JSON [1]_ represenation of an object.
568 Note that this uses the ``eval`` function of the interpreter, and
569 therefore trusts the contents of ``aJSONString`` to be safe. This
570 is acceptable when the JSON and JavaScript application originate
571 from the same server, but in other scenarios it may not be the
572 appropriate security model. Currently, a validating JSON parser is
573 beyond the scope of MochiKit, but there is one available from
577 Available in MochiKit 1.3.1+
580 :mochidef:`filter(fn, lst)`:
582 Returns a new ``Array`` composed of all elements from ``lst``
583 where ``fn(lst[i])`` returns a true value.
585 If ``fn`` is ``null``, ``operator.truth`` will be used.
588 Available in MochiKit 1.3.1+
591 :mochidef:`findValue(lst, value, start=0, end=lst.length)`:
593 Finds the index of ``value`` in the ``Array``-like object ``lst``
594 using :mochiref:`compare`. The search starts at the index
595 ``start``, and ends at the index ``end - 1``. If ``value`` is not
596 found in ``lst``, it will return ``-1``.
600 assert( findValue([1, 2, 3, 2, 1], 2) == 1 )
601 assert( findValue([1, 2, 3, 2, 1], 2, 2) == 3 )
604 Available in MochiKit 1.3.1+
607 :mochidef:`findIdentical(lst, value, start=0, end=lst.length)`:
609 Finds the index of ``value`` in the ``Array``-like object ``lst``
610 using the ``===`` operator. The search starts at the index
611 ``start``, and ends at the index ``end - 1``. If ``value`` is not
612 found in ``lst``, it will return ``-1``.
614 You should use this function instead of :mochiref:`findValue` if
615 ``lst`` may be comprised of objects for which no comparator is
616 defined and all you care about is finding an identical object
617 (e.g. the same instance), or if ``lst`` is comprised of just
618 numbers or strings and performance is important.
622 assert( findIdentical([1, 2, 3, 2, 1], 2) == 1 )
623 assert( findIdentical([1, 2, 3, 2, 1], 2, 2) == 3 )
626 Available in MochiKit 1.3.1+
629 :mochidef:`flattenArguments(arg[, ...])`:
631 Given a bunch of arguments, return a single ``Array`` containing
632 all of those arguments. Any ``Array``-like argument will be extended
635 compare(flattenArguments(1, [2, 3, [4, 5]]), [1, 2, 3, 4, 5]) == 0
638 Available in MochiKit 1.3.1+
641 :mochidef:`flattenArray(lst)`:
643 Return a new ``Array`` consisting of every item in lst with ``Array``
644 items expanded in-place recursively. This differs from
645 :mochiref:`flattenArguments` in that it only takes one argument and
646 it only flattens items that are ``instanceof Array``.
648 compare(flattenArray([1, [2, 3, [4, 5]]]), [1, 2, 3, 4, 5]) == 0
651 Available in MochiKit 1.4+
654 :mochidef:`forwardCall(name)`:
656 Returns a function that forwards a method call to
660 Available in MochiKit 1.3.1+
663 :mochidef:`isArrayLike(obj[, ...])`:
665 Returns ``true`` if all given arguments are ``Array``-like (have a
666 ``.length`` property and ``typeof(obj) == 'object'``)
669 Available in MochiKit 1.3.1+
672 :mochidef:`isDateLike(obj[, ...])`:
674 Returns ``true`` if all given arguments are ``Date``-like (have a
675 ``.getTime()`` method)
678 Available in MochiKit 1.3.1+
681 :mochidef:`isEmpty(obj[, ...])`:
683 Returns ``true`` if all the given ``Array``-like or string
684 arguments are empty ``(obj.length == 0)``
687 Available in MochiKit 1.3.1+
690 :mochidef:`isNotEmpty(obj[, ...])`:
692 Returns ``true`` if all the given ``Array``-like or string
693 arguments are not empty ``(obj.length > 0)``
696 Available in MochiKit 1.3.1+
699 :mochidef:`isNull(obj[, ...])`:
701 Returns ``true`` if all arguments are ``null``.
704 Available in MochiKit 1.3.1+
707 :mochidef:`isUndefinedOrNull(obj[, ...])`:
709 Returns ``true`` if all arguments are undefined or ``null``
712 Available in MochiKit 1.3.1+
715 :mochidef:`itemgetter(name)`:
717 Returns a ``function(obj)`` that returns ``obj[name]``
720 Available in MochiKit 1.3.1+
723 :mochidef:`items(obj)`:
725 Return an ``Array`` of ``[propertyName, propertyValue]`` pairs for
726 the given ``obj`` (in the order determined by ``for propName in
730 Available in MochiKit 1.3.1+
733 :mochidef:`keyComparator(key[, ...])`:
735 A comparator factory that compares ``a[key]`` with ``b[key]``.
738 var lst = ["a", "bbb", "cc"];
739 lst.sort(keyComparator("length"));
740 assert( lst.toString() == "a,cc,bbb" );
743 Available in MochiKit 1.3.1+
746 :mochidef:`keys(obj)`:
748 Return an ``Array`` of the property names of an object (in the
749 order determined by ``for propName in obj``).
752 Available in MochiKit 1.3.1+
755 :mochidef:`listMax(lst)`:
757 Return the largest element of an ``Array``-like object, as
758 determined by :mochiref:`compare`. This is a special form of
759 :mochiref:`listMinMax`, specifically
760 :mochiref:`partial(listMinMax, 1)`.
763 Available in MochiKit 1.3.1+
766 :mochidef:`listMin(lst)`:
768 Return the smallest element of an ``Array``-like object, as
769 determined by :mochiref:`compare`. This is a special form of
770 :mochiref:`listMinMax`, specifically
771 :mochiref:`partial(listMinMax, -1)`.
774 Available in MochiKit 1.3.1+
777 :mochidef:`listMinMax(which, lst)`:
779 If ``which == -1`` then it will return the smallest element of the
780 ``Array``-like ``lst``. This is also available as
781 :mochiref:`listMin(lst)`.
783 If ``which == 1`` then it will return the largest element of the
784 ``Array``-like ``lst``. This is also available as
785 :mochiref:`listMax(list)`.
788 Available in MochiKit 1.3.1+
791 :mochidef:`map(fn, lst[, ...])`:
793 Return a new array composed of the results of ``fn(x)`` for every
796 If ``fn`` is ``null``, and only one sequence argument is given the
797 identity function is used.
799 :mochiref:`map(null, lst)` -> ``lst.slice()``;
801 If ``fn`` is not ``null`` and more than one sequence argument is
802 given, then one element from each sequence is used to build the
803 argument list for ``fn``.
805 :mochiref:`map(fn, p, q, ...)`
806 -> ``[fn(p[0], q[0], ..), fn(p[1], q[1], ...), ...]``
808 If ``fn`` is ``null``, and more than one sequence is given as
809 arguments, then the ``Array`` function is used, making it
810 equivalent to :mochiref:`MochiKit.Iter.zip`.
812 :mochiref:`map(null, p, q, ...)`
813 -> :mochiref:`MochiKit.Iter.zip(p, q, ...)`
814 -> ``[[p0, q0, ...], [p1, q1, ...], ...];``
817 Available in MochiKit 1.3.1+
820 :mochidef:`mean(lst[, ...])`:
822 Returns the arithmetic mean (average) of the argument list, or an array.
823 This function applies :mochiref:`flattenArguments()` to the argument list.
826 Available in MochiKit 1.4+
829 :mochidef:`median(lst[, ...])`:
831 Returns the median of the argument list, or an array. This function
832 applies :mochiref:`flattenArguments()` to the argument list.
835 Available in MochiKit 1.4+
838 :mochidef:`merge(obj[, ...])`:
840 Create a new instance of ``Object`` that contains every property
841 from all given objects. If a property is defined on more than one
842 of the objects, the last property is used.
844 This is a special form of :mochiref:`update(self, obj[, ...])`,
845 specifically, it is defined as :mochiref:`partial(update, null)`.
848 Available in MochiKit 1.3.1+
851 :mochidef:`method(self, func, ...)`:
853 Alternate form of :mochiref:`bind` that takes the object before
854 the function. These two calls are equivalent::
856 bind("method", myobject)
857 method(myobject, "method")
860 Available in MochiKit 1.3.1+
863 :mochidef:`methodcaller(name[, args...])`:
865 Return a new function that calls a method on its argument,
868 lst = map(methodcaller("toLowerCase"), ["THIS", "is", "LoWeRCaSe"]);
869 assert( lst.join(" ") == "this is lowercase" );
872 Available in MochiKit 1.4+
875 :mochidef:`nameFunctions(namespace)`:
877 Given a ``namespace`` (object or function) with a ``NAME``
878 property, find all methods in it and give them nice ``NAME``
879 properties too (for use with :mochiref:`repr`). e.g.::
885 nameFunctions(namespace);
886 assert( namespace.Dude.NAME == 'Awesome.Dude' );
889 Available in MochiKit 1.3.1+
894 A function that performs no operation. Use this where you would
895 otherwise use ``(function () {})`` in order to avoid Internet
896 Explorer cyclic garbage leakage.
899 Available in MochiKit 1.4
902 :mochidef:`objEqual(a, b)`:
904 Return ``true`` if ``compare(a, b) == 0``
907 Available in MochiKit 1.3.1+
910 :mochidef:`nodeWalk(node, visitor)`:
912 Non-recursive generic node walking function (e.g. for a DOM).
914 The walk order for nodeWalk is breadth first, meaning that all
915 siblings will be visited before any children.
918 The initial node to be searched.
921 The visitor function, will be called as ``visitor(node)``, and
922 should return an ``Array``-like of nodes to be searched next
923 (e.g. ``node.childNodes``). Leaf nodes may return ``null`` or
927 Available in MochiKit 1.3.1+
930 :mochidef:`objMax(obj[, ...])`:
932 Return the maximum object according to :mochiref:`compare` out of
933 the given arguments. This is similar to :mochiref:`listMax`,
934 except is uses the arguments instead of a given ``Array``-like.
937 Available in MochiKit 1.3.1+
940 :mochidef:`objMin(obj[, ...])`:
942 Return the minimum object according to :mochiref:`compare` out of
943 the given arguments. This is similar to :mochiref:`listMin`,
944 except it uses the arguments instead of a given ``Array``-like.
947 Available in MochiKit 1.3.1+
950 :mochidef:`operator`:
952 A table of JavaScript's operators for usage with :mochiref:`map`,
953 :mochiref:`filter`, etc.
956 Unary Logic Operators:
958 +--------------------+--------------------------+-------------------+
959 | Operator | Implementation | Description |
960 +====================+==========================+===================+
961 | ``truth(a)`` | ``!!a`` | Logical truth |
962 +--------------------+--------------------------+-------------------+
963 | ``lognot(a)`` | ``!a`` | Logical not |
964 +--------------------+--------------------------+-------------------+
965 | ``identity(a)`` | ``a`` | Logical identity |
966 +--------------------+--------------------------+-------------------+
970 Unary Math Operators:
972 +--------------------+--------------------------+---------------+
973 | Operator | Implementation | Description |
974 +====================+==========================+===============+
975 | ``not(a)`` | ``~a`` | Bitwise not |
976 +--------------------+--------------------------+---------------+
977 | ``neg(a)`` | ``-a`` | Negation |
978 +--------------------+--------------------------+---------------+
984 +-------------------+-------------------+-------------------------------+
985 | Operator | Implementation | Description |
986 +===================+===================+===============================+
987 | ``add(a, b)`` | ``a + b`` | Addition |
988 +-------------------+-------------------+-------------------------------+
989 | ``sub(a, b)`` | ``a - b`` | Subtraction |
990 +-------------------+-------------------+-------------------------------+
991 | ``div(a, b)`` | ``a / b`` | Division |
992 +-------------------+-------------------+-------------------------------+
993 | ``mod(a, b)`` | ``a % b`` | Modulus |
994 +-------------------+-------------------+-------------------------------+
995 | ``mul(a, b)`` | ``a * b`` | Multiplication |
996 +-------------------+-------------------+-------------------------------+
997 | ``and(a, b)`` | ``a & b`` | Bitwise and |
998 +-------------------+-------------------+-------------------------------+
999 | ``or(a, b)`` | ``a | b`` | Bitwise or |
1000 +-------------------+-------------------+-------------------------------+
1001 | ``xor(a, b)`` | ``a ^ b`` | Bitwise exclusive or |
1002 +-------------------+-------------------+-------------------------------+
1003 | ``lshift(a, b)`` | ``a << b`` | Bitwise left shift |
1004 +-------------------+-------------------+-------------------------------+
1005 | ``rshift(a, b)`` | ``a >> b`` | Bitwise signed right shift |
1006 +-------------------+-------------------+-------------------------------+
1007 | ``zrshift(a, b)`` | ``a >>> b`` | Bitwise unsigned right shift |
1008 +-------------------+-------------------+-------------------------------+
1012 Built-in Comparators:
1014 +---------------+-------------------+---------------------------+
1015 | Operator | Implementation | Description |
1016 +===============+===================+===========================+
1017 | ``eq(a, b)`` | ``a == b`` | Equals |
1018 +---------------+-------------------+---------------------------+
1019 | ``ne(a, b)`` | ``a != b`` | Not equals |
1020 +---------------+-------------------+---------------------------+
1021 | ``gt(a, b)`` | ``a > b`` | Greater than |
1022 +---------------+-------------------+---------------------------+
1023 | ``ge(a, b)`` | ``a >= b`` | Greater than or equal to |
1024 +---------------+-------------------+---------------------------+
1025 | ``lt(a, b)`` | ``a < b`` | Less than |
1026 +---------------+-------------------+---------------------------+
1027 | ``le(a, b)`` | ``a <= b`` | Less than or equal to |
1028 +---------------+-------------------+---------------------------+
1032 Strict Built-in Comparators:
1034 +---------------+-------------------+---------------------------+
1035 | Operator | Implementation | Description |
1036 +===============+===================+===========================+
1037 | ``seq(a, b)`` | ``a === b`` | Strict equals |
1038 +---------------+-------------------+---------------------------+
1039 | ``sne(a, b)`` | ``a !== b`` | Strict not equals |
1040 +---------------+-------------------+---------------------------+
1044 Extended Comparators (uses :mochiref:`compare`):
1046 +---------------+---------------------------+---------------------------+
1047 | Operator | Implementation | Description |
1048 +===============+===========================+===========================+
1049 | ``ceq(a, b)`` | ``compare(a, b) == 0`` | Equals |
1050 +---------------+---------------------------+---------------------------+
1051 | ``cne(a, b)`` | ``compare(a, b) != 0`` | Not equals |
1052 +---------------+---------------------------+---------------------------+
1053 | ``cgt(a, b)`` | ``compare(a, b) == 1`` | Greater than |
1054 +---------------+---------------------------+---------------------------+
1055 | ``cge(a, b)`` | ``compare(a, b) != -1`` | Greater than or equal to |
1056 +---------------+---------------------------+---------------------------+
1057 | ``clt(a, b)`` | ``compare(a, b) == -1`` | Less than |
1058 +---------------+---------------------------+---------------------------+
1059 | ``cle(a, b)`` | ``compare(a, b) != 1`` | Less than or equal to |
1060 +---------------+---------------------------+---------------------------+
1064 Binary Logical Operators:
1066 +-----------------------+-------------------+---------------------------+
1067 | Operator | Implementation | Description |
1068 +=======================+===================+===========================+
1069 | ``logand(a, b)`` | ``a && b`` | Logical and |
1070 +-----------------------+-------------------+---------------------------+
1071 | ``logor(a, b)`` | ``a || b`` | Logical or |
1072 +-----------------------+-------------------+---------------------------+
1073 | ``contains(a, b)`` | ``b in a`` | Has property (note order) |
1074 +-----------------------+-------------------+---------------------------+
1077 Available in MochiKit 1.3.1+
1080 :mochidef:`parseQueryString(encodedString[, useArrays=false])`:
1082 Parse a name=value pair URL query string into an object with a
1083 property for each pair. e.g.::
1085 var args = parseQueryString("foo=value%20one&bar=two");
1086 assert( args.foo == "value one" && args.bar == "two" );
1088 If you expect that the query string will reuse the same name, then
1089 give ``true`` as a second argument, which will use arrays to store
1092 var args = parseQueryString("foo=one&foo=two", true);
1093 assert( args.foo[0] == "one" && args.foo[1] == "two" );
1096 Available in MochiKit 1.3.1+
1099 :mochidef:`partial(func, arg[, ...])`:
1101 Return a partially applied function, e.g.::
1103 addNumbers = function (a, b) {
1107 addOne = partial(addNumbers, 1);
1109 assert(addOne(2) == 3);
1111 :mochiref:`partial` is a special form of :mochiref:`bind` that
1112 does not alter the bound ``self`` (if any). It is equivalent to
1115 bind(func, undefined, arg[, ...]);
1117 See the documentation for :mochiref:`bind` for more details about
1120 This could be used to implement, but is NOT currying.
1123 Available in MochiKit 1.3.1+
1126 :mochidef:`queryString(names, values)`:
1128 Creates a URL query string from a pair of ``Array``-like objects
1129 representing ``names`` and ``values``. Each name=value pair will
1130 be URL encoded by :mochiref:`urlEncode`. name=value pairs with a
1131 value of ``undefined`` or ``null`` will be skipped. e.g.::
1133 var keys = ["foo", "bar"];
1134 var values = ["value one", "two"];
1135 assert( queryString(keys, values) == "foo=value%20one&bar=two" );
1138 :mochiref:`queryString(domElement)`
1140 If :mochiref:`MochiKit.DOM` is loaded, one argument is given, and
1141 that argument is either a string or has a ``nodeType`` property
1142 greater than zero, then ``names`` and ``values`` will be the
1143 result of :mochiref:`MochiKit.DOM.formContents(domElement)`.
1146 :mochiref:`queryString({name: value, ...})`
1148 Note that when using the alternate form, the order of the
1149 name=value pairs in the resultant query string is dependent on how
1150 the particular JavaScript implementation handles ``for (..in..)``
1151 property enumeration.
1153 When using the second alternate form, name=value pairs with
1154 ``typeof(value) == "function"`` are ignored. This is a workaround
1155 for the case where a poorly designed library has modified
1156 ``Object.prototype`` and inserted "convenience functions".
1158 Values that are Array-like will be expanded as if they were multiply
1159 defined HTML elements. For example::
1161 assert( queryString({a: [1,2]}) === "a=1&a=2" );
1163 Alternate form 2 (MochiKit 1.4+):
1164 :mochiref:`queryString([names, values])`
1166 This form behaves identically to :mochiref:`queryString(names, values)`,
1167 except it takes both arguments as a single Array. This mirrors the
1168 return value of :mochiref:`MochiKit.DOM.formContents`.
1171 Available in MochiKit 1.3.1+
1174 :mochidef:`registerComparator(name, check, comparator[, override])`:
1176 Register a comparator for use with :mochiref:`compare`.
1179 unique identifier describing the comparator.
1182 ``function(a, b)`` that returns ``true`` if ``a`` and ``b``
1183 can be compared with ``comparator``.
1186 ``function(a, b)`` that returns:
1188 +-------+-----------+
1189 | Value | Condition |
1190 +-------+-----------+
1192 +-------+-----------+
1194 +-------+-----------+
1196 +-------+-----------+
1198 ``comparator`` is guaranteed to only be called if ``check(a,
1199 b)`` returns a ``true`` value.
1202 if ``true``, then this will be made the highest precedence
1203 comparator. Otherwise, the lowest.
1206 Available in MochiKit 1.3.1+
1209 :mochidef:`registerJSON(name, check, simplifier[, override])`:
1211 Register a simplifier function for use with
1212 :mochiref:`serializeJSON`.
1215 unique identifier describing the serialization.
1218 ``function(obj)`` that returns ``true`` if ``obj`` can
1219 can be simplified for serialization by ``simplifier``.
1222 ``function(obj)`` that returns a simpler object that can be
1223 further serialized by :mochiref:`serializeJSON`. For example,
1224 you could simplify ``Date``-like objects to ISO 8601 timestamp
1225 strings with the following simplifier::
1227 var simplifyDateAsISO = function (obj) {
1228 return toISOTimestamp(obj, true);
1230 registerJSON("DateLike", isDateLike, simplifyDateAsISO);
1232 ``simplifier`` is guaranteed to only be called if
1233 ``check(obj)`` returns a ``true`` value.
1236 if ``true``, then this will be made the highest precedence
1237 serialization. Otherwise, the lowest.
1240 Available in MochiKit 1.3.1+
1243 :mochidef:`registerRepr(name, check, wrap[, override])`:
1245 Register a programmer representation function. :mochiref:`repr`
1246 functions should take one argument and return a string
1247 representation of it suitable for developers, primarily used when
1250 If ``override`` is given, it is used as the highest priority repr,
1251 otherwise it will be used as the lowest.
1254 Available in MochiKit 1.3.1+
1257 :mochidef:`repr(obj)`:
1259 Return a programmer representation for ``obj``. See the
1260 `Programmer Representation`_ overview for more information about
1264 Available in MochiKit 1.3.1+
1267 :mochidef:`reverseKeyComparator(key)`:
1269 A comparator factory that compares ``a[key]`` with ``b[key]`` in
1272 var lst = ["a", "bbb", "cc"];
1273 lst.sort(reverseKeyComparator("length"));
1274 assert(lst.toString() == "bbb,cc,a");
1277 Available in MochiKit 1.3.1+
1280 :mochidef:`serializeJSON(anObject)`:
1282 Serialize ``anObject`` in the JSON [1]_ format, see `JSON
1283 Serialization`_ for the coercion rules. For unserializable objects
1284 (functions that do not have an adapter, ``__json__`` method, or
1285 ``json`` method), this will return ``undefined``.
1287 For those familiar with Python, JSON is similar in scope to
1288 pickle, but it can not handle recursive object graphs.
1291 Available in MochiKit 1.3.1+
1294 :mochidef:`setdefault(self, obj[, ...])`:
1296 Mutate ``self`` by adding all properties from other object(s) that
1297 it does not already have set.
1299 If ``self`` is ``null``, a new ``Object`` instance will be created
1302 This mutates *and returns* ``self``, be warned.
1305 Available in MochiKit 1.3.1+
1308 :mochidef:`typeMatcher(typ[, ...])`:
1310 Given a set of types (as string arguments), returns a
1311 ``function(obj[, ...])`` that will return ``true`` if the types of
1312 the given arguments are all members of that set.
1315 Available in MochiKit 1.3.1+
1318 :mochidef:`update(self, obj[, ...])`:
1320 Mutate ``self`` by replacing its key:value pairs with those from
1321 other object(s). Key:value pairs from later objects will overwrite
1322 those from earlier objects.
1324 If ``self`` is ``null``, a new ``Object`` instance will be created
1327 This mutates *and returns* ``self``, be warned.
1329 A version of this function that creates a new object is available
1330 as :mochiref:`merge(a, b[, ...])`
1333 Available in MochiKit 1.3.1+
1336 :mochidef:`updatetree(self, obj[, ...])`:
1338 Mutate ``self`` by replacing its key:value pairs with those from
1339 other object(s). If a given key has an object value in both
1340 ``self`` and ``obj``, then this function will be called
1341 recursively, updating instead of replacing that object.
1343 If ``self`` is ``null``, a new ``Object`` instance will be created
1346 This mutates *and returns* ``self``, be warned.
1349 Available in MochiKit 1.3.1+
1352 :mochidef:`urlEncode(unencoded)`:
1354 Converts ``unencoded`` into a URL-encoded string. In this
1355 implementation, spaces are converted to %20 instead of "+". e.g.::
1357 assert( URLencode("1+2=2") == "1%2B2%3D2");
1360 Available in MochiKit 1.3.1+
1363 :mochidef:`values(obj)`:
1365 Return an ``Array`` of the property values of an object (in the
1366 order determined by ``for propName in obj``).
1369 Available in MochiKit 1.4+
1372 :mochidef:`xfilter(fn, obj[, ...])`:
1374 Returns a new ``Array`` composed of the arguments where
1375 ``fn(obj)`` returns a true value.
1377 If ``fn`` is ``null``, ``operator.truth`` will be used.
1380 Available in MochiKit 1.3.1+
1383 :mochidef:`xmap(fn, obj[, ...)`:
1385 Return a new ``Array`` composed of ``fn(obj)`` for every ``obj``
1386 given as an argument.
1388 If ``fn`` is ``null``, ``operator.identity`` is used.
1391 Available in MochiKit 1.3.1+
1397 .. [1] JSON, JavaScript Object Notation: http://json.org/
1398 .. [2] Python's itertools
1399 module: http://docs.python.org/lib/module-itertools.html
1404 - Bob Ippolito <bob@redivi.com>
1410 Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is
1411 dual-licensed free software; you can redistribute it and/or modify it
1412 under the terms of the `MIT License`_ or the `Academic Free License
1415 .. _`MIT License`: http://www.opensource.org/licenses/mit-license.php
1416 .. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php