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;
};
/*@
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
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')
0.1
@*/
Ox.avg = function(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)
0
@*/
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?
var ret = Ox.isArray(col) ? [] : {};
if (deep) {
@ -109,7 +107,6 @@ Ox.filter <f> Filters a collection by a given condition
> Ox.filter(' foo bar ', function(v) { return v != ' '; })
'foobar'
@*/
Ox.filter = function(col, fn) {
var type = Ox.typeOf(col),
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()
{"key": "val", "foo": "foo", "bar": "bar"}
@*/
Ox.getset = function(obj, args, callback, context) {
var obj_ = Ox.clone(obj), ret;
if (args.length == 0) {
@ -322,6 +318,8 @@ Ox.isEmpty <f> Returns true if a collection is empty
false
> Ox.isEmpty(null)
false
> Ox.isEmpty(0)
false
> Ox.isEmpty()
false
@*/
@ -345,7 +343,6 @@ Ox.keys <f> Returns the keys of a collection
> Ox.keys('abc')
[0, 1, 2]
@*/
// fixme: is this really needed? arrays... ok... but strings??
Ox.keys = function(obj) {
var keys = [];
@ -402,47 +399,6 @@ Ox.len = function(col) {
: 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
Alias for <code>Array.prototype.slice.call</code>
@ -558,41 +514,6 @@ Ox.min = function(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
Given a array of objects, each of which has a property with a boolean

View file

@ -70,8 +70,6 @@ Some conventions:
: expression;
*/
// FIXME: add memoize
// 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
@ -81,7 +79,6 @@ Ox <f> The <code>Ox</code> object
(value) -> <o> wrapped value
value <*> Any value
@*/
window.Ox = function(val) {
return Ox.wrap(val);
};
@ -103,7 +100,6 @@ Ox.load <f> Loads a module
callback <f> Callback function
success <b> If true, the module has been loaded successfully
@*/
Ox.load = function() {
var callback = arguments[arguments.length - 1],
counter = 0,
@ -224,6 +220,47 @@ Ox.Log = (function() {
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
(arg, ...) -> <s> String

View file

@ -35,7 +35,7 @@ if (!Array.prototype.forEach) {
fn.call(that, arr[i], i, arr);
}
}
}
};
}
// see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
@ -55,7 +55,7 @@ if (!Array.prototype.indexOf) {
}
}
return ret;
}
};
}
// see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/map
@ -74,7 +74,7 @@ if (!Array.prototype.map) {
}
}
return ret;
}
};
}
// see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/reduce
@ -116,5 +116,5 @@ if (!Object.keys) {
}
}
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;
};
/*@
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({a: 1, b: 2, c: 3})