UNPKG

@nodeguy/generic

Version:
116 lines (84 loc) 3.72 kB
# Generic Functions for JavaScript It's time to bring something <s>new</s> old to JavaScript: generic functions! # Why? Polymorphism in JavaScript is changing: * ES 2015 brought an important new interface, the [Iterable](http://www.ecma-international.org/ecma-262/6.0/index.html#sec-iterable-interface), which isn't a type so you can't use inheritance with it. * After getting `Object.create` added to the language, [Douglas Crockford doesn't use it any more](https://www.youtube.com/watch?v=bo36MrBfTk4&feature=youtu.be&t=18m54s). * Object Oriented Programming is dead. [Yes](http://lists.squeakfoundation.org/pipermail/squeak-dev/1998-October/017019.html) [sweetheart](https://commandcenter.blogspot.com/2012/06/less-is-exponentially-more.html), [it](https://en.wikipedia.org/wiki/Composition_over_inheritance) [really](http://www.catb.org/esr/writings/taoup/html/unix_and_oo.html) [is](https://www.infoq.com/presentations/Simple-Made-Easy). Loosen your white knuckles and let it go. That's it, nice and easy. Exhale. # What are Generic Functions? Generic functions were popularized in the [Common Lisp Object System](https://en.wikipedia.org/wiki/Common_Lisp_Object_System), published in 1988. A generic function has a single signature (or interface) and multiple implementations, called methods. Unlike in OOP, the methods are specialized across all of the function arguments, not just the first one. For example, the signature may be: ```JavaScript map(mapper, collection) ``` It may have different implementations based on the type of the collection: ```JavaScript const mapMethod = (callback, array) => array.map(callback); const mapMethod = (callback, set) => new Set([...set].map(callback)); ``` It may also have a method that takes a lookup table instead of a callback function: ```JavaScript const mapMethod = (table, array) => array.map((value) => table[value]); ``` In fact we could support lookup tables for every type of collection by adding a method that calls itself recursively like this: ```JavaScript const mapMethod = (table, collection) => map((value) => table[value], collection); ``` # Usage Here's how you could implement the above example using the library. ```JavaScript const assert = require(`@nodeguy/assert`); const generic = require('@nodeguy/generic') const _ = generic._; const map = generic.function(); map.method([m => typeof m === "function", Array.isArray], (callback, array) => array.map(callback) ); map.method( [m => typeof m === "function", c => c instanceof Set], (callback, set) => new Set([...set].map(callback)) ); map.method([m => typeof m === "object", _], (table, collection) => map(value => table[value], collection) ); assert.deepEqual(map(Math.sqrt, [1, 4, 9]), [1, 2, 3]); assert.deepEqual(map(Math.sqrt, new Set([1, 4, 9])), new Set([1, 2, 3])); assert.deepEqual(map({ 1: 1, 4: 2, 9: 3 }, [1, 4, 9]), [1, 2, 3]); assert.deepEqual( map({ 1: 1, 4: 2, 9: 3 }, new Set([1, 4, 9])), new Set([1, 2, 3]) ); ``` See `test/index.js` for more usage examples. # Installation `$ npm install @nodeguy/generic` # Copyright Copyright 2016 [David Braun](https://www.NodeGuy.com/) Licensed under the Apache License, Version 2.0 (the "License"); you may not use these files except in compliance with the License. You may obtain a copy of the License at `http://www.apache.org/licenses/LICENSE-2.0`. Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.