{ "name": "method", "id": "method", "version": "2.0.0", "description": "Functional polymorphic method dispatch", "keywords": [ "method", "dispatch", "protocol", "polymorphism", "type dispatch" ], "author": { "name": "Irakli Gozalishvili", "email": "rfobic@gmail.com", "url": "http://jeditoolkit.com" }, "homepage": "https://github.com/Gozala/method", "main": "./core.js", "repository": { "type": "git", "url": "https://github.com/Gozala/method.git", "web": "https://github.com/Gozala/method" }, "bugs": { "url": "http://github.com/Gozala/method/issues/" }, "devDependencies": { "test": "~0.x.0", "phantomify": "~0.x.0", "retape": "~0.x.0", "tape": "~0.1.5" }, "scripts": { "test": "npm run test-node && npm run test-browser && npm run test-tap", "test-browser": "node ./node_modules/phantomify/bin/cmd.js ./test/phantom-index.js", "test-node": "node ./test/common-index.js", "test-tap": "node ./test/tap-index.js" }, "testling": { "files": "test/testling-index.js", "browsers": { "iexplore": [ 6, 7, 8, 9, 10 ], "chrome": [ 16, 20, 25, "canary" ], "firefox": [ 10, 15, 16, 17, 18, 19, "nightly" ], "safari": [ 5, 6 ], "opera": [ 10, 11, 12, "next" ], "iphone": [ 6 ], "ipad": [ 6 ] } }, "licenses": [ { "type": "MIT", "url": "https://github.com/Gozala/method/License.md" } ], "readme": "# method\n\n[![Build Status](https://secure.travis-ci.org/Gozala/method.png)](http://travis-ci.org/Gozala/method)\n\n\n[![Browser support](http://ci.testling.com/Gozala/method.png)](http://ci.testling.com/Gozala/method)\n\n\nLibrary provides an API for defining polymorphic methods that dispatch on the\nfirst argument type. This provides a powerful way for decouple abstraction\ninterface definition from an actual implementations per type / instance,\nwithout risks of interference with other libraries.\n\n### Motivation\n\n - Provide a high-performance, dynamic polymorphism construct as an\n alternative to existing object methods that does not provides any\n mechanics for guarding against name conflicts.\n - Allow independent extension of types, and implementations of methods\n on types, by different parties.\n\n## Install\n\n npm install method\n\n## Use\n\n```js\nvar method = require(\"method\")\n\n// Define `isWatchable` method that can be implemented for any type.\n// Use some UNIQUE identifer for the method to avoid any naming collisions.\n// If not provided one will be generate but with npm it's easy to end up\n// with copies of same library and there for copies of the same function\n// leading to surprises. So just really pick a name that is unique!\nvar isWatchable = method(\"isWatchable@watchables\")\n\n// If you call it on any object it will\n// throw as nothing implements that method yet.\n//isWatchable({}) // => Exception: method is not implemented\n\n// If you define private method on `Object.prototype`\n// all objects will inherit it.\nObject.prototype[isWatchable] = function() {\n return false;\n}\n\nisWatchable({}) // => false\n\n\n// Although `isWatchable` property above will be enumerable and there for\n// may damage some assumbtions made by other libraries. There for it\"s\n// recomended to use built-in helpers methods that will define extension\n// without breaking assumbtions made by other libraries:\n\nisWatchable.define(Object, function() { return false })\n\n\n// There are primitive types in JS that won\"t inherit methods from Object:\nisWatchable(null) // => Exception: method is not implemented\n\n// One could either implement methods for such types:\nisWatchable.define(null, function() { return false })\nisWatchable.define(undefined, function() { return false })\n\n// Or simply define default implementation:\nisWatchable.define(function() { return false })\n\n// Alternatively default implementation may be provided at creation:\nisWatchable = method(function() { return false })\n\n// Method dispatches on an first argument type. That allows us to create\n// new types with an alternative implementations:\nfunction Watchable() {}\nisWatchable.define(Watchable, function() { return true })\n\n// This will make all `Watchable` instances watchable!\nisWatchable(new Watchable()) // => true\n\n// Arbitrary objects can also be extended to implement given method. For example\n// any object can simply made watchable:\nfunction watchable(object) {\n return isWatchable.implement(objct, function() { return true })\n}\n\nisWatchable(watchable({})) // => true\n\n// Full protocols can be defined with such methods:\nvar observers = \"observers@\" + module.filename\nvar watchers = method(\"watchers@watchables\")\nvar watch = method(\"watch@watchables\")\nvar unwatch = method(\"unwatch@watchables\")\n\nwatchers.define(Watchable, function(target) {\n return target[observers] || (target[observers] = [])\n})\n\nwatch.define(Watchable, function(target, watcher) {\n var observers = watchers(target)\n if (observers.indexOf(watcher) < 0) observers.push(watcher)\n return target\n})\nunwatch.define(Watchable, function(target, watcher) {\n var observers = watchers(target)\n var index = observers.indexOf(watcher)\n if (observers.indexOf(watcher) >= 0) observers.unshift(watcher)\n return target\n})\n\n// Define type Port that inherits form Watchable\n\nfunction Port() {}\nPort.prototype = Object.create(Watchable.prototype)\n\nvar emit = method(\"emit\")\nemit.define(Port, function(port, message) {\n watchers(port).slice().forEach(function(watcher) {\n watcher(message)\n })\n})\n\nvar p = new Port()\nwatch(p, console.log)\nemit(p, \"hello world\") // => info: \"hello world\"\n```\n", "readmeFilename": "Readme.md", "_id": "method@2.0.0", "_from": "method@2" }