|
| 1 | +# ProtocolJS |
| 2 | + |
| 3 | +ProtocolJS ports the concept of protocols found in Clojure to JavaScript. |
| 4 | + |
| 5 | +## Inspiration and Attribution |
| 6 | + |
| 7 | +ProtocolJS is an informal fork of [Gozala's protocol module](https://github.com/Gozala/protocol) |
| 8 | +with some variation in implementation to |
| 9 | + |
| 10 | +- Make it compatible across more browsers. |
| 11 | +- Make it more robust to using serialized objects with the library between runtime restarts. |
| 12 | +- Reflect small differences in coding style. |
| 13 | + |
| 14 | +## Installation |
| 15 | + |
| 16 | +``` |
| 17 | +$ npm install protocoljs |
| 18 | +``` |
| 19 | + |
| 20 | +## Documentation |
| 21 | + |
| 22 | +A protocol is a set of function interfaces. |
| 23 | + |
| 24 | +```javascript |
| 25 | +var protocol = require('protocoljs'); |
| 26 | + |
| 27 | +var Enumerable = protocol({ |
| 28 | + first: [protocol] // Here protocol is a placeholder for the typed argument |
| 29 | +, rest: [protocol] |
| 30 | +, repeat: [Number, protocol] // The typed argument does not need to be first |
| 31 | +}); |
| 32 | +``` |
| 33 | + |
| 34 | +Protocols enable polymorphism in a flexible way where the interface definition |
| 35 | +is decoupled from the implementations for any number of types. |
| 36 | + |
| 37 | +```javascript |
| 38 | +Enumerable(Array, { |
| 39 | + first: function (array) { |
| 40 | + return array[0]; |
| 41 | + } |
| 42 | +, rest: function (array) { |
| 43 | + return array.slice(1); |
| 44 | + } |
| 45 | +, repeat: function (times, array) { |
| 46 | + var result = []; |
| 47 | + while (times--) { |
| 48 | + result = result.concat(array); |
| 49 | + } |
| 50 | + return result; |
| 51 | + } |
| 52 | +}); |
| 53 | + |
| 54 | +Enumerable.first([1, 2, 3]); // => 1 |
| 55 | +Enumerable.rest([1, 2, 3]); // => [2, 3] |
| 56 | +Enumerable.repeat(2, [1, 2, 3]); // => [1, 2, 3, 1, 2, 3] |
| 57 | +``` |
| 58 | + |
| 59 | +You can tie any number of types to a protocol. |
| 60 | + |
| 61 | +```javascript |
| 62 | +Enumerable(String, { |
| 63 | + first: function (string) { |
| 64 | + return string.charAt(0); |
| 65 | + } |
| 66 | +, rest: function (string) { |
| 67 | + return string.substring(1); |
| 68 | + } |
| 69 | +, repeat: function (times, string) { |
| 70 | + var result = ''; |
| 71 | + while (times--) { |
| 72 | + result += string; |
| 73 | + } |
| 74 | + return result; |
| 75 | + } |
| 76 | +}); |
| 77 | + |
| 78 | +Enumerable.first('abc'); => 'a' |
| 79 | +Enumerable.rest('abc'); => 'bc' |
| 80 | +Enumerable.repeat(2, 'abc'); => 'abcabc' |
| 81 | +``` |
| 82 | + |
| 83 | +You can also tie any number of protocols to a type. |
| 84 | + |
| 85 | +```javascript |
| 86 | +var RightEnumerable = protocol({ |
| 87 | + first: [protocol] |
| 88 | +, rest: [protocol] |
| 89 | +}); |
| 90 | + |
| 91 | +RightEnumerable(String, { |
| 92 | + first: function (string) { |
| 93 | + return string.charAt(string.length-1); |
| 94 | + } |
| 95 | +, rest: function (string) { |
| 96 | + return string.substring(0, string.length-1); |
| 97 | + } |
| 98 | +}); |
| 99 | + |
| 100 | +RightEnumerable.first('abc'); // => 'c' |
| 101 | +RightEnumerable.rest('abc'); // => 'ab' |
| 102 | +``` |
| 103 | + |
| 104 | +Finally, you can re-open protocols and extend their interfaces. |
| 105 | + |
| 106 | +```javascript |
| 107 | +protocol(Enumerable, { |
| 108 | + slice: [protocol, Number, Number] |
| 109 | +}); |
| 110 | + |
| 111 | +Enumerable(Array, { |
| 112 | + slice: function (array, start, end) { |
| 113 | + return array.slice(start, end); |
| 114 | + } |
| 115 | +}); |
| 116 | + |
| 117 | +Enumerable(String, { |
| 118 | + slice: function (string, start, end) { |
| 119 | + return string.substring(start, end); |
| 120 | + } |
| 121 | +}); |
| 122 | + |
| 123 | +Enumerable.slice([1, 2, 3], 0, 2); => [1, 2] |
| 124 | +Enumerable.slice('abc', 0, 2); => 'ab' |
| 125 | +``` |
| 126 | + |
| 127 | +### MIT License |
| 128 | +Copyright (c) 2011 by Brian Noguchi and Nate Smith |
| 129 | + |
| 130 | +Permission is hereby granted, free of charge, to any person obtaining a copy |
| 131 | +of this software and associated documentation files (the "Software"), to deal |
| 132 | +in the Software without restriction, including without limitation the rights |
| 133 | +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 134 | +copies of the Software, and to permit persons to whom the Software is |
| 135 | +furnished to do so, subject to the following conditions: |
| 136 | + |
| 137 | +The above copyright notice and this permission notice shall be included in |
| 138 | +all copies or substantial portions of the Software. |
| 139 | + |
| 140 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 141 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 142 | +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 143 | +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 144 | +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 145 | +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| 146 | +THE SOFTWARE. |
0 commit comments