add Function.js, some updates in OxJS

This commit is contained in:
rolux 2012-01-07 12:50:02 +05:30
parent 80f9a1a33d
commit 1db649bd61
6 changed files with 123 additions and 90 deletions

View file

@ -48,6 +48,41 @@ Ox.merge = function(arr) {
return arr; return arr;
}; };
/*@
Ox.range <f> Python-style range
(stop) -> <[n]> range
Returns an array of integers from <code>0</code> (inclusive) to
<code>stop</code> (exclusive).
(start, stop) -> <[n]> range
Returns an array of integers from <code>start</code> (inclusive) to
<code>stop</code> (exclusive).
(start, stop, step) -> <[n]> range
Returns an array of numbers from <code>start</code> (inclusive) to
<code>stop</code> (exclusive), incrementing by <code>step</step>.
start <n> Start value
stop <n> Stop value
step <n> Step value
> Ox.range(3)
[0, 1, 2]
> Ox.range(1, 4)
[1, 2, 3]
> Ox.range(3, 0)
[3, 2, 1]
> Ox.range(1, 2, 0.5)
[1, 1.5]
> Ox.range(-1, -2, -0.5)
[-1, -1.5]
@*/
Ox.range = function() {
var args = Ox.makeArray(arguments),
arr = [];
args.push(function(i) {
arr.push(i);
});
Ox.loop.apply(null, args);
return arr;
};
/*@ /*@
Ox.sort <f> Sorts an array, handling leading digits and ignoring capitalization Ox.sort <f> Sorts an array, handling leading digits and ignoring capitalization
arr <a> Array arr <a> Array

View file

@ -11,7 +11,6 @@ Ox.avg <f> Returns the average of an array's values, or an object's properties
> Ox.avg('avg is 0.1') > Ox.avg('avg is 0.1')
0.1 0.1
@*/ @*/
Ox.avg = function(obj) { Ox.avg = function(obj) {
return Ox.sum(obj) / Ox.len(obj); return Ox.sum(obj) / Ox.len(obj);
}; };
@ -44,9 +43,8 @@ Ox.copy <f> Returns a (shallow or deep) copy of an object or array
> Ox.clone(0) > Ox.clone(0)
0 0
@*/ @*/
Ox.copy = Ox.clone = function(col, deep) { Ox.copy = Ox.clone = function(col, deep) {
// fixme: remove references to Ox.clone // fixme: copy or clone?
// fixme: is there any use case for shallow copy? // fixme: is there any use case for shallow copy?
var ret = Ox.isArray(col) ? [] : {}; var ret = Ox.isArray(col) ? [] : {};
if (deep) { if (deep) {
@ -109,7 +107,6 @@ Ox.filter <f> Filters a collection by a given condition
> Ox.filter(' foo bar ', function(v) { return v != ' '; }) > Ox.filter(' foo bar ', function(v) { return v != ' '; })
'foobar' 'foobar'
@*/ @*/
Ox.filter = function(col, fn) { Ox.filter = function(col, fn) {
var type = Ox.typeOf(col), var type = Ox.typeOf(col),
ret = type == 'array' ? [] : type == 'object' ? {} : ''; ret = type == 'array' ? [] : type == 'object' ? {} : '';
@ -285,7 +282,6 @@ Ox.getset <f> Generic getter and setter function
> Ox.test.object.options({foo: "foo", bar: "bar"}).options() > Ox.test.object.options({foo: "foo", bar: "bar"}).options()
{"key": "val", "foo": "foo", "bar": "bar"} {"key": "val", "foo": "foo", "bar": "bar"}
@*/ @*/
Ox.getset = function(obj, args, callback, context) { Ox.getset = function(obj, args, callback, context) {
var obj_ = Ox.clone(obj), ret; var obj_ = Ox.clone(obj), ret;
if (args.length == 0) { if (args.length == 0) {
@ -322,6 +318,8 @@ Ox.isEmpty <f> Returns true if a collection is empty
false false
> Ox.isEmpty(null) > Ox.isEmpty(null)
false false
> Ox.isEmpty(0)
false
> Ox.isEmpty() > Ox.isEmpty()
false false
@*/ @*/
@ -345,7 +343,6 @@ Ox.keys <f> Returns the keys of a collection
> Ox.keys('abc') > Ox.keys('abc')
[0, 1, 2] [0, 1, 2]
@*/ @*/
// fixme: is this really needed? arrays... ok... but strings?? // fixme: is this really needed? arrays... ok... but strings??
Ox.keys = function(obj) { Ox.keys = function(obj) {
var keys = []; var keys = [];
@ -402,47 +399,6 @@ Ox.len = function(col) {
: type == 'object' ? Ox.values(col).length : void 0; : type == 'object' ? Ox.values(col).length : void 0;
}; };
/*@
Ox.loop <f> For-loop, functional-style
Returning <code>false</code> from the iterator function acts like a
<code>break</code> statement. Unlike a <code>for</code> loop,
<code>Ox.loop</code> doesn't leak its counter variable to the outer scope,
but returns it.
(stop, callback) -> <n> Next value
equivalent to <code>for (var i = 0; i < stop; i++)</code>
(start, stop, callback) -> <n> Next value
equivalent to <code>for (var i = start; i < stop; i++)</code> or,
if <code>start</code> is larger than <code>stop</code>,
<code>for (var i = start; i > stop; i--)</code>
(start, stop, step, callback) -> <n> Next value
equivalent to <code>for (var i = start; i < stop; i += step)</code> or,
if <code>step</code> is negative,
<code>for (var i = start; i > stop; i += step)</code>
start <n> Start value
stop <n> Stop value (exclusive)
step <n> Step value
callback <f> Iterator function
i <n> Counter value
> Ox.loop(10, function(i) { return i != 4; })
4
> Ox.loop(0, 3, 2, function() {})
4
@*/
Ox.loop = function() {
var len = arguments.length,
start = len > 2 ? arguments[0] : 0,
stop = arguments[len > 2 ? 1 : 0],
step = len == 4 ? arguments[2] : (start <= stop ? 1 : -1),
callback = arguments[len - 1],
i;
for (i = start; step > 0 ? i < stop : i > stop; i += step) {
if (callback(i) === false) {
break;
};
}
return i;
};
/*@ /*@
Ox.makeArray <f> Takes an array-like object and returns a true array Ox.makeArray <f> Takes an array-like object and returns a true array
Alias for <code>Array.prototype.slice.call</code> Alias for <code>Array.prototype.slice.call</code>
@ -558,41 +514,6 @@ Ox.min = function(col) {
return Math.min.apply(Math, Ox.values(col)); return Math.min.apply(Math, Ox.values(col));
}; };
/*@
Ox.range <f> Python-style range
(stop) -> <[n]> range
Returns an array of integers from <code>0</code> (inclusive) to
<code>stop</code> (exclusive).
(start, stop) -> <[n]> range
Returns an array of integers from <code>start</code> (inclusive) to
<code>stop</code> (exclusive).
(start, stop, step) -> <[n]> range
Returns an array of numbers from <code>start</code> (inclusive) to
<code>stop</code> (exclusive), incrementing by <code>step</step>.
start <n> Start value
stop <n> Stop value
step <n> Step value
> Ox.range(3)
[0, 1, 2]
> Ox.range(1, 4)
[1, 2, 3]
> Ox.range(3, 0)
[3, 2, 1]
> Ox.range(1, 2, 0.5)
[1, 1.5]
> Ox.range(-1, -2, -0.5)
[-1, -1.5]
@*/
Ox.range = function() {
var args = Ox.makeArray(arguments),
arr = [];
args.push(function(i) {
arr.push(i);
});
Ox.loop.apply(null, args);
return arr;
};
/*@ /*@
Ox.setPropertyOnce <f> Sets a property once Ox.setPropertyOnce <f> Sets a property once
Given a array of objects, each of which has a property with a boolean Given a array of objects, each of which has a property with a boolean

View file

@ -70,8 +70,6 @@ Some conventions:
: expression; : expression;
*/ */
// FIXME: add memoize
// todo: check http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/ // todo: check http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/
// also see https://github.com/tlrobinson/narwhal/blob/master/lib/util.js // also see https://github.com/tlrobinson/narwhal/blob/master/lib/util.js
@ -81,7 +79,6 @@ Ox <f> The <code>Ox</code> object
(value) -> <o> wrapped value (value) -> <o> wrapped value
value <*> Any value value <*> Any value
@*/ @*/
window.Ox = function(val) { window.Ox = function(val) {
return Ox.wrap(val); return Ox.wrap(val);
}; };
@ -103,7 +100,6 @@ Ox.load <f> Loads a module
callback <f> Callback function callback <f> Callback function
success <b> If true, the module has been loaded successfully success <b> If true, the module has been loaded successfully
@*/ @*/
Ox.load = function() { Ox.load = function() {
var callback = arguments[arguments.length - 1], var callback = arguments[arguments.length - 1],
counter = 0, counter = 0,
@ -224,6 +220,47 @@ Ox.Log = (function() {
return that; return that;
}()); }());
/*@
Ox.loop <f> For-loop, functional-style
Returning <code>false</code> from the iterator function acts like a
<code>break</code> statement. Unlike a <code>for</code> loop,
<code>Ox.loop</code> doesn't leak its counter variable to the outer scope,
but returns it.
(stop, callback) -> <n> Next value
equivalent to <code>for (var i = 0; i < stop; i++)</code>
(start, stop, callback) -> <n> Next value
equivalent to <code>for (var i = start; i < stop; i++)</code> or,
if <code>start</code> is larger than <code>stop</code>,
<code>for (var i = start; i > stop; i--)</code>
(start, stop, step, callback) -> <n> Next value
equivalent to <code>for (var i = start; i < stop; i += step)</code> or,
if <code>step</code> is negative,
<code>for (var i = start; i > stop; i += step)</code>
start <n> Start value
stop <n> Stop value (exclusive)
step <n> Step value
callback <f> Iterator function
i <n> Counter value
> Ox.loop(10, function(i) { return i != 4; })
4
> Ox.loop(0, 3, 2, function() {})
4
@*/
Ox.loop = function() {
var len = arguments.length,
start = len > 2 ? arguments[0] : 0,
stop = arguments[len > 2 ? 1 : 0],
step = len == 4 ? arguments[2] : (start <= stop ? 1 : -1),
callback = arguments[len - 1],
i;
for (i = start; step > 0 ? i < stop : i > stop; i += step) {
if (callback(i) === false) {
break;
};
}
return i;
};
/*@ /*@
Ox.print <f> Prints its arguments to the console Ox.print <f> Prints its arguments to the console
(arg, ...) -> <s> String (arg, ...) -> <s> String

View file

@ -35,7 +35,7 @@ if (!Array.prototype.forEach) {
fn.call(that, arr[i], i, arr); fn.call(that, arr[i], i, arr);
} }
} }
} };
} }
// see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf // see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
@ -55,7 +55,7 @@ if (!Array.prototype.indexOf) {
} }
} }
return ret; return ret;
} };
} }
// see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/map // see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/map
@ -74,7 +74,7 @@ if (!Array.prototype.map) {
} }
} }
return ret; return ret;
} };
} }
// see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduce // see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduce
@ -116,5 +116,5 @@ if (!Object.keys) {
} }
} }
return ret; return ret;
} };
} }

29
source/Ox/js/Function.js Normal file
View file

@ -0,0 +1,29 @@
/*@
Ox.cache <f> Memoize a function
<script>
var f = Ox.cache(function(n) { return n * Math.random(); });
</script>
> f(10) == f(10);
true
> f(10) == f.clear()(10);
false
@*/
Ox.cache = function(fn) {
var cache = {},
ret = function() {
var key = JSON.stringify(Ox.makeArray(arguments));
return key in cache ? cache[key]
: (cache[key] = fn.apply(this, arguments));
};
ret.clear = function() {
if (arguments.length == 0) {
cache = {};
} else {
Ox.toArray(arguments).forEach(function(key) {
delete cache[key];
});
}
return ret;
}
return ret;
};

View file

@ -31,6 +31,17 @@ Ox.keyOf = function(obj, val) {
return key; return key;
}; };
/*@
Ox.methods <f> Returns a sorted list of all method names of an object
> Ox.methods({a: [], b: false, f: function() {}, n: 0, o: {}, s: ''})
['f']
@*/
Ox.methods = function(obj) {
return Object.keys(obj).filter(function(key) {
return Ox.isFunction(obj[key]);
}).sort();
};
/*@ /*@
Ox.serialize <f> Parses an object into query parameters Ox.serialize <f> Parses an object into query parameters
> Ox.serialize({a: 1, b: 2, c: 3}) > Ox.serialize({a: 1, b: 2, c: 3})