</div></div>
<div id="scripts">
-<!--# include file="build/tags.html" -->
+<!--# include file="tags.html" -->
</div>
</body>
// Generic Collection Functions
+
var undefined
, globals = (function(){ return this; })()
, _Function = globals.Function
, _Array = globals.Array
-, PT = "prototype"
-, slice = _Array[PT].slice
-, type = require('Y/type')
-;
-
-// function slice(a){
-// return _asl.apply(a, _asl.call(arguments, 1));
-// }
+, slice = _Array.prototype.slice
-function notWrapped(fn){
- var self = arguments.callee.caller;
- return fn && fn !== self && fn.__wraps__ !== self;
-}
+, type = require('Y/type')
+;
function reduce(o, fn, acc){
if ( !o )
fn = _Function.toFunction(fn);
var cxt = arguments[3] || o;
- if ( notWrapped(o.reduce) )
- return o.reduce.apply(o, [fn, acc, cxt]);
+
+ if ( o instanceof _Array )
+ return o.reduce.call(o, fn, acc, cxt);
for ( var name in o )
acc = fn.call(cxt, acc, o[name], name, o);
-
return acc;
}
fn = _Function.toFunction(fn);
var acc = {}, cxt = arguments[2] || o;
- if ( notWrapped(o.map) )
- return o.map.apply(o, [fn, cxt]);
+
+ if ( o instanceof _Array )
+ return o.map(fn, cxt);
for ( var name in o )
acc[name] = fn.call(cxt, o[name], name, o);
-
return acc;
}
function forEach(o, fn){
- map(o, fn, arguments[2] || o);
+ var cxt = arguments[2] || o;
+
+ if ( o instanceof _Array )
+ o.forEach(fn, cxt);
+ else
+ map(o, fn, cxt);
+
return o;
}
fn = _Function.toFunction(fn);
var acc = {}, cxt = arguments[2] || o;
- if ( notWrapped(o.filter) )
- return o.filter.apply(o, [fn, cxt]);
+
+ if ( o instanceof _Array )
+ return o.filter(fn, cxt);
for ( var name in o )
if ( fn.call(cxt, o[name], name, o) )
acc[name] = o[name];
-
return acc;
}
return o;
}
-function dset(o, key, value, def){
- if ( o && notWrapped(o.set) )
- return o.set.apply(o, slice.call(arguments,1));
- else
- return set(o, key, value, def);
-}
-
function attr(o, key, value, def){
if ( !o || key === undefined ) return o;
return extend(o, key);
if ( value !== undefined || def !== undefined ){
- return dset(o, key, value, def);
+ return set(o, key, value, def);
} else
return o[key];
}
-function dattr(o, key, value, def){
- if ( o && notWrapped(o.attr) )
- return o.attr.apply(o, slice.call(arguments,1));
- else
- return attr(o, key, value, def);
-}
-
function extend( A, B ){
return slice.call(arguments,1).reduce(extendall, A);
}
function extendall(A, donor){ return reduce(donor, attrvk, A); }
function attrvk(o, v, k){ return attr(o, k, v, o[k]); }
-function dextend( A, B ){
- return slice.call(arguments,1).reduce(dextendall, A);
-}
-function dextendall(A, donor){ return reduce(donor, dattrvk, A); }
-function dattrvk(o, v, k){ return dattr(o, k, v, o[k]); }
-
exports['reduce'] = reduce;
exports['map'] = map;
exports['attr'] = attr;
exports['extend'] = extend;
-exports['dset'] = dset;
-exports['dattr'] = dattr;
-exports['dextend'] = dextend;
-exports['slice'] = slice;
\ No newline at end of file
+exports['slice'] = slice;
--- /dev/null
+// Delegating Collection Functions
+var undefined
+, _Function = Function
+, type = require('Y/type')
+, core = require('Y/core')
+, slice = core.slice
+;
+
+function notWrapped(fn){
+ var self = arguments.callee.caller;
+ return fn && fn !== self && fn.__wraps__ !== self;
+}
+
+function reduce(o, fn, acc){
+ if ( !o )
+ return acc;
+
+ fn = _Function.toFunction(fn);
+ var cxt = arguments[3] || o;
+
+ if ( notWrapped(o.reduce) )
+ return o.reduce.call(o, fn, acc, cxt);
+
+ for ( var name in o )
+ acc = fn.call(cxt, acc, o[name], name, o);
+
+ return acc;
+}
+
+function map(o, fn){
+ if ( !o )
+ return o;
+
+ fn = _Function.toFunction(fn);
+ var acc = {}, cxt = arguments[2] || o;
+
+ if ( notWrapped(o.map) )
+ return o.map.call(o, fn, cxt);
+
+ for ( var name in o )
+ acc[name] = fn.call(cxt, o[name], name, o);
+
+ return acc;
+}
+
+function forEach(o, fn){
+ var cxt = arguments[2] || o;
+
+ if ( notWrapped(o.forEach) )
+ o.forEach.call(o, fn, cxt);
+ else
+ map(o, fn, cxt);
+
+ return o;
+}
+
+function filter(o, fn){
+ if ( !o )
+ return o;
+
+ fn = _Function.toFunction(fn);
+ var acc = {}, cxt = arguments[2] || o;
+
+ if ( notWrapped(o.filter) )
+ return o.filter.call(o, fn, cxt);
+
+ for ( var name in o )
+ if ( fn.call(cxt, o[name], name, o) )
+ acc[name] = o[name];
+
+ return acc;
+}
+
+function set(o, key, value, def){
+ if ( o && notWrapped(o.set) )
+ return o.set.apply(o, slice.call(arguments,1));
+ else
+ return core.set(o, key, value, def);
+}
+
+function attr(o, key, value, def){
+ if ( !o || key === undefined ) return o;
+
+ if ( notWrapped(o.attr) )
+ return o.attr.apply(o, slice.call(arguments,1));
+
+ if ( type.isPlainObject(key) )
+ return extend(o, key);
+
+ if ( value !== undefined || def !== undefined ){
+ return set(o, key, value, def);
+ } else
+ return o[key];
+}
+
+function extend( A, B ){
+ return slice.call(arguments,1).reduce(extendall, A);
+}
+function extendall(A, donor){ return reduce(donor, attrvk, A); }
+function attrvk(o, v, k){ return attr(o, k, v, o[k]); }
+
+
+exports['reduce'] = reduce;
+exports['map'] = map;
+exports['forEach'] = forEach;
+exports['filter'] = filter;
+
+exports['set'] = set;
+exports['attr'] = attr;
+exports['extend'] = extend;
// same name as its namespace
core.extend(type.type, type);
-// Attach core & type to Y
-core.extend(Y, core, type);
-delete Y.slice; // grr
-
-// Make top-level setters refer to the delegating versions
-Y['core'] = core;
-Y['set'] = core.dset;
-Y['attr'] = core.dattr;
-Y['extend'] = core.dextend;
+// Attach delegate-core & type to Y
+var del = require('Y/delegate');
+core.extend(Y, type, del);
+Y['core'] = core;
+Y['delegate'] = del;
/// Patch modules that weren't available earlier ///
YFunction(Y);
core.forEach(core, YFunction);
+core.forEach(del, YFunction);
YFunction(Y.type);
Y['is'] = YFunction(Y.is).curry();
// Curry all operators
var op = require('Y/op');
-core.forEach(op, YFunction);
-// Y['op'] = op['curried'] = op.extend({}, core.map(op, yfn.curry));
Y['op'] =
op['curried'] =
core.reduce(op, function(Yop, fn, k){
- Yop[k] = fn.curry();
+ Yop[k] = YFunction(fn).curry();
return Yop;
}, {});
addNames('YString', require('Y/types/string'));
addNames('YNumber range', require('Y/types/number'));
+var utils = require('Y/utils');
+Y['bindAll'] = utils.bindAll;
function addName(name){ Y[name] = this[name]; }
function addNames(names, ns){ names.split(' ').forEach(addName, ns); }
Y.YCollection.prototype.toKV =
function toKV(del){
- return this.reduce(function(acc, v, k){
- return acc.push( enc(k) + '=' + enc(v) );
- }, Y([]))
- .join(del !== undefined ? del : "&");
+ return this
+ .reduce(encoder, Y([]))
+ .join(del !== undefined ? del : "&");
};
Y.YString.prototype.toObject =
Y.YString.prototype.fromKV =
function fromKV(del){
- return Y(this.split(del || '&'))
- .reduce(function(acc, pair){
- var idx = pair.indexOf('=')
- , k = dec(pair.slice(0,idx))
- , v = dec(pair.slice(idx+1)) ;
- if (k) acc[k] = v;
- return acc;
- }, {});
+ return this
+ .split(del || '&')
+ .reduce(decoder, {});
};
+
+function encoder(acc, v, k){
+ return acc.push( enc(k) + '=' + enc(v) );
+}
+function decoder(acc, pair){
+ var idx = pair.indexOf('=')
+ , k = dec(pair.slice(0,idx))
+ , v = dec(pair.slice(idx+1)) ;
+ if (k) acc[k] = v;
+ return acc;
+}
\ No newline at end of file
var args = slice.call(arguments,1);
return function(obj){
if (obj && obj[name])
- return obj[name].apply( obj, args.concat(slice.call(arguments)) );
+ return obj[name].apply( obj, args.concat(slice.call(arguments,0)) );
else
return obj;
};
- },
- extend : function extend(A,B){
- return slice.call(arguments,1).reduce(extender, A);
}
};
-function extender(target, donor){
- return core.reduce(donor, op.vkset, target);
-}
-
-op.extend(exports, op);
+core.extend(exports, op);
function is( A, B ){
if ( isArray(B) )
- return B.map( is.bind(this,A) ).any();
+ return B.map( is.bind(this,A) ).any(); // XXX: implicitly depends on YFunction, but we'll just quietly not use it
else {
var AT = type(A), BT = type(B);
return (A instanceof BT || B instanceof AT || AT === BT);
mixin(YArray, { donor:Array, chain:true,
names:'push unshift sort splice reverse'.split(' ') });
- mixin(YArray, { donor:Array, wrap:YArray,
+ mixin(YArray, { donor:Array, wrap:YArray.instantiate.bind(YArray),
names:'map forEach filter slice'.split(' ') });
mixin(YArray, { donor:Array,
names:'reduce some every indexOf lastIndexOf shift pop join'.split(' ') });
-/** YCollection is the core of Y. */
+/**
+ * A generic collection (which also provides the majority of core functionality for YObject).
+ * Specializations are provided by subclasses. All subclasses must implement reduce().
+ */
-var YBase = require('Y/class').YBase
-, isFunction = require('Y/type').isFunction
-, core = require('Y/core')
-, op = require('Y/op')
-, slice = core.slice
-, extend = core.extend
-, attr = core.attr
-, bool = op.bool
+var YBase = require('Y/class').YBase
+// , type = require('Y/type')
+, core = require('Y/core')
+, del = require('Y/delegate')
+, op = require('Y/op')
+, slice = core.slice
;
function extendY(){
- extend.apply(this, [this._o].concat(slice.call(arguments)));
+ del.extend.apply(this, [this._o].concat(slice.call(arguments)));
return this;
}
},
'attr' : function attr(k, v, def){
- var r = attr(this._o, k, v, def);
+ var r = del.attr(this._o, k, v, def);
if (r === this._o)
return this;
else
return new this.constructor().extend(this);
},
+ // Dependence on YArray closes the loop
// 'remove' : function remove(v){
// var o = this._o
// , toRemove = new Y(arguments);
},
'every' : function every( fn ){
- var self = this, fn = fn || bool;
+ var self = this, fn = fn || op.bool;
return this.reduce(function(acc, v, k, o){
return acc && fn.call(self, v, k, o);
}, true);
},
'any' : function any( fn ){
- var self = this, fn = fn || bool;
+ var self = this, fn = fn || op.bool;
return this.reduce(function(acc, v, k, o){
return acc || fn.call(self, v, k, o);
}, false);
'pluck' : function pluck(key){
return this.map(function(v){
- return v && (isFunction(v.attr) ? v.attr(key) : v[key]);
+ return del.attr(v, key);
+ // return v && (type.isFunction(v.attr) ? v.attr(key) : v[key]);
});
},
'invoke' : function invoke(name){
var args = slice.call(arguments,1);
- return core.map(this, function(o){
+ return del.map(this, function(o){
return o && o[name].apply(o, args);
});
},
});
-
+function wraps(wrapper, fn) {
+ wrapper[WRAPS] = fn;
+ return YFunction(wrapper);
+}
function unwrap(fn){
return ( fn && isFunction(fn) ) ? unwrap(fn[WRAPS]) || fn : fn;
return curry.apply(this, [fn].concat(_args));
}
- curried[WRAPS] = fn;
curried.__curried__ = args;
- return curried;
+ return wraps(curried, fn);
}
function methodized(){
return fn.apply(this, [this].concat( slice.call(arguments) ));
};
- m[WRAPS] = fn;
- return m;
+ return wraps(m, fn);
}
function genericize( fn ) {
var args = slice.call(arguments);
return fn.apply(args.shift(), args);
};
- g[WRAPS] = fn;
- return g;
+ return wraps(g, fn);
};
// function lazy(fn){
// var args = slice.call(arguments, 1)
// , L = unwrap(fn).length
-// , lazied = function(){
+// , lazied =
+// function lazied(){
// var _args = slice.call(arguments)
// , f = _args[0];
//
// return fn.apply(this, args);
// else
// return arguments.callee;
-// }
-// ;
-// lazied[WRAPS] = fn;
+// };
+//
// lazied.__args = args;
-// return lazied();
+// return wraps(lazied, fn)();
// }
var _bind = _Function.prototype.bind;
function bind(fn, context, args){
- var bound = _bind.apply(fn, slice.call(arguments,1));
- bound[WRAPS] = fn;
- return YFunction(bound);
+ return wraps(_bind.apply(fn, slice.call(arguments,1)), fn);
}
function partially(){
return fn.apply( this, args.concat(slice.call(arguments)) );
};
- partially[WRAPS] = fn;
- return YFunction(partially);
+ return wraps(partially, fn);
}
return cache[key];
};
- m[WRAPS] = fn;
m.purge = function purge(){
var cache = this.cache;
this.cache = {};
return cache;
};
-
m.purge();
- return m;
+
+ return wraps(m, fn);
}
// Memorized to reduce eval costs
YFunction._ofArityWrapper =
memoize(function(n, limit){
var i = n, args = [];
- while (i-- > 0) args.unshift('$'+i);
- // range(n).map( op.add('$') ).join(',')
- return eval('(function '+(limit ? 'limited' : 'artized')+'(fn){ '+
- 'return function('+args.join(',')+'){ '+
- 'return fn.apply(this,' + (limit ? 'slice.call(arguments, 0,'+n+')' : 'arguments')+
- '); }; })');
+ while (i-- > 0) args.unshift('$'+i); // Can't use Y.range due to deps
+ return eval(
+ '(function '+(limit ? 'limited' : 'artized')+'(fn){ '+
+ 'return wraps(function('+args.join(',')+'){ '+
+ 'return fn.apply(this,' + (limit ? 'slice.call(arguments, 0,'+n+')' : 'arguments') + '); '+
+ '}, fn); '+
+ '})');
&nb