diff --git a/build/immutable.js b/build/immutable.js index 822a2d4..ed711ef 100644 --- a/build/immutable.js +++ b/build/immutable.js @@ -1 +1 @@ -!function(e){if("function"==typeof bootstrap)bootstrap("immutable",e);else if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeImmutable=e}else"undefined"!=typeof window?window.immutable=e():global.immutable=e()}(function(){var define,ses,bootstrap,module,exports;return function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s=0;i-=1)if(a.has(i))return i};module.exports.prototype=array.prototype={constructor:module.exports,map:function(fn){var result=this;for(var i=0,len=this.length;i=0;i-=1){if(this.has(i))seed=fn(seed,this.get(i),i.toString(),this)}return seed},push:function(v){return this.assoc(this.length,v)},indexOf:function(v){for(var i=0,len=this.length;i6)return makeHashmap();else return makeTrie()},hashmap:function(node,key,val,opts,depth){var v=copyAdd(node.values,key,Value(key,val));return Hashmap(v)}};var copyDissoc=function(obj,key){obj=util.clone(obj);delete obj[key];return obj};lib.dissoc=function(node,key,opts){return dissoc(node,key,opts||defaultOpts,0)};var dissoc=function(node,key,opts,depth){return dissocFns[node.type](node,key,opts,depth)};var dissocFns={trie:function(node,key,opts,depth){var path=hash.mask(key,depth,opts.hash);var child=node.children[path];var dissocKey=function(){if(child.type==="value"&&opts.eq(child.key,key))return Trie(copyDissoc(node.children,path));else return Trie(copyDissoc(node.children,path,dissoc(child,key,opts,depth+1)))};var collapseTrie=function(trie){var names=util.keys(trie.children);var child=trie.children[names[0]];if(depth===0)return trie;else if(child===undefined)return trie;else if(names.length===1&&child.type==="value")return Value(child.key,child.value);else return trie};var handleTrie=function(){return collapseTrie(dissocKey(node))};if(child===undefined)return node;else return handleTrie()},value:function(){},hashmap:function(node,key,opts,depth){var ret=copyDissoc(node.values,key);var names=util.keys(ret);var child=ret[names[0]];if(names.length===1)return Value(child.key,child.value);else return Hashmap(ret)}};lib.has=function(trie,key,opts){return has(trie,key,opts||defaultOpts,0)};var has=function(trie,key,opts,depth){return hasFns[trie.type](trie,key,opts,depth)};var hasFns={trie:function(node,key,opts,depth){var child=node.children[hash.mask(key,depth,opts.hash)];if(child===undefined)return false;else return has(child,key,opts,depth+1)},value:function(node,key,opts){return opts.eq(node.key,key)},hashmap:function(node,key,opts){return key in node.values}};lib.get=function(trie,key,opts){return get(trie,key,opts||defaultOpts,0)};var get=function(trie,key,opts,depth){return getFns[trie.type](trie,key,opts,depth)};var getFns={trie:function(node,key,opts,depth){var child=node.children[hash.mask(key,depth,opts.hash)];if(child===undefined)return undefined;else return get(child,key,opts,depth+1)},value:function(node,key,opts,depth){if(opts.eq(node.key,key))return node.value},hashmap:function(node,key,opts,depth){var value=node.values[key];return value?value.value:undefined}};lib.reduce=function(node,callback,initial){var state=reduce(node,callback,initial);return state instanceof Break?state.value:state};var reduce=function(node,callback,initial){return reduceFns[node.type](node,callback,initial)};var reduceFns={trie:function(node,callback,state){for(var path in node.children){if(node.children.hasOwnProperty(path)){state=reduce(node.children[path],callback,state)}if(state instanceof Break)break}return state},value:function(node,callback,state){return callback(state,node.value,node.key)},hashmap:function(node,callback,state){for(var key in node.values){if(node.values.hasOwnProperty(key)){state=reduce(node.values[key],callback,state)}if(state instanceof Break)break}return state}};var Break=lib.reduce.Break=function(v){if(!(this instanceof Break))return new Break(v);this.value=v};lib.mutable=function(node){return lib.reduce(node,addKeyVal,{})};var addKeyVal=function(o,val,key){o[key]=val;return o};lib.keys=function(node){return lib.reduce(node,addKey,[])};var addKey=function(arr,val,key){arr.push(key);return arr}},{"./util":6,"./hash":7}],6:[function(require,module,exports){"use strict";var extend=function(t,f){for(var p in f)t[p]=f[p];return t};var clone=function(o){return extend({},o)};var slice=function(a,f,n){return[].slice.call(a,f,n)};var mapObj=function(o,fn){var r={};for(var p in o)r[p]=fn(o[p],p,o);return r};var map=function(arr,fn){var a=[];for(var i=0,l=arr.length;i>>from&31};var hashMask=function(str,from,hash){return mask(hash(str),from)};module.exports={hash:require("string-hash"),mask:hashMask}},{"string-hash":8}],8:[function(require,module,exports){module.exports=function(str){var hash=5381,i=str.length;while(i)hash=hash*33^str.charCodeAt(--i);return hash>=0?hash:(hash&2147483647)+2147483648}},{}]},{},[1])(1)}); \ No newline at end of file +!function(e){if("function"==typeof bootstrap)bootstrap("immutable",e);else if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else if("undefined"!=typeof ses){if(!ses.ok())return;ses.makeImmutable=e}else"undefined"!=typeof window?window.immutable=e():global.immutable=e()}(function(){var define,ses,bootstrap,module,exports;return function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s=0;i-=1)if(a.has(i))return i};module.exports.prototype=array.prototype={constructor:module.exports,map:function(fn){var result=this;for(var i=0,len=this.length;ithis.length-1?this.length-1:end;var arr=(new array).assoc(util.range(lowEnd,highEnd-1));var ref=this;return arr.map(function(e){return ref.get(e)})},concat:function(arr){var details=function(seed,val,key,array){return seed.push(val)};var additional=Array.isArray(arr)?(new array).assoc(arr):arr;if(additional.mutable==undefined||Array.isArray(additional.mutable())==false){return this}return additional.reduce(details,this)},flatMap:function(fn){var details=function(seed,val,key,array){if(Array.isArray(val)||val.mutable!=undefined&&Array.isArray(val.mutable())){return seed.concat(val.map(fn))}else return seed};return this.reduce(details,new array)},reduceRight:function(fn,seed){if(arguments.length===1){var member=lastMember(this);return this.dissoc(member).reduceRight(fn,this.get(member))}for(var i=this.length-1;i>=0;i-=1){if(this.has(i))seed=fn(seed,this.get(i),i.toString(),this)}return seed},push:function(v){return this.assoc(this.length,v)},indexOf:function(v){for(var i=0,len=this.length;i6)return makeHashmap();else return makeTrie()},hashmap:function(node,key,val,opts,depth){var v=copyAdd(node.values,key,Value(key,val));return Hashmap(v)}};var copyDissoc=function(obj,key){obj=util.clone(obj);delete obj[key];return obj};lib.dissoc=function(node,key,opts){return dissoc(node,key,opts||defaultOpts,0)};var dissoc=function(node,key,opts,depth){return dissocFns[node.type](node,key,opts,depth)};var dissocFns={trie:function(node,key,opts,depth){var path=hash.mask(key,depth,opts.hash);var child=node.children[path];var dissocKey=function(){if(child.type==="value"&&opts.eq(child.key,key))return Trie(copyDissoc(node.children,path));else return Trie(copyDissoc(node.children,path,dissoc(child,key,opts,depth+1)))};var collapseTrie=function(trie){var names=util.keys(trie.children);var child=trie.children[names[0]];if(depth===0)return trie;else if(child===undefined)return trie;else if(names.length===1&&child.type==="value")return Value(child.key,child.value);else return trie};var handleTrie=function(){return collapseTrie(dissocKey(node))};if(child===undefined)return node;else return handleTrie()},value:function(){},hashmap:function(node,key,opts,depth){var ret=copyDissoc(node.values,key);var names=util.keys(ret);var child=ret[names[0]];if(names.length===1)return Value(child.key,child.value);else return Hashmap(ret)}};lib.has=function(trie,key,opts){return has(trie,key,opts||defaultOpts,0)};var has=function(trie,key,opts,depth){return hasFns[trie.type](trie,key,opts,depth)};var hasFns={trie:function(node,key,opts,depth){var child=node.children[hash.mask(key,depth,opts.hash)];if(child===undefined)return false;else return has(child,key,opts,depth+1)},value:function(node,key,opts){return opts.eq(node.key,key)},hashmap:function(node,key,opts){return key in node.values}};lib.get=function(trie,key,opts){return get(trie,key,opts||defaultOpts,0)};var get=function(trie,key,opts,depth){return getFns[trie.type](trie,key,opts,depth)};var getFns={trie:function(node,key,opts,depth){var child=node.children[hash.mask(key,depth,opts.hash)];if(child===undefined)return undefined;else return get(child,key,opts,depth+1)},value:function(node,key,opts,depth){if(opts.eq(node.key,key))return node.value},hashmap:function(node,key,opts,depth){var value=node.values[key];return value?value.value:undefined}};lib.reduce=function(node,callback,initial){var state=reduce(node,callback,initial);return state instanceof Break?state.value:state};var reduce=function(node,callback,initial){return reduceFns[node.type](node,callback,initial)};var reduceFns={trie:function(node,callback,state){for(var path in node.children){if(node.children.hasOwnProperty(path)){state=reduce(node.children[path],callback,state)}if(state instanceof Break)break}return state},value:function(node,callback,state){return callback(state,node.value,node.key)},hashmap:function(node,callback,state){for(var key in node.values){if(node.values.hasOwnProperty(key)){state=reduce(node.values[key],callback,state)}if(state instanceof Break)break}return state}};var Break=lib.reduce.Break=function(v){if(!(this instanceof Break))return new Break(v);this.value=v};lib.mutable=function(node){return lib.reduce(node,addKeyVal,{})};var addKeyVal=function(o,val,key){o[key]=val;return o};lib.keys=function(node){return lib.reduce(node,addKey,[])};var addKey=function(arr,val,key){arr.push(key);return arr}},{"./hash":8,"./util":7}],7:[function(require,module,exports){"use strict";var extend=function(t,f){for(var p in f)t[p]=f[p];return t};var clone=function(o){return extend({},o)};var slice=function(a,f,n){return[].slice.call(a,f,n)};var mapObj=function(o,fn){var r={};for(var p in o)r[p]=fn(o[p],p,o);return r};var map=function(arr,fn){var a=[];for(var i=0,l=arr.length;i>>from&31};var hashMask=function(str,from,hash){return mask(hash(str),from)};module.exports={hash:require("string-hash"),mask:hashMask}},{"string-hash":9}],9:[function(require,module,exports){module.exports=function(str){var hash=5381,i=str.length;while(i)hash=hash*33^str.charCodeAt(--i);return hash>=0?hash:(hash&2147483647)+2147483648}},{}]},{},[1])(1)}); \ No newline at end of file diff --git a/src/array.js b/src/array.js index 2ff9bef..644f804 100644 --- a/src/array.js +++ b/src/array.js @@ -137,6 +137,36 @@ module.exports.prototype = array.prototype = { return seed }, + slice: function(start, end) { + var lowEnd = start < 0 ? 0 : start; + var highEnd = end > this.length - 1 ? this.length - 1 : end; + var arr = (new array()).assoc(util.range(lowEnd,highEnd - 1)); + var ref = this; + return arr.map(function (e) {return ref.get(e)}); + }, + + concat: function(arr) { + var details = function(seed, val, key, array){ + return seed.push(val); + } + var additional = Array.isArray(arr) ? (new array()).assoc(arr) : arr; + if ((additional).mutable == undefined || Array.isArray(additional.mutable()) == false) { + return this; + } + + return additional.reduce(details, this); + }, + + flatMap: function(fn) { + var details = function(seed, val, key, array){ + if ( Array.isArray(val) || ((val).mutable != undefined && Array.isArray(val.mutable())) ) { + return seed.concat(val.map(fn)); + } else return seed; + + }; + return this.reduce(details, new array()); + }, + // array-specific methods reduceRight: function(fn, seed){ if ( arguments.length === 1 ) { diff --git a/src/util.js b/src/util.js index 786ef41..22989e3 100644 --- a/src/util.js +++ b/src/util.js @@ -31,7 +31,17 @@ var areEqual = function(v1, v2){ else return v1 === v2 } +var range = function(start, end) { + if (end - start < 0) return undefined; + var list = []; + for (var i = start; i <= end; i++) { + list.push(i); + } + return list; +} + module.exports = { + range : range, extend : extend, clone : clone, slice : slice, diff --git a/test/array-test.js b/test/array-test.js index a14b5bd..5745e55 100644 --- a/test/array-test.js +++ b/test/array-test.js @@ -92,6 +92,38 @@ describe('im.array', function(){ }) }) + describe('.slice', function(){ + it('should create an immutable array slice', function(){ + var arr = im.array([1,2,3,4,5,6]); + a.deepEqual(arr.slice(2,3).mutable(), [3]); + arr = im.array([1,2,3,4,5,6]); + a.deepEqual(arr.slice(0,4).mutable(), [1,2,3,4]); + a.deepEqual(arr.slice(-1,7).mutable(), [1,2,3,4,5] ); + }) + }) + + describe('.concat', function(){ + it('should append one immutable array to another', function(){ + var arr = im.array([1,2,3,4,5,6]).concat(im.array([7,8])); + a.deepEqual(arr.mutable(), [1,2,3,4,5,6,7,8]); + var arr = im.array([1,2,3,4,5,6]).concat([7,8]); + a.deepEqual(arr.mutable(), [1,2,3,4,5,6,7,8]); + }) + }) + + describe('.flatMap', function(){ + it('should flatten immutable arrays', function(){ + var arr = im.array([1,2,3,4,5,[6,7]]).flatMap(function(n){return n}); + a.deepEqual(arr.mutable(), [6,7]); + arr = im.array([[1,2,3,4,5],[6,7]]).flatMap(function(n){return n}); + a.deepEqual(arr.mutable(), [1,2,3,4,5,6,7]); + arr = (im.array([1,2,3,4,5,6]).concat([7,8])).flatMap(function(n){return n}); + a.deepEqual(arr.mutable(), []); + var h = im.array().push(im.array([1]).concat(im.array([2]))); + arr = h.flatMap(function(n){return n}); + a.deepEqual(arr.mutable(), [1,2]); + }) + }) describe('.map', function(){ it('should create an immutable object with updated values', function(){ var inc = function(a){ return a + 1 }