/*##functional*/
function addMethod(object, name, func){
	if(object && object.prototype && !object.prototype[name])object.prototype[name]=func;
}

function map(func,iterable){
	var len = iterable.length, result = new Array(len);
	while(len--)result[len]=func(iterable[len]);
	return result;
}
addMethod(Array,"map",function(func){return map(func,this)});

function reduce(func,init,iterable){
	for(var i=0,len=iterable.length;i<len;++i)init = func(init,iterable[i]);
	return init;
}
addMethod(Array,"reduce",function(func,init){return reduce(func,init,this)});

function filter(func,iterable){
	var len = iterable.length, result=[], out_len=0;
	while(len--)if(func(iterable[len]))result[out_len++]=iterable[len];
	return result;
}
addMethod(Array,"filter",function(func){return filter(func,this)});

function each(func, iterable){
	for(var i=0,len=iterable.length;i<len;++i)func(iterable[i]);
}
addMethod(Array,"each",function(func){return each(func,this)});

function any(func, iterable){
	var len=iterable.length;
	while(len--)if(func(iterable[len]))return true;
	return false;
}
addMethod(Array,"any",function(func){return any(func,this)});

function seq(func,limit){
	var i = func.length, result=[], args=new Array(i);
	while(i--)args[i]=arguments[i+2];
	while((result[i]=func.apply(this,args))!=null && limit){
		args.shift();
		args.push(result[i++]);
		limit--;
	}
	result.pop();
	return result;
}

Function.prototype.curry = function(){
	var len = arguments.length;
	if(!len)return this;
	var func = this, args = new Array(len);
	while(len--)args[len]=arguments[len];
	return function(){
		var len=arguments.length, args_next=new Array(len);
		while(len--)args_next[len]=arguments[len];
		return func.apply(this,args.concat(args_next));
	}
}

Function.prototype.rcurry = function(){
	var len = arguments.length;
	if(!len)return this;
	var func = this, args = new Array(len);
	while(len--)args[len]=arguments[len];
	return function(){
		var len=arguments.length, args_next=new Array(len);
		while(len--)args_next[len]=arguments[len];
		return func.apply(this,args_next.concat(args));
	}
}

Function.prototype.bind = function(){
	var len = arguments.length-1, self = arguments[0];
	if(len<1 && self===undefined)return this;
	var func = this, args = new Array(len);
	while(len--)args[len]=arguments[len+1];
	return function(){
		var len=arguments.length, args_next=new Array(len);
		while(len--)args_next[len]=arguments[len];
		return func.apply(self,args.concat(args_next));
	}
}

Function.prototype.rbind = function(){
	var len = arguments.length-1, self = arguments[0];
	if(len<1 && self===undefined)return this;
	var func = this, args = new Array(len);
	while(len--)args[len]=arguments[len+1];
	return function(){
		var len=arguments.length, args_next=new Array(len);
		while(len--)args_next[len]=arguments[len];
		return func.apply(self,args_next.concat(args));
	}
}

function jqCurry(func){
	var len=arguments.length-1,args = new Array(len);
	while(len)args[len] = arguments[len+1];
	return function(){
		var len2=arguments.length,args2=new Array(len2);
		while(len2--)args2[len]=arguments[len];
		jQuery.fn[func].apply(jQuery(this),args.concat(args2));
	}
}

function jqRCurry(func){
	var len=arguments.length-1,args = new Array(len);
	while(len)args[len] = arguments[len+1];
	return function(){
		var len2=arguments.length,args2=new Array(len2);
		while(len2--)args2[len]=arguments[len];
		jQuery(this)[func](args2.concat(args));
	}
}
