+var WR_P = "__wraps__";
+
+var _ = globals._ = YFunction._ = {};
+
function YFunction(fn){
- fn._o = fn;
+ if (!fn)
+ fn = function(){};
+ if (fn.__y__)
+ return fn;
+
+ // fn._o = fn;
fn.__y__ = true;
return install(fn);
}
-// YFunction = YCollection.subclass({
-// init : YFunction,
-// reduce : reduce,
-// attr : attr,
-// extend : extend,
-// end : function(){ return this; }
-// })
-
Y.YFunction = YFunction;
-YFunction.prototype.end = function(){ return this; };
+Y.extend(YFunction.prototype, {
+ init : YFunction,
+ reduce : methodize(Y.reduce),
+ extend : methodize(Y.extend),
+ end : function(){ return this; }
+});
YFunction.prototype.attr = methodize(Y.attr);
-YFunction.prototype.extend = methodize(Y.extend);
-YFunction.prototype.reduce = methodize(Y.reduce);
+// YFunction.prototype.extend = methodize(Y.extend);
+// YFunction.prototype.reduce = methodize(Y.reduce);
YFunction.install = install;
function install(target){
target = target || Function.prototype;
var proto = YFunction.prototype;
+
for (var k in proto) {
if ( isFunction(proto[k]) && (k == 'bind' || !target[k]) )
target[k] = proto[k];
+function unwrap(fn){
+ return ( fn && isFunction(fn) ) ? unwrap(fn[WR_P]) || fn : fn;
+}
+
+Y.curry = curry;
+YFunction.prototype.curry = methodize(curry);
+function curry(fn){
+ if (fn.__curried__)
+ return fn.apply(this, Y(arguments,1));
+
+ var args = Y(arguments, 1)
+ , L = unwrap(fn).length;
+
+ if ( args.length >= L )
+ return fn.apply(this, args);
+
+ function curried(){
+ var _args = args.concat( Y(arguments) );
+ if ( _args.length >= L )
+ return fn.apply(this, _args);
+ else
+ return curry.apply(this, [fn].concat(_args));
+ }
+
+ curried.__wraps__ = fn;
+ curried.__curried__ = args;
+ return curried;
+}
+
+
+Y.methodize = methodize;
+YFunction.prototype.methodize = methodize(methodize);
+function methodize(fn) {
+ if ( fn.__methodized__ )
+ return fn.__methodized__;
+
+ var m = fn.__methodized__ =
+ function(){
+ return fn.apply(this, [this].concat( Y(arguments) ));
+ };
+ m[WR_P] = fn;
+ return m;
+}
+
+
Y.compose = compose;
YFunction.prototype.compose = methodize(compose);
function _composer(x,fn){ return fn.call(this, x); }
return wrapper;
}
-function splat(fn, x){
- return fn[ isArray(x) ? "apply" : "call"](this, x);
-}
-
-function unwrap(fn){
- return (fn && isFunction(fn)) ? unwrap(fn.__wraps__) || fn : fn;
-}
-
-YFunction.prototype.bind = function(context, args){
- var bound = Y( _Function.prototype.bind.apply(this, arguments) );
- bound.__wraps__ = this;
- return bound;
-};
-
-
-// Remembers arguments but obeys current context
-YFunction.prototype.partial = partial;
-function partial(){
- var fn = this
- , args = Y(arguments)
- , partially = Y(function(){
- return fn.apply( this, args.concat(arguments) );
- });
- partially.__wraps__ = fn;
- return partially;
-}
-
-// Collects arguments but ignores context: fn.curry( arg1, arg2, ... )
-YFunction.prototype.curry = methodize(curry);
-function curry(fn){
- if (fn.__curried__)
- return fn.apply(this, arguments);
-
- var args = Y(arguments, 1)
- , L = unwrap(fn).length;
-
- function curried(){
- var self = arguments.callee
- , _args = self.__curried__ = args.concat(arguments);
- self.__wraps__ = fn;
-
- if ( _args.length >= L )
- return fn.apply(this, _args);
- else
- return curried;
- }
-
- return curried();
-}
-
// YFunction.prototype.lazy = methodize(lazy);
// function lazy(fn){
// var args = Y(arguments, 1)
// }
-Y.methodize = methodize;
-YFunction.prototype.methodize = methodize(methodize); // heh
-function methodize( fn ) {
- if (fn.__methodized)
- return fn.__methodized;
-
- var m = fn.__methodized =
- Y(function(){
- var target = (this instanceof YBase) ? this._o : this
- , result = fn.apply(target, [target].concat(Y(arguments)));
- if (result === target)
- return this;
- else
- return result;
- // return fn.apply(this, [this].concat(Y(arguments)));
- });
- m.__wraps__ = fn;
- return m;
+function splat(fn, x){
+ return fn[ isArray(x) ? "apply" : "call"](this, x);
}
+var _bind = _Function.prototype.bind;
+YFunction.prototype.bind = function(context, args){
+ var bound = _bind.apply(this, arguments);
+ bound.__wraps__ = this;
+ return Y(bound);
+};
+
+
+// Remembers arguments but obeys current context
+YFunction.prototype.partial = partial;
+function partial(){
+ var fn = this
+ , args = Y(arguments)
+ , partially = function(){
+ return fn.apply( this, args.concat(Y(arguments)) );
+ };
+ partially.__wraps__ = fn;
+ return Y(partially);
+}
+
+
Y.genericize = genericize;
YFunction.prototype.genericize = methodize(genericize); // heh
function genericize( fn ) {
- if (fn.__genericize)
- return fn.__genericize;
+ if (fn.__genericized__)
+ return fn.__genericized__;
- var g = fn.__genericize =
- Y(function(){
+ var g = fn.__genericized__ =
+ function(){
var args = Y(arguments), self = args.shift();
return fn.apply(self, args);
- });
+ };
g.__wraps__ = fn;
- return g;
+ return Y(g);
+}
+
+// Only works for arguments whose toString is unique and stateless (for example, primitives, but not closures).
+// XXX: hashCode()
+Y.memoize = memoize;
+YFunction.prototype.memoize = methodize(memoize);
+function memoize(fn){
+ var cache = {};
+ function memorizer(){
+ // I'd like to use toJSON here, but that won't work cross-browser.
+ var key = Y(arguments).join('\0');
+ if ( !(key in cache) )
+ cache[key] = fn.apply(this, arguments);
+ return cache[key];
+ }
+
+ memorizer.__wraps__ = fn;
+ memorizer.__cache__ = cache;
+ return memorizer;
}
+// Memorized to reduce eval costs
+var
+n = 4,
+_ofArityWrapper =
+YFunction._ofArityWrapper =
+ memoize(function(n, limit){
+ return eval('(function(fn){ '+
+ 'return function('+Y.range(n).map( Y.op.add('$') ).join(',')+'){ '+
+ 'return fn.apply(this,' + (limit ? 'Y(arguments).slice(0,'+n+')' : 'arguments')+
+ '); }; })');
+ });
+
+YFunction.prototype.aritize = function(n){
+ return _ofArityWrapper(n, false)(this);
+};
+
+YFunction.prototype.limit = function(n){
+ return _ofArityWrapper(n, true)(this);
+};
+
+
+/**
+ * Filter the arguments passed to the wrapper function
+ */
+YFunction.prototype.mask = mask;
+function mask(){
+
+}
+
+
+
/** Returns the declared name of a function. */
YFunction.prototype.getname = Y.getname = getname;
function getname( fn ){
return fn.className || fn.name || (fn+'').match( /function\s*([^\(]*)\(/ )[1] || '';
}
-
Y.mixinNames = mixinNames;
function mixinNames(o, Donor, names, override, yWrap){
var target = ( isFunction(o) ? o.prototype : o)
}
+YFunction(Y);
Y(Y.reduce);
Y(Y.attr);
Y(Y.extend);
+Y.reduce(YFunction.prototype, function(_,fn,name){
+ YFunction(fn);
+});
Y.range = range;
-function range(start, end){
- // range() --> []
- if ( arguments.length === 0 ) return [];
- // range(3) --> range(0,3)
- else if ( arguments.length === 1 ) { end = start; start = 0; }
- // range(5,2) --> range(1,6).reverse()
- if (start > end) {
- var r = range(end-1, start+1);
- r.reverse();
- return r;
- } else {
- var i = end - start - 1, r = new Array(i);
- while ( i >= 0 ) r[i] = start + i--;
- return r;
+function range(start, end, step){
+ switch (arguments.length) {
+ // range() -> []
+ case 0 : return [];
+
+ // range(3) -> range( 0,3)
+ // range(-3) -> range(-3,0)
+ case 1 :
+ if (start > 0) {
+ end = start;
+ start = 0;
+ } else
+ end = 0;
}
+
+ if (start === end) return [];
+
+ // range(2,5) -> range(2,5, 1) -> [2,3,4]
+ // range(5,2) -> range(5,2,-1) -> [5,4,3]
+ if (start < end)
+ var v = start, L = end, s = 1;
+ else
+ var v = end, L = start, s = -1;
+
+ step = step || s;
+
+ var r = [];
+ while ( v < L ) {
+ r.push(v);
+ v += step;
+ }
+ return r;
}
});
-Triangle = new Y.Class('Triangle', Shape, {
- x1: 0, y1: 0,
- x2: 0, y2: 0,
+Polygon = new Y.Class('Polygon', Shape, {
+ x0: 0, y0:0,
_offsetX : 0, // We need our triangle to be in the first quadrant
_offsetY : 0, // so we'll have to offset any negative shapes at the position call
- init : function(x1,y1, x2,y2){
+ /**
+ * Expects two arrays of coordinate-halfs, which could be zipped
+ * together to make the numbered coordinates.
+ * x0 and y0 will always be 0.
+ */
+ init : function(xs, ys){
Layer.init.call(this);
- var minX = Math.min(0, x1, x2);
- if (minX < 0) {
- var offX = this._offsetX = -minX;
- x1 += offX; x2 += offX;
- }
+ var xs = this._calcOffset('x', xs)
+ , ys = this._calcOffset('y', ys) ;
- var minY = Math.min(0, y1, y2);
- if (minY < 0) {
- var offY = this._offsetY = -minY;
- Y1 += offY; y2 += offY;
- }
+ this.points = Y(xs).zip(ys);
- this.x1 = x1; this.y1 = y1;
- this.x2 = x2; this.y2 = y2;
- this.width( Math.max(0, x1, x2) );
- this.height( Math.max(0, y1, y2) );
+ this.width( Math.max.apply(Math, xs) );
+ this.height( Math.max.apply(Math, ys) );
},
_calcOffset : function(which, values){
- var min = Math.min(0, Math.min.apply(Math, values));
+ values.unshift(0);
+ var self = this
+ , off = -1 * Math.min.apply(Math, values);
- if (min < 0) {
- var off = this['_offset'+which] = -min;
- x1 += off; x2 += off;
- }
- return
+ self['_offset'+which.toUpperCase()] = off;
+ self[which+'s'] = values = values.map(function(v, i){
+ v += (i === 0 ? 0 : off);
+ self[which+i] = v
+ return v;
+ });
+ return values;
},
position : function(left, top){
return this;
},
+ drawShape : function(ctx){
+ var self = this;
+
+ }
+});
+
+Triangle = new Y.Class('Triangle', Polygon, {
+ x1: 0, y1: 0,
+ x2: 0, y2: 0,
+
+ init : function (x1,y1, x2,y2){
+ Polygon.init.call(this, [x1,x2], [y1,y2]);
+ },
+
+ drawShape : function(ctx){
+
+ }
});
Ellipse = new Y.Class('Ellipse', Shape, {