<commit_before>/*
---
description: Extensions to the Function class that allow a more functional programming style
license: LGPL
authors: ['<NAME>']
requires: [Core,Function,Class]
provides: [
	FunctionTools, Function._, Function.empty, Function.identity, Function.lambda,
	Function.combine, Function.compose, Function.overload, Function::wrap, Function::memoize,
	Function::partial, Function::curry, Function::not, Function::prepend, Function::append,
	Function::overload, Function::getArgs, Function::getArity, Array::toFunction, Hash::toFunction
]
... */


// class properties and globals
this._ = Function._ = function(_){
	var args = arguments.callee.caller.arguments;
	if(_===undefined) args._ = (args._===undefined ? 0 : args._+1);
	return args[_||args._];
};


// class methods
Function.extend({

	empty: function(){},

	identity: function(_){ return _; },

	lambda: function(_){
		return function(){ return _; };
	},

	combine: function(){
		var args = Array.prototype.slice.call(arguments);
		return function(){
			var result;
			args.each(function(fn){
				result = fn.apply(this,arguments);
			});
			return result;
		};
	},

	overload: function(funcTable){
		if(!funcTable || typeof funcTable === 'function'){
			var newTable = [];
			for(var i=0, l=arguments.length; i<l; i++){
				newTable[arguments[i].arity] = arguments[i];
			}
			funcTable = newTable;
		}
		return function(){
			var fn = funcTable[arguments.length];
			if(!fn || typeof fn !== 'function') return undefined;
			return fn.apply(this,arguments);
		};
	}
});

// aliasing
Function.extend({compose: Function.combine});


// instance methods
Function.implement({

	wrap: function(fn){
		var that = this;
		var ret = function(){
			var args = Array.prototype.slice.call(arguments);
			return fn.call(this,that.bind(this),args);
		};
		ret._origin = this;
		return ret;
	},

	memoize: function(memos){
		memos = memos || {};
		return this.wrap(function(original,args){
			var origin = this;
			while(origin._origin) origin = origin._origin;
			var key = [origin,args];
			if(memos[key] !== undefined) return memos[key];
			if(memos[args] !== undefined) return memos[args];
			return (memos[key] = original.apply(this,args));
		});<commit_msg>Function.compose is now different than Function.combine<commit_after>/*
---
description: Extensions to the Function class that allow a more functional programming style
license: LGPL
authors: ['<NAME>']
requires: [Core,Function,Class]
provides: [
	FunctionTools, Function._, Function.empty, Function.identity, Function.lambda,
	Function.combine, Function.compose, Function.overload, Function::wrap, Function::memoize,
	Function::partial, Function::curry, Function::not, Function::prepend, Function::append,
	Function::overload, Function::getArgs, Function::getArity, Array::toFunction, Hash::toFunction
]
... */


// class properties and globals
this._ = Function._ = function(_){
	var args = arguments.callee.caller.arguments;
	if(_===undefined) args._ = (args._===undefined ? 0 : args._+1);
	return args[_||args._];
};


// class methods
Function.extend({

	empty: function(){},

	identity: function(_){ return _; },

	lambda: function(_){
		return function(){ return _; };
	},

	combine: function(){
		var args = Array.prototype.slice.call(arguments);
		return function(){
			var result;
			args.each(function(fn){
				result = fn.apply(this,arguments);
			});
			return result;
		};
	},

	compose: function(){
		var args = Array.prototype.slice.call(arguments);
		return function(){
			var lastReturn = Array.prototype.slice.call(arguments);
			args.reverse().each(function(fn){
				lastReturn = [fn.apply(this,lastReturn)]
			});
			return lastReturn[0];
		}
	},

	overload: function(funcTable){
		if(!funcTable || typeof funcTable === 'function'){
			var newTable = [];
			for(var i=0, l=arguments.length; i<l; i++){
				newTable[arguments[i].arity] = arguments[i];
			}
			funcTable = newTable;
		}
		return function(){
			var fn = funcTable[arguments.length];
			if(!fn || typeof fn !== 'function') return undefined;
			return fn.apply(this,arguments);
		};
	}
});


// instance methods
Function.implement({

	wrap: function(fn){
		var that = this;
		var ret = function(){
			var args = Array.prototype.slice.call(arguments);
			return fn.call(this,that.bind(this),args);
		};
		ret._origin = this;
		return ret;
	},

	memoize: function(memos){
		memos = memos || {};
		return this.wrap(function(original,args){
			var origin = this;
			while(origin._origin) origin = origin._origin;
			var key = [origin,args];
			if(memos[key] !== undefined) return memos[key];
			if(memos[args] !== undefined) return memos[args];
			return (memos[key] = original.apply(this,args));
		});
{'fraction_non_alphanumeric': 0.16482347937048064, 'fraction_numerical': 0.0014887282007656317, 'mean_word_length': 4.46860465116279, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1514445', 'n_tokens_mistral': 1634, 'n_tokens_neox': 1474, 'n_words': 345}