nodash 0.13.0 api documentation
This is the API documentation for nodash 0.13.0.
Don't miss the Appendix.
Boolean
AND
&&
Prelude: &&
Boolean → Boolean → Boolean
Boolean "and". This is effectively just making the &&
operator
available as a curried function.
Not to be confused with the lower case and.
Example:
AND(true, true) === true
AND(false)(true) === false
foldl(AND, true, [ true, false ]) === false
Haskell Definition:
True && True = True
_ && _ = False
Source:
function AND(a, b) {
return a && b;
}
bool
Boolean → Boolean → Boolean
Fold on Boolean
. bool(x, y, c)
evaluates to x
if c
is false
and to y
otherwise.
Haskell Definition:
bool no yes condition = case condition of
True -> yes
False -> no
Source:
function bool(no, yes, bool) {
return bool ? yes : no;
}
not
Prelude: not
Boolean → Boolean
Negates a boolean value.
This is basically JavaScripts unary prefix operator !
defined as a function.
Example:
not(true) === false
Haskell Definition:
not False = True
not _ = False
Source:
function not(value) {
return !value;
}
OR
||
Prelude: ||
Boolean → Boolean → Boolean
Booleanm "or". This is effectively just making the &&
operator
available as a curried function.
Not to be confused with the lower case or.
Example:
OR(false, true) === true
OR(false)(false) === false
foldl(OR, false, [ true, false ]) === true
Haskell Definition:
False && False = False
_ && _ = True
Source:
function OR(a, b) {
return a || b;
}
Char
chr
Integer → Char
Source:
function chr(x) {
return String.fromCharCode(x);
}
isAsciiLetter
String → Boolean
Determines whether the given String or Character is an ascii letter, that is: Matching the regular expression /^[a-zA-Z]+$/
.
Example:
isAsciiLetter('X') === true
isAsciiLetter('@') === false
isAsciiLetter('8') === false
Source:
function isAsciiLetter(x) {
return /^[a-zA-Z]+$/.test(x);
}
isLetter
Char → Boolean
Source:
function isLetter(x) {
var xUpper = x.toUpperCase();
var xLower = x.toLowerCase();
for (var i = 0; i < x.length; i += 1) {
if (xUpper[i] === xLower[i]) {
return false;
}
}
return true;
}
isLower
String → Boolean
Source:
function isLower(x) {
var xUpper = x.toUpperCase();
var xLower = x.toLowerCase();
for (var i = 0; i < x.length; i += 1) {
if (xUpper[i] === xLower[i] || x[i] !== xLower[i]) {
return false;
}
}
return true;
}
isNumeric
isDigit
Something → Boolean
Source:
function isNumeric(thing) {
return /^[0-9]+$/.test(thing);
}
isUpper
String → Boolean
Source:
function isUpper(x) {
var xUpper = x.toUpperCase();
var xLower = x.toLowerCase();
for (var i = 0; i < x.length; i += 1) {
if (xUpper[i] === xLower[i] || x[i] !== xUpper[i]) {
return false;
}
}
return true;
}
ord
Char → Integer
Source:
function ord(x) {
return x.charCodeAt(0);
}
Control
async
Source:
function async(f) {
return function () {
try {
var callback = arguments[arguments.length - 1];
var result = f.apply(null, [].slice.call(arguments, 0, arguments.length - 1));
setImmediate(function () { callback(null, result); });
} catch (e) {
setImmediate(function () { callback(e); });
}
};
}
pipe
Source:
function pipe() {
var functions, intermediateResult, callback;
var error = null;
if (isArray(arguments[0])) {
functions = arguments[0];
callback = arguments[1];
} else {
functions = arguments;
}
if (functions.length > 0) {
if (isFunction(functions[0])) {
intermediateResult = functions[0]();
} else {
intermediateResult = functions[0];
}
for (var i = 1; i < functions.length; i += 1) {
try {
intermediateResult = functions[i](intermediateResult);
} catch (err) {
error = err;
}
}
}
if (isFunction(callback)) {
callback(error, intermediateResult);
} else if (error) {
throw error;
}
return intermediateResult;
}
run
Source:
function run(specification) {
// this function does its own currying.
if (arguments.length === 2) {
run(specification)(arguments[1]);
return;
}
// if spec is an array, translate to object spec
if (isArray(specification)) {
var prev = null;
var newSpec = {};
each(function (func, taskName) {
newSpec[taskName] = prev === null ? func : [ prev, func ];
prev = taskName;
}, specification);
specification = newSpec;
}
var tasks = {};
var initial = [];
// prepare tasks specification.
each(function (spec, name) {
var dependencies = [];
var func = null;
if (isArray(spec)) {
dependencies = init(spec);
func = last(spec);
} else {
if (isArray(spec.depends)) {
dependencies = spec.depends;
}
func = spec;
}
var task = {
func: func,
args: dependencies,
depends: {},
enables: tasks[name] ? tasks[name].enables : {}
};
each(function (dependency) {
task.depends[dependency] = true;
if (!tasks[dependency]) {
tasks[dependency] = { enables: {} };
}
tasks[dependency].enables[name] = true;
}, dependencies);
tasks[name] = task;
}, specification);
// check spec for unmet dependencies
var unmetDependencies = [];
each(function (task, taskName) {
each(function (_, dependency) {
if (!specification[dependency]) {
unmetDependencies.push([ taskName, dependency ]);
}
}, task.depends);
}, tasks);
function mkError(message) {
return function (callback) {
setImmediate(function () {
callback(message);
});
};
}
if (!isEmpty(unmetDependencies)) {
return mkError({
message: 'unmet dependencies',
details: map(function (detail) {
return '`' +
detail[0] + '` depends on `' +
detail[1] + '` which is not defined';
}, unmetDependencies)
});
}
// build initial set
each(function (task, taskName) {
if (isEmpty(task.depends)) {
initial.push(taskName);
}
}, tasks);
if (isEmpty(initial)) {
return mkError({
message: 'no initial task',
details: 'There is no task without any dependencies.'
});
}
// check spec for cycles
var cycles = [];
each(function (taskName) {
var visited = {};
var path = [];
function visit(node) {
path.push(node);
if (visited[node]) {
cycles.push(map(id, path));
} else {
visited[node] = true;
each(visit, Object.keys(tasks[node].enables));
}
delete visited[path.pop()];
}
visit(taskName);
}, initial);
if (!isEmpty(cycles)) {
cycles = map(function (cycle) {
cycle = dropWhile(NEQ(last(cycle)), cycle);
return reverse(cycle);
}, cycles);
return mkError({
message: 'cycle detected',
details: map(intercalate(' -> '), cycles)
});
}
return function _runTasks(callback) {
var depends = {},
toGo = length(tasks),
results = map(function (task, taskName) {
return { toGo: length(task.enables) };
}, tasks);
function callbackHandle(taskName) {
return function (error, result) {
if (!error) {
results[taskName].result = result;
} else {
results[taskName].error = error;
}
// clean up results if need be
each(function (_, dependency) {
results[dependency].toGo -= 1;
if (results[dependency].toGo === 0) {
delete results[dependency];
}
}, tasks[taskName].depends);
toGo -= 1;
if (toGo === 0) {
// clean results object
each(function (result) {
delete result.toGo;
}, results);
callback(null, results);
} else {
each(function (_, next) {
delete depends[next][taskName];
if (isEmpty(depends[next])) {
execute(next);
}
}, tasks[taskName].enables);
}
};
}
function execute(taskName) {
var task = tasks[taskName],
callback = callbackHandle(taskName),
dependenciesFailed = false,
args = map(function (dependency) {
if (results[dependency].error) {
dependenciesFailed = true;
}
return results[dependency].result;
}, task.args);
if (dependenciesFailed && isFunction(task.func.runOnError)) {
var tempResult = {};
each(function (dependency) {
var result = results[dependency];
var stubResult = {};
if (result.error) {
stubResult.error = result.error;
} else {
stubResult.result = result.result;
}
tempResult[dependency] = stubResult;
}, task.args);
tempResult = task.func.runOnError(tempResult) || tempResult;
args = map(function (dependency) {
return tempResult[dependency].result;
}, task.args);
}
args.push(callback);
setImmediate(function _executeTask() {
if (dependenciesFailed && !task.func.runOnError) {
callback({ message: 'dependencies failed' });
} else {
var f = task.func;
if (isObject(f)) {
f = f.func;
}
try {
f.apply(null, args);
} catch (e) {
callback(e);
}
}
});
}
each(function (task, taskName) {
depends[taskName] = clone(task.depends);
}, tasks);
each(execute, initial);
};
}
Collection
AND && Prelude: &&
Boolean → Boolean → Boolean
Boolean "and". This is effectively just making the &&
operator
available as a curried function.
Not to be confused with the lower case and.
Example:
AND(true, true) === true
AND(false)(true) === false
foldl(AND, true, [ true, false ]) === false
Haskell Definition:
True && True = True
_ && _ = False
Source:
function AND(a, b) {
return a && b;
}
bool
Boolean → Boolean → Boolean
Fold on Boolean
. bool(x, y, c)
evaluates to x
if c
is false
and to y
otherwise.
Haskell Definition:
bool no yes condition = case condition of
True -> yes
False -> no
Source:
function bool(no, yes, bool) {
return bool ? yes : no;
}
not Prelude: not
Boolean → Boolean
Negates a boolean value.
This is basically JavaScripts unary prefix operator !
defined as a function.
Example:
not(true) === false
Haskell Definition:
not False = True
not _ = False
Source:
function not(value) {
return !value;
}
OR || Prelude: ||
Boolean → Boolean → Boolean
Booleanm "or". This is effectively just making the &&
operator
available as a curried function.
Not to be confused with the lower case or.
Example:
OR(false, true) === true
OR(false)(false) === false
foldl(OR, false, [ true, false ]) === true
Haskell Definition:
False && False = False
_ && _ = True
Source:
function OR(a, b) {
return a || b;
}
chr
Integer → Char
Source:
function chr(x) {
return String.fromCharCode(x);
}
isAsciiLetter
String → Boolean
Determines whether the given String or Character is an ascii letter, that is: Matching the regular expression /^[a-zA-Z]+$/
.
Example:
isAsciiLetter('X') === true
isAsciiLetter('@') === false
isAsciiLetter('8') === false
Source:
function isAsciiLetter(x) {
return /^[a-zA-Z]+$/.test(x);
}
isLetter
Char → Boolean
Source:
function isLetter(x) {
var xUpper = x.toUpperCase();
var xLower = x.toLowerCase();
for (var i = 0; i < x.length; i += 1) {
if (xUpper[i] === xLower[i]) {
return false;
}
}
return true;
}
isLower
String → Boolean
Source:
function isLower(x) {
var xUpper = x.toUpperCase();
var xLower = x.toLowerCase();
for (var i = 0; i < x.length; i += 1) {
if (xUpper[i] === xLower[i] || x[i] !== xLower[i]) {
return false;
}
}
return true;
}
isNumeric isDigit
Something → Boolean
Source:
function isNumeric(thing) {
return /^[0-9]+$/.test(thing);
}
isUpper
String → Boolean
Source:
function isUpper(x) {
var xUpper = x.toUpperCase();
var xLower = x.toLowerCase();
for (var i = 0; i < x.length; i += 1) {
if (xUpper[i] === xLower[i] || x[i] !== xUpper[i]) {
return false;
}
}
return true;
}
ord
Char → Integer
Source:
function ord(x) {
return x.charCodeAt(0);
}
Control
async
Source:
function async(f) {
return function () {
try {
var callback = arguments[arguments.length - 1];
var result = f.apply(null, [].slice.call(arguments, 0, arguments.length - 1));
setImmediate(function () { callback(null, result); });
} catch (e) {
setImmediate(function () { callback(e); });
}
};
}
pipe
Source:
function pipe() {
var functions, intermediateResult, callback;
var error = null;
if (isArray(arguments[0])) {
functions = arguments[0];
callback = arguments[1];
} else {
functions = arguments;
}
if (functions.length > 0) {
if (isFunction(functions[0])) {
intermediateResult = functions[0]();
} else {
intermediateResult = functions[0];
}
for (var i = 1; i < functions.length; i += 1) {
try {
intermediateResult = functions[i](intermediateResult);
} catch (err) {
error = err;
}
}
}
if (isFunction(callback)) {
callback(error, intermediateResult);
} else if (error) {
throw error;
}
return intermediateResult;
}
run
Source:
function run(specification) {
// this function does its own currying.
if (arguments.length === 2) {
run(specification)(arguments[1]);
return;
}
// if spec is an array, translate to object spec
if (isArray(specification)) {
var prev = null;
var newSpec = {};
each(function (func, taskName) {
newSpec[taskName] = prev === null ? func : [ prev, func ];
prev = taskName;
}, specification);
specification = newSpec;
}
var tasks = {};
var initial = [];
// prepare tasks specification.
each(function (spec, name) {
var dependencies = [];
var func = null;
if (isArray(spec)) {
dependencies = init(spec);
func = last(spec);
} else {
if (isArray(spec.depends)) {
dependencies = spec.depends;
}
func = spec;
}
var task = {
func: func,
args: dependencies,
depends: {},
enables: tasks[name] ? tasks[name].enables : {}
};
each(function (dependency) {
task.depends[dependency] = true;
if (!tasks[dependency]) {
tasks[dependency] = { enables: {} };
}
tasks[dependency].enables[name] = true;
}, dependencies);
tasks[name] = task;
}, specification);
// check spec for unmet dependencies
var unmetDependencies = [];
each(function (task, taskName) {
each(function (_, dependency) {
if (!specification[dependency]) {
unmetDependencies.push([ taskName, dependency ]);
}
}, task.depends);
}, tasks);
function mkError(message) {
return function (callback) {
setImmediate(function () {
callback(message);
});
};
}
if (!isEmpty(unmetDependencies)) {
return mkError({
message: 'unmet dependencies',
details: map(function (detail) {
return '`' +
detail[0] + '` depends on `' +
detail[1] + '` which is not defined';
}, unmetDependencies)
});
}
// build initial set
each(function (task, taskName) {
if (isEmpty(task.depends)) {
initial.push(taskName);
}
}, tasks);
if (isEmpty(initial)) {
return mkError({
message: 'no initial task',
details: 'There is no task without any dependencies.'
});
}
// check spec for cycles
var cycles = [];
each(function (taskName) {
var visited = {};
var path = [];
function visit(node) {
path.push(node);
if (visited[node]) {
cycles.push(map(id, path));
} else {
visited[node] = true;
each(visit, Object.keys(tasks[node].enables));
}
delete visited[path.pop()];
}
visit(taskName);
}, initial);
if (!isEmpty(cycles)) {
cycles = map(function (cycle) {
cycle = dropWhile(NEQ(last(cycle)), cycle);
return reverse(cycle);
}, cycles);
return mkError({
message: 'cycle detected',
details: map(intercalate(' -> '), cycles)
});
}
return function _runTasks(callback) {
var depends = {},
toGo = length(tasks),
results = map(function (task, taskName) {
return { toGo: length(task.enables) };
}, tasks);
function callbackHandle(taskName) {
return function (error, result) {
if (!error) {
results[taskName].result = result;
} else {
results[taskName].error = error;
}
// clean up results if need be
each(function (_, dependency) {
results[dependency].toGo -= 1;
if (results[dependency].toGo === 0) {
delete results[dependency];
}
}, tasks[taskName].depends);
toGo -= 1;
if (toGo === 0) {
// clean results object
each(function (result) {
delete result.toGo;
}, results);
callback(null, results);
} else {
each(function (_, next) {
delete depends[next][taskName];
if (isEmpty(depends[next])) {
execute(next);
}
}, tasks[taskName].enables);
}
};
}
function execute(taskName) {
var task = tasks[taskName],
callback = callbackHandle(taskName),
dependenciesFailed = false,
args = map(function (dependency) {
if (results[dependency].error) {
dependenciesFailed = true;
}
return results[dependency].result;
}, task.args);
if (dependenciesFailed && isFunction(task.func.runOnError)) {
var tempResult = {};
each(function (dependency) {
var result = results[dependency];
var stubResult = {};
if (result.error) {
stubResult.error = result.error;
} else {
stubResult.result = result.result;
}
tempResult[dependency] = stubResult;
}, task.args);
tempResult = task.func.runOnError(tempResult) || tempResult;
args = map(function (dependency) {
return tempResult[dependency].result;
}, task.args);
}
args.push(callback);
setImmediate(function _executeTask() {
if (dependenciesFailed && !task.func.runOnError) {
callback({ message: 'dependencies failed' });
} else {
var f = task.func;
if (isObject(f)) {
f = f.func;
}
try {
f.apply(null, args);
} catch (e) {
callback(e);
}
}
});
}
each(function (task, taskName) {
depends[taskName] = clone(task.depends);
}, tasks);
each(execute, initial);
};
}
Collection
async
Source:
function async(f) {
return function () {
try {
var callback = arguments[arguments.length - 1];
var result = f.apply(null, [].slice.call(arguments, 0, arguments.length - 1));
setImmediate(function () { callback(null, result); });
} catch (e) {
setImmediate(function () { callback(e); });
}
};
}
pipe
Source:
function pipe() {
var functions, intermediateResult, callback;
var error = null;
if (isArray(arguments[0])) {
functions = arguments[0];
callback = arguments[1];
} else {
functions = arguments;
}
if (functions.length > 0) {
if (isFunction(functions[0])) {
intermediateResult = functions[0]();
} else {
intermediateResult = functions[0];
}
for (var i = 1; i < functions.length; i += 1) {
try {
intermediateResult = functions[i](intermediateResult);
} catch (err) {
error = err;
}
}
}
if (isFunction(callback)) {
callback(error, intermediateResult);
} else if (error) {
throw error;
}
return intermediateResult;
}
run
Source:
function run(specification) {
// this function does its own currying.
if (arguments.length === 2) {
run(specification)(arguments[1]);
return;
}
// if spec is an array, translate to object spec
if (isArray(specification)) {
var prev = null;
var newSpec = {};
each(function (func, taskName) {
newSpec[taskName] = prev === null ? func : [ prev, func ];
prev = taskName;
}, specification);
specification = newSpec;
}
var tasks = {};
var initial = [];
// prepare tasks specification.
each(function (spec, name) {
var dependencies = [];
var func = null;
if (isArray(spec)) {
dependencies = init(spec);
func = last(spec);
} else {
if (isArray(spec.depends)) {
dependencies = spec.depends;
}
func = spec;
}
var task = {
func: func,
args: dependencies,
depends: {},
enables: tasks[name] ? tasks[name].enables : {}
};
each(function (dependency) {
task.depends[dependency] = true;
if (!tasks[dependency]) {
tasks[dependency] = { enables: {} };
}
tasks[dependency].enables[name] = true;
}, dependencies);
tasks[name] = task;
}, specification);
// check spec for unmet dependencies
var unmetDependencies = [];
each(function (task, taskName) {
each(function (_, dependency) {
if (!specification[dependency]) {
unmetDependencies.push([ taskName, dependency ]);
}
}, task.depends);
}, tasks);
function mkError(message) {
return function (callback) {
setImmediate(function () {
callback(message);
});
};
}
if (!isEmpty(unmetDependencies)) {
return mkError({
message: 'unmet dependencies',
details: map(function (detail) {
return '`' +
detail[0] + '` depends on `' +
detail[1] + '` which is not defined';
}, unmetDependencies)
});
}
// build initial set
each(function (task, taskName) {
if (isEmpty(task.depends)) {
initial.push(taskName);
}
}, tasks);
if (isEmpty(initial)) {
return mkError({
message: 'no initial task',
details: 'There is no task without any dependencies.'
});
}
// check spec for cycles
var cycles = [];
each(function (taskName) {
var visited = {};
var path = [];
function visit(node) {
path.push(node);
if (visited[node]) {
cycles.push(map(id, path));
} else {
visited[node] = true;
each(visit, Object.keys(tasks[node].enables));
}
delete visited[path.pop()];
}
visit(taskName);
}, initial);
if (!isEmpty(cycles)) {
cycles = map(function (cycle) {
cycle = dropWhile(NEQ(last(cycle)), cycle);
return reverse(cycle);
}, cycles);
return mkError({
message: 'cycle detected',
details: map(intercalate(' -> '), cycles)
});
}
return function _runTasks(callback) {
var depends = {},
toGo = length(tasks),
results = map(function (task, taskName) {
return { toGo: length(task.enables) };
}, tasks);
function callbackHandle(taskName) {
return function (error, result) {
if (!error) {
results[taskName].result = result;
} else {
results[taskName].error = error;
}
// clean up results if need be
each(function (_, dependency) {
results[dependency].toGo -= 1;
if (results[dependency].toGo === 0) {
delete results[dependency];
}
}, tasks[taskName].depends);
toGo -= 1;
if (toGo === 0) {
// clean results object
each(function (result) {
delete result.toGo;
}, results);
callback(null, results);
} else {
each(function (_, next) {
delete depends[next][taskName];
if (isEmpty(depends[next])) {
execute(next);
}
}, tasks[taskName].enables);
}
};
}
function execute(taskName) {
var task = tasks[taskName],
callback = callbackHandle(taskName),
dependenciesFailed = false,
args = map(function (dependency) {
if (results[dependency].error) {
dependenciesFailed = true;
}
return results[dependency].result;
}, task.args);
if (dependenciesFailed && isFunction(task.func.runOnError)) {
var tempResult = {};
each(function (dependency) {
var result = results[dependency];
var stubResult = {};
if (result.error) {
stubResult.error = result.error;
} else {
stubResult.result = result.result;
}
tempResult[dependency] = stubResult;
}, task.args);
tempResult = task.func.runOnError(tempResult) || tempResult;
args = map(function (dependency) {
return tempResult[dependency].result;
}, task.args);
}
args.push(callback);
setImmediate(function _executeTask() {
if (dependenciesFailed && !task.func.runOnError) {
callback({ message: 'dependencies failed' });
} else {
var f = task.func;
if (isObject(f)) {
f = f.func;
}
try {
f.apply(null, args);
} catch (e) {
callback(e);
}
}
});
}
each(function (task, taskName) {
depends[taskName] = clone(task.depends);
}, tasks);
each(execute, initial);
};
}
Nodash knows four different types of collections:
- Array
- String
- List
- Stream
Those are typically distinguished as belonging to either Array-like or List-like.
A JavaScript String is an Array-like type, a Stream is a List-like type. Array
and Strings
are the native types from JavaScript, List and
Stream are introduced by Nodash.
Properties of the various type, where x
is a value of the given type,
i
is an index, and n
is the number of elements.
Array | String | List | Stream | |
---|---|---|---|---|
evaluation | strict | strict | lazy | lazy |
mutability | mutable | immutable | immutable | immutable |
typeOf(x) | array |
string |
list |
stream |
elements | arbitrary | characters | arbitrary | arbitrary |
limit | finite | finite | finite | infinite |
at(i, x) | O(1) | O(1) | O(n) | O(n) |
all Prelude: all
(a → Bool) → [a] → Bool
Applied to a predicate and a list, all
determines if all
elements of the list satisfy the given predicate.
Example:
all(even, [1, 2, 3]) === false
all(lte(3), [1, 2, 3]) === true
This function works with strings too:
all(isDigit, "123") === true
Source:
function all(p, xs) {
for (var i = 0; i < xs.length; i++) {
if (!p(xs[i])) {
return false;
}
}
return true;
}
and Prelude: and
[Bool] → Bool
Returns the conjunction of a list of booleans, i.e. it returns
true
iff all the elements in the list evaluate to true
.
NOTE: This, the lowercase and
, is not the binary boolean operator, which
is the uppercase AND
.
Example:
and([true, true, true]) === true
and([true, false, true]) === false
and([1, 1, 1]) === true
and([]) === false
Source:
var and = /* this is a composed function */
foldl foldl'reduceLeft Prelude: foldl'
(a → b → b) → b → [a] → b
Left-associative fold of a structure.
Haskell Definition:
foldl :: (a -> b -> b) -> b -> [a] -> b
foldl f s xs = case xs of
[] -> s
(x : xs) -> foldl f (f x s) xs
Source:
function foldl(f, x, xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
for (var i = 0; i < xs.length; i += 1) {
x = f(x, xs[i]);
}
return x;
case 'list':
while (!xs.isEmpty()) {
x = f(xs.head(), x);
xs = xs.tail();
}
return x;
}
}
foldr reduceRight Prelude: foldr
(b → a → b) → b → [a] → b
Right-associative fold of a structure.
Haskell Definition:
foldr :: (b -> a -> b) -> b -> [a] -> b
foldr f s xs = case xs of
[] -> s
(x : xs) -> f (foldr f s xs) x
Source:
function foldr(f, x, xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
for (var i = xs.length - 1; i >= 0; i -= 1) {
x = f(xs[i], x);
}
return x;
case 'list':
if (xs.isEmpty()) {
return x;
}
return f(foldr(f, x, xs.tail()), xs.head());
}
}
isInfixOf Prelude: isInfixOf
[a] → [a] → Boolean
The isInfixOf function takes two lists and returns true
iff the first list is contained, wholly and intact, anywhere
within the second.
It uses an implementation of the Knuth-Morris-Pratt algorithm and works with both strings and arrays.
Source:
function isInfixOf(infix, string) {
return indexOf(infix, string) >= 0;
}
isPrefixOf Prelude: isPrefixOf
[a] → [a] → Boolean
The isPrefixOf function takes two lists and returns true
iff the first list is a prefix of the second.
Source:
function isPrefixOf(prefix, string) {
for (var j = 0; j < prefix.length; j++) {
if (string[j] !== prefix[j]) {
return false;
}
}
return true;
}
isSuffixOf Prelude: isSuffixOf
[a] → [a] → Boolean
The isSuffixOf function takes two lists and returns true
iff the first list is a suffix of the second.
Source:
function isSuffixOf(suffix, string) {
for (var i = 0; i < suffix.length; i++) {
if (string[string.length - suffix.length + i] !== suffix[i]) {
return false;
}
}
return true;
}
permutations Prelude: permutations
[a] → [[a]]
Generates a list of permutations using the Steinhaus-Johnson-Trotter algorithm.
This function returns an array of all the permutations if an array or a string is passed, or a lazily evaluated list if a list is passed.
Example using a string:
permutations('abc')
// → [ 'abc', 'acb', 'cab', 'cba', 'bca', 'bac' ]
Example using a list:
permutations(lazy([ 7, 4 ]))
// → [ [ 7, 4 ], [ 4, 7 ] ]
Source:
function permutations(thing) {
switch (typeOf(thing)) {
case 'array':
case 'string':
return sjt.all(thing);
case 'list':
return generateList(listToArray(thing));
default:
error(TypeError);
}
}
sum Prelude: sum
[Number] → Number
The sum function computes the sum of a list of numbers.
Example:
sum([1, 4, 9]) === 14
Source:
var sum = /* this is a composed function */
zip Prelude: zip
Source:
var zip = /* this is a composed function */
zip3 Prelude: zip3
Source:
var zip3 = /* this is a composed function */
zip4 Prelude: zip4
Source:
var zip4 = /* this is a composed function */
zipWith Prelude: zipWith
Source:
function zipWith(f, as, bs) {
var length = Math.min(as.length, bs.length);
var zs = [];
for (var i = 0; i < length; i++) {
zs[i] = f(as[i], bs[i]);
}
return zs;
}
zipWith3 Prelude: zipWith3
Source:
function zipWith3(f, as, bs, cs) {
var length = minimum([as.length, bs.length, cs.length]);
var zs = [];
for (var i = 0; i < length; i++) {
zs[i] = f(as[i], bs[i], cs[i]);
}
return zs;
}
zipWith4 Prelude: zipWith4
Source:
function zipWith4(f, as, bs, cs, ds) {
var length = minimum([as.length, bs.length, cs.length, ds.length]);
var zs = [];
for (var i = 0; i < length; i++) {
zs[i] = f(as[i], bs[i], cs[i], ds[i]);
}
return zs;
}
Either
Either
Source:
function Either() {
fail();
}
isLeft
Either a b → Boolean
Source:
var isLeft = /* this is a composed function */
isRight
Either a b → Boolean
Source:
var isRight = /* this is a composed function */
Left
Source:
function Left(value) {
if (!(this instanceof Left)) {
return new Left(value);
}
this.value = idf(value);
}
lefts
Source:
var lefts = /* this is a composed function */
partitionEithers
Source:
function partitionEithers(xs) {
return tuple(lefts(xs), rights(xs));
}
Right
Source:
function Right(value) {
if (!(this instanceof Right)) {
return new Right(value);
}
this.value = idf(value);
}
rights
Source:
var rights = /* this is a composed function */
Function
apply
$
Prelude: $
Haskell Definition:
apply func arg = func arg
Source:
function apply(f, x) {
return f(x);
}
compose
.
Prelude: .
(b → c) → (a → b) → a → c
Function composition.
Example:
var f = compose(plus(10), times(2));
f(3) === 16
Haskell Definition:
compose g f = \x -> g (f x)
Source:
function compose(f, g, x) {
return f(g(x));
}
compose2
Source:
function compose2(f, g, x, y) {
return f(g(x, y));
}
const
const_constant
Prelude: const
Haskell Definition:
const = \a _ -> a
Source:
function const(a, b) {
return a;
}
curry
Prelude: curry
Source:
function curry(f) {
return curried(function (a, b) {
return f(tuple(a, b));
});
}
flip
Prelude: flip
(a → b → c) → (b → a → c)
flip(f)
takes its (first) two arguments in the reverse order of f
.
Example:
minus(10, 8) === 2
var subtract = flip(minus)
subtract(10, 8) === -2
Haskell Definition:
flip f = \a b -> f b a
Source:
function flip(f) {
return curried(function (b, a) {
return f(a, b);
});
}
id
Prelude: id
a → a
Identity function.
Example:
id(7) === 7
Haskell Definition:
id = \x -> x
Source:
function id(x) { return x; }
idf
Source:
function idf(x) {
return function () {
return x;
};
}
invoke
Source:
function invoke(f) {
return f();
}
on
(b → b → c) → (a → b) → a → a → c
Example:
var xs = [
{ firstName: 'Jonathan', secondName: 'Müller' },
{ firstName: 'Benjamin', secondName: 'Bamboo' }
];
var sortByFirstName = sortBy(on(compare, select('firstName')), xs);
Haskell Definition:
(.*.) `on` f = \x y -> f x .*. f y
Source:
function on(g, f, a, b) {
return g(f(a), f(b));
}
uncurry
Prelude: uncurry
Source:
function uncurry(f) {
return function (t) {
return f(fst(t), snd(t));
};
}
List
arrayToString
Source:
function arrayToString(array) {
return array.join('');
}
lazy
arrayToList
Source:
function lazy(val) {
if (isFunction(val)) {
return new Thunk(val);
}
function generator(i) {
if (i < val.length) {
return new List(val[i], new Thunk(function () {
return generator(i + 1);
}));
}
return emptyList();
}
return generator(0);
}
List
new List(head, tail) :: a → [a] → [a]
Lists are immutable singly-linked sequences.
Methods:
- .head() → a
- Extract the first element in the list.
- .tail() → List a
- Extract the rest of the list.
Lists are typically not constructed by user code with this
constructor, but with builers such as arrayToList.
The purpose of the List type is to implement lazy evaluation.
Internally the head and the tail of a list may actually be Thunks
which are evaluated only if you call .head()
or .tail()
respectively.
To construct lazy lists, use lazy.
Example:
var xs = new List(38, new List(42, emptyList()))
console.log(xs.head()) // 38
console.log(xs.tail().head()) // 42
head
and tail
are functional forms of .head()
and .tail()
.
var xs = lazy([1, 2, 3, 4, 5]);
console.log(head(xs)); // 1
console.log(head(tail(xs))); // 2
Haskell Definition:
data List a = EmptyList | Cons { head :: a, tail :: (List a) }
Source:
function List(head, tail) {
var self = this;
this.head = function () {
if (is(Thunk, head)) {
var value = head.get();
self.head = head.get;
return value;
}
return head;
};
this.tail = function () {
if (is(Thunk, tail)) {
var value = tail.get();
self.tail = tail.get;
return value;
}
return tail;
};
}
listToArray
Source:
function listToArray(xs) {
var array = [];
each(function (x) {
array.push(x);
}, xs);
return array;
}
listToString
Source:
var listToString = /* this is a composed function */
range
..
Source:
function range(from, to) {
return rangeStep(1, from, to);
}
rangeStep
Source:
function rangeStep(step, from, to) {
step = from < to ? step : -step;
to = step > 0 ? Math.floor(to) : Math.ceil(to);
var current = from;
function gen() {
current += step;
return new List(current, current === to ? emptyList : new Thunk(gen));
}
return new List(from, new Thunk(gen));
}
singleton
Source:
function singleton(thing) {
return new List(thing, emptyList);
}
Maybe
catMaybes
Source:
var catMaybes = /* this is a composed function */
isJust
Source:
function isJust(thing) {
return thing !== null && thing !== undefined;
}
isNothing
Source:
function isNothing(thing) {
return !isJust(thing);
}
mapMaybe
Source:
var mapMaybe = /* this is a composed function */
maybe
Prelude: maybe
Source:
function maybe(def, fun, value) {
if (value === null || value === undefined) {
return def;
}
return fun(value);
}
maybeToList
Source:
function maybeToList(thing) {
if (isJust(thing)) {
return singleton(thing);
}
return emptyList();
}
Math
abs
Prelude: abs
Number → Number
Returns the absolute (positive, non-negative) value of a number.
Example:
abs(9) === 9
abs(-3) === 3
Haskell Definition:
abs x | x >= 0 = x
| x < 0 = -x
Source:
function abs() { [native code] }
acos
Prelude: acos
Number → Number
Source:
function acos() { [native code] }
acosh
Prelude: acosh
Number → Number
Source:
function acosh(x) {
return Math.log(x + Math.sqrt(x * x - 1));
}
add
+ADDplusPLUS
Prelude: +
Number → Number → Number
Source:
function add(a, b) {
return a + b;
}
asin
Prelude: asin
Number → Number
Source:
function asin() { [native code] }
asinh
Prelude: asinh
Number → Number
Source:
function asinh(x) {
if (x === -Infinity) {
return x;
} else {
return Math.log(x + Math.sqrt(x * x + 1));
}
}
atan
Prelude: atan
Number → Number
Source:
function atan() { [native code] }
atanh
Prelude: atanh
Number → Number
Source:
function atanh(x) {
return Math.log((1 + x) / (1 - x)) / 2;
}
ceiling
Prelude: ceiling
Number → Number
ceiling x
returns the least integer not less than x
.
Source:
function ceil() { [native code] }
cos
Prelude: cos
Number → Number
Source:
function cos() { [native code] }
cosh
Prelude: cosh
Number → Number
Source:
function cosh(x) {
return (Math.exp(x) + Math.exp(-x)) / 2;
}
div
Prelude: div
Number → Number
Source:
function div(a, b) {
return Math.floor(a / b);
}
divMod
Prelude: divMod
Number → Number → (Number, Number)
Source:
function divMod(a, b) {
return tuple(div(a, b), mod(a, b));
}
even
Prelude: even
Number → Bool
Source:
function even(x) {
return (x % 2) === 0;
}
exp
Prelude: exp
Number → Number
Source:
function exp() { [native code] }
floor
Prelude: floor
Number → Number
floor x
returns the greatest integer not greater than x
.
Source:
function floor() { [native code] }
frac
/
Prelude: /
Number → Number → Number
Source:
function frac(a, b) {
return a / b;
}
gcd
Prelude: gcd
Number → Number → Number
Source:
function gcd(a, b) {
var c;
while (b !== 0) {
c = rem(a, b);
a = b;
b = c;
}
return a;
}
lcm
Prelude: lcm
Number → Number → Number
Source:
function lcm(a, b) {
if (a === 0 || b === 0) {
return 0;
}
return Math.abs(quot(a, gcd(a, b)) * b);
}
log
Prelude: log
Number → Number
Source:
function log() { [native code] }
logBase
Prelude: logBase
Number → Number → Number
Haskell Definition:
logBase x y = log y / log x
Source:
function logBase(a, b) {
return Math.log(a) / Math.log(b);
}
minus
-MINUS
Prelude: -
Number → Number → Number
Source:
function minus(a, b) {
return a - b;
}
mod
Prelude: mod
Number → Number → Number
Source:
function mod(a, b) {
var q = quot(a, b);
var r = rem(a, b);
return signum(r) === -signum(b) ? r + b : r;
}
mul
*MULtimesTIMES
Prelude: *
Number → Number → Number
Source:
function mul(a, b) {
return a * b;
}
negate
Prelude: negate
Number → Number
Source:
function negate(x) {
return -x;
}
odd
Prelude: odd
Number → Boolean
Source:
function odd(x) {
return (x % 2) !== 0;
}
pow
**^^^
Prelude: ^^
Haskell Definition:
x ** y = exp (log x * y)
Source:
function pow() { [native code] }
properFraction
Prelude: properFraction
Number → (Number, Number)
properFraction
takes a real fractional
number x
and returns a pair (n, f)
such that x = n + f
,
and: n
is an integral number with the same sign as x
;
and f
is a fraction with the same type and sign as x
,
and with absolute value less than 1.
Source:
function properFraction(x) {
var num = truncate(x);
return tuple(num, -(num - x));
}
quot
Prelude: quot
Number → Number → Number
Source:
function quot(a, b) {
var r = a / b;
return r >= 0 ? Math.floor(r) : Math.ceil(r);
}
quotRem
Prelude: quotRem
Number → Number → (Number, Number)
Source:
function quotRem(a, b) {
return tuple(quot(a, b), rem(a, b));
}
recip
Prelude: recip
Haskell Definition:
recip = 1 / x
Source:
function recip(x) {
return 1 / x;
}
rem
Prelude: rem
Number → Number → Number
Source:
function rem(a, b) {
return a % b;
}
round
Prelude: round
Number → Number
round x
returns the nearest integer to x
; the even
integer if x
is equidistant between two integers.
Source:
function round(x) {
var fraction = properFraction(x);
var n = fraction[0];
var m = fraction[1] < 0 ? n - 1 : n + 1;
switch (signum(Math.abs(fraction[1]) - 0.5)) {
case -1:
return n;
case 0:
return n % 2 === 0 ? n : m;
case 1:
return m;
}
}
signum
Prelude: signum
Number → Number
Haskell Definition:
signum x | x > 0 = 1
| x == 0 = 0
| x < 0 = -1
Source:
function signum(x) {
if (x > 0) {
return 1;
} else if (x === 0) {
return 0;
}
return -1;
}
sin
Prelude: sin
Number → Number
Source:
function sin() { [native code] }
sqrt
Prelude: sqrt
Number → Number
Source:
function sqrt() { [native code] }
sub
subtract
Prelude: subtract
Number → Number
Source:
function sub(a, b) {
return b - a;
}
tan
Prelude: tan
Number → Number
Haskell Definition:
tan x = sin x / cos x
Source:
function tan() { [native code] }
tanh
Prelude: tanh
Number → Number
Haskell Definition:
tanh x = sinh x / cosh x
Source:
function tanh(x) {
if (x === Infinity) {
return 1;
} else if (x === -Infinity) {
return -1;
} else {
return (Math.exp(x) - Math.exp(-x)) / (Math.exp(x) + Math.exp(-x));
}
}
truncate
Prelude: truncate
Number → Number
truncate x
returns the integer nearest x
between zero and x
.
Source:
function truncate(x) {
switch (signum(x)) {
case -1:
return Math.ceil(x);
case 1:
return Math.floor(x);
}
return 0;
}
Nodash
install
Source:
function install(mountpoint) {
var options = arguments[1];
var nodashObject = Nodash;
var prefix = '';
var postfix = '';
if (!mountpoint) {
return Nodash;
}
if (options) {
nodashObject = makeNodash(options);
}
if (isArray(mountpoint)) {
if (isString(mountpoint[0])) {
prefix = [].shift.call(mountpoint);
}
if (isString(mountpoint[1])) {
postfix = mountpoint[1];
}
mountpoint = mountpoint[0] || {};
}
each(function (func, name) {
if (name[0] === '_') {
return;
}
var key = prefix + name + postfix;
if (!(key in mountpoint)) {
mountpoint[key] = func;
}
}, nodashObject);
return mountpoint;
}
register
Source:
function register() {
var args = [].slice.call(arguments);
if (arguments.length === 1) {
switch (typeof args[0]) {
case 'object':
if (Array.isArray(args[0])) {
registerInjected(args[0].slice());
} else {
registerLib(args[0]);
}
break;
case 'function':
register(args[0].call(Nodash));
break;
}
return;
}
var func = args.pop();
var aliases = [];
args.forEach(function (arg) {
[].push.apply(aliases, arg.split(/ +/));
});
var name = null;
for (var i = 0; i < aliases.length; i += 1) {
if (/^[a-z0-9]+$/i.test(aliases[i])) {
name = aliases[i];
break;
}
}
__metadata[name] = {
aliases: aliases,
definition: func
};
if (!/^[A-Z]/.test(name)) {
func = curried(func);
}
aliases.forEach(function (alias) {
Nodash[alias] = func;
});
}
Pattern
match
MatchSpec → Any → MatchResult
match(spec, value)
matches value
against the spec
, returning
what was captured in the spec.
A MatchSpec
is an array of arrays. Every array in the spec
must have two elements: [ 0: Pattern, 1: Result ]
. The first
Pattern
that matches value
will yield the associated Result
.
If Result
is a function it will be invoked with an object of
all captured variables in the Pattern
and the result will be returned,
otherwise the Result
itself.
Example:
var matchJohn = match([
[ { firstName: 'John' }, 'John is a fine name' ],
[ { firstName: '$firstName' },
function (result) {
return result.$firstName + ' is also a fine name'; } ]
]);
console.log(matchJohn({ firstName: 'John', lastName: 'Doe' }));
// → 'John is a fine name'
console.log(matchJohn({ firstName: 'Johnathan', lastName: 'X' }));
// → 'Jonathan is also a fine name'
Source:
function match(pattern, arg) {
for (var i = 0; i < pattern.length; i += 1) {
var result = {};
var p = pattern[i];
if (matchR(p[0], arg, result)) {
if (typeof p[1] === 'function') {
return p[1](result);
}
return p[1];
}
}
}
Object
each
Source:
function each(f, xs) {
if (is(List, xs)) {
while (!xs.isEmpty()) {
f(xs.head());
xs = xs.tail();
}
} else if (isArray(xs) || isString(xs)) {
for (var i = 0; i < xs.length; i++) {
f(xs[i], i);
}
} else if (isObject(xs)) {
var ks = Object.keys(xs);
for (var j = 0; j < ks.length; j += 1) {
f(xs[ks[j]], ks[j]);
}
}
}
keys
Source:
function keys() { [native code] }
values
Source:
function values(object) {
var values = [];
each(function (value) {
values.push(value);
}, object);
return values;
}
Stream
cycle
Prelude: cycle
Source:
function cycle(xs) {
if (isArray(xs)) {
xs = lazy(xs);
}
function generator(ys) {
if (ys.isEmpty()) {
ys = xs;
}
return function () {
return tuple(ys.head(), generator(ys.tail()));
};
}
return new Stream(generator(xs));
}
iterate
Prelude: iterate
Source:
function iterate(f, seed) {
function generator(seed) {
return function () {
var newSeed = f(seed);
return tuple(seed, generator(newSeed));
};
}
return new Stream(generator(seed));
}
repeat
Prelude: repeat
Source:
function repeat(x) {
function generator() {
return tuple(x, generator);
}
return new Stream(generator);
}
Stream
stream
new Stream(generator)
Streams are immutable, lazily evaluated, infinite Lists.
Methods:
- .head() → a
- Extract the first element of this stream.
- .tail() → List a
- Extract the rest of the stream.
Source:
function Stream(generator) {
if (!(this instanceof Stream)) {
return new Stream(generator);
}
var thunk = new Thunk(generator);
var self = this;
this.head = function () {
var value = thunk.get().fst();
self.head = idf(value);
return value;
};
this.tail = function () {
var value = thunk.get().snd();
switch (typeOf(value)) {
case 'list':
case 'stream':
break;
case 'function':
value = new Stream(value);
break;
default:
error(TypeError);
}
self.tail = idf(value);
return value;
};
}
until
Prelude: until
Source:
function until(p, f, v) {
while (!p(v)) {
v = f(v);
}
return v;
}
String
lines
Prelude: lines
Source:
function lines(string) {
var result = string.split(/\n/);
if (result[result.length - 1].length === 0) {
delete result[result.length - 1];
}
return result;
}
unlines
Prelude: unlines
Source:
function unlines(lines) {
return lines.join('\n');
}
unwords
Prelude: unwords
Source:
function unwords(words) {
return words.join(' ');
}
words
Prelude: words
Source:
function words(string) {
return string.split(/[\n\r\v\t ]/);
}
Tuple
fst
Prelude: fst
(a, b) → b
Extract the first component of a pair.
Tuples also have a fst()
method which does the same thing,
but this function is exposing that method as a function.
Haskell Definition:
fst (a, _) = a
Source:
function fst(t) {
return t.fst();
}
objectToArray
Object → [(String, Any)]
Turns an object into an associative list of tuples.
The objects keys are the first components of the tuples,
the values the second components.
eq( objectToArray({ a: 17, b: 20 }), [ tuple('a', 17), tuple('b', 20) ]) === true
Source:
function objectToArray(obj) {
var arr = [];
each(function (val, key) {
arr.push(new Tuple(key, val));
}, obj);
return arr;
}
snd
Prelude: snd
(a, b) → b
Extract the second component of a pair.
Tuples also have a fst()
method which does the same thing,
but this function is exposing that method as a function.
Haskell Definition:
snd (_, b) = b
Source:
function snd(t) {
return t.snd();
}
Tuple
new Tuple(first, second) :: a → b → (a, b)
Tuples are immutable pairs of a first and a second components.
Methods:
- .fst() → a
- Retrieves the first component of this tuple.
- .snd() → b
- Retrieves the second component of this tuple.
Example:
var t = new Tuple(4711, 8080);
console.log(t.fst()); // 4711
console.log(t.snd()); // 8080
fst
and snd
are functional forms of .fst()
and .snd()
.
tuple
is a convenience method for omitting new
:
var t = tuple(4711, 8080);
console.log(fst(t)); // 4711
console.log(snd(t)); // 8080
var extractFirsts = map(fst);
console.log(extractFirsts([
tuple(4711, 8080),
tuple(3000, 4444)
])); // [ 4711, 3000 ]
Haskell Definition:
data Tuple a b = Tuple { fst :: a, snd :: b }
Source:
function Tuple(fst, snd) {
if (!(this instanceof Tuple)) {
return new Tuple(fst, snd);
}
this.fst = idf(fst);
this.snd = idf(snd);
freeze(this);
}
tuple
,
Prelude: ,
Source:
function tuple(first, second) {
return new Tuple(first, second);
}
tuple3
,,
Source:
function tuple3(first, second, third) {
return tuple(first, tuple(second, third));
}
tuple4
,,,
Source:
function tuple4(first, second, third, fourth) {
return tuple3(first, second, tuple(third, fourth));
}
tuplesToObject
[(String, Any)] → Object
Turns an associative list of tuples into an object.
The first components of the tuples are the keys,
the second components the corresponding values.
Example:
eq( tuplesToObject([ tuple('a', 2), tuple('b', 3) ]), { a: 2, b: 3 }) === true
Source:
function tuplesToObject(xs) {
var obj = {};
each(function (t) {
obj[t.fst()] = t.snd();
}, xs);
return obj;
}
Type
classOf
Any → String
Determines the property of the internal
[[Class]]
attribute,
normalized to lower case.
Example:
classOf(new Date()) === 'date'
classOf(null) === 'null'
classOf([]) === 'array'
function f() {
return classOf(arguments)
}
f() === 'arguments'
Source:
function classOf(thing) {
var exactType = toString.call(thing);
return exactType.slice(8, exactType.length - 1).toLowerCase();
}
is
Source:
function is(type, thing) {
return thing instanceof type;
}
isArguments
Any → Boolean
Source:
function isArguments(thing) {
return toString.call(thing) === '[object Arguments]';
}
isArray
Any → Boolean
Determines whether something is an array or not.
This is exactly the same as Array.isArray
.
Example:
isArray([]) === true
isArray({}) === false
isArray(new Array(3)) === true
isArray(undefined) === false
isArray(3) === false
Source:
function isArray() { [native code] }
isBoolean
Any → Boolean
Returns true
if the argument is a boolean value, otherwise false
.
Example:
isBoolean(true) === true
isBoolean(false) === false
isBoolean({}) === false
isBoolean(undefined) === false
isBoolean(0) === false
isBoolean(1) === false
isBoolean("true") === false
Source:
function isBoolean(thing) {
return typeof thing === 'boolean';
}
isDate
Any → Boolean
Source:
function isDate(thing) {
return toString.call(thing) === '[object Date]';
}
isEmpty
null_
Prelude: null
Any → Boolean
Source:
function isEmpty(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs.length === 0;
case 'list':
case 'stream':
return xs.isEmpty();
default:
for (var _ in xs) {
return false;
}
return true;
}
}
isFunction
Any → Boolean
Source:
function isFunction(thing) {
return typeof thing === 'function';
}
isInteger
Any → Boolean
Returns true
is the argument is an integral number.
Numbers in JavaScript are floating point values and there is no proper integer type.
This function can be used to check whether a given number could be cast to an
integer without truncating.
isInteger(7) === true
isInteger(7.0) === true
isInteger(7.3) === false
Source:
function isInteger(thing) {
return isNumber(thing) && !isNaN(thing) &&
thing - Math.floor(thing) === 0 &&
thing !== Infinity && thing !== -Infinity;
}
isNull
Any → Boolean
Source:
function isNull(thing) {
return toString.call(thing) === '[object Null]';
}
isNumber
Source:
function isNumber(thing) {
return typeof thing === 'number';
}
isObject
Source:
function isObject(thing) {
return typeof thing === 'object' &&
thing !== null && !Array.isArray(thing);
}
isRegExp
Any → Boolean
Returns true
is the argument is a regular expression object.
Example:
isRegExp(/a+/) === true
isRegExp("a+") === false
isRegExp(new RegExp("a+")) === true
Source:
function isRegExp(thing) {
return toString.call(thing) === '[object RegExp]';
}
isString
Source:
function isString(thing) {
return typeof thing === 'string' || toString.call(thing) === '[object String]';
}
isUndefined
Source:
function isUndefined(thing) {
return typeof thing === 'undefined';
}
typeOf
Something → String
Returns the type of the given thing as a String.
This differs from JavaScripts typeof
in the way that it
distinguishes null
, object
, and array
and identifies
NaN
as not-a-number
(Infinity
and -Infinity
are both
reported as number
). Also it knows some types native to
nodash, such as list
, stream
, and tuple
.
The possible return values are:
boolean
for true
and false
,
number
for a number which is not NaN
,
string
for a JavaScript string,
function
for a JavaScript function,
not-a-number
if isNaN
would return true,
null
for null
,
undefined
for undefined
,
array
is Array.isArray
would return true,
list
if it is a List,
stream
if it is a Stream,
tuple
if it is a Tuple,
object
if it is an object but neither null
nor an array
or any of the previously mentioned object types (e.g. tuple
)
In ECMAScript 2015 (ES6) this function may also return symbol
for Symbols.
Source:
function typeOf(thing) {
var type = typeof thing;
switch (type) {
case 'number':
return isNaN(thing) ? 'not-a-number' : 'number';
case 'object':
var exactType = classOf(thing);
if (exactType === 'object' && thing.constructor && thing.constructor.__type) {
return thing.constructor.__type;
}
return exactType;
default:
return type;
}
}
(unclassified)
any
Prelude: any
Source:
function any(p, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
return true;
}
}
return false;
}
append
++
Prelude: ++
Source:
function append(xs, ys) {
switch (typeOf(xs)) {
case 'list':
return appendList(xs, ys);
case 'string':
return xs + ys;
case 'array':
return [].concat.call(xs, ys);
default:
error(TypeError);
}
}
at
!!AT
Prelude: !!
Source:
function at(xs, ix) {
if (xs === undefined) {
return xs;
}
return xs[ix];
}
break
break_
Prelude: break
Source:
function break(p, xs) {
var i = 0;
while (i < xs.length && !p(xs[i])) {
i++;
}
return tuple(xs.slice(0, i), xs.slice(i));
}
clone
Source:
function clone(thing) {
if (typeof thing === 'object') {
if (thing === null) {
return null;
}
return map(clone, thing);
}
return thing;
}
compare
Prelude: compare
Source:
function compare(a, b) {
switch (typeof a) {
case 'string':
return a.localeCompare(b);
case 'object':
if (isFunction(a.compareTo)) {
return a.compareTo(b);
} else if (isArray(a)) {
for (var i = 0; i < Math.min(a.length, b.length); i++) {
var r = compare(a[i], b[i]);
if (r !== 0) {
return r;
}
}
return 0;
}
return a.toString().localeCompare(b.toString());
case 'number':
return signum(a - b);
}
return undefined;
}
comparing
Source:
function comparing(f, a, b) {
return compare(f(a), f(b));
}
concat
Prelude: concat
Source:
function concat(xs) {
if (isString(xs[0])) {
return xs.join('');
}
var zs = [];
var ks = Object.keys(xs);
for (var i = 0; i < ks.length; i++) {
[].push.apply(zs, xs[ks[i]]);
}
return zs;
}
concatMap
Prelude: concatMap
Source:
var concatMap = /* this is a composed function */
cons
:
Prelude: :
Source:
function cons(x, xs) {
switch (typeOf(xs)) {
case 'array':
var zs = [].slice.call(xs);
zs.unshift(x);
return zs;
case 'string':
return x + xs;
case 'list':
return new List(x, xs);
case 'stream':
return new Stream(function () {
return tuple(x, xs);
});
default:
error(TypeError);
}
}
curried
Source:
function curried(fn) {
return funcs[fn.length](fn);
}
delete
delete_
Prelude: delete
Source:
function delete(x, xs) {
var i = xs.indexOf(x);
if (i >= 0) {
return append(xs.slice(0,i), xs.slice(i+1));
}
return xs;
}
deleteBy
Prelude: deleteBy
Source:
function deleteBy(p, x, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(x, xs[i])) {
return append(xs.slice(0,i), xs.slice(i+1));
}
}
return xs;
}
difference
\\
Prelude: \\
Source:
function difference(xs, ys) {
var set = new Set();
var i;
for (i = 0; i < ys.length; i++) {
set.add(ys[i]);
}
var zs = [];
for (i = 0; i < xs.length; i++) {
if (!set.has(xs[i])) {
zs.push(xs[i]);
}
}
return isString(xs) ? arrayToString(zs) : zs;
}
drop
Prelude: drop
Source:
function drop(n, xs) {
return xs.slice(n);
}
dropWhile
Prelude: dropWhile
Source:
function dropWhile(p, xs) {
var i = 0;
while (i < xs.length && p(xs[i])) {
i++;
}
return xs.slice(i);
}
either
Prelude: either
Source:
function either(afun, bfun, value) {
if (is(Left, value)) {
return afun(value.value());
} else if (is(Right, value)) {
return bfun(value.value());
} else {
fail();
}
}
elem
Prelude: elem
Source:
function elem(x, xs) {
for (var i = 0; i < xs.length; i++) {
if (eq(xs[i], x)) {
return true;
}
}
return false;
}
elemIndex
Prelude: elemIndex
Source:
function elemIndex(x, xs) {
return findIndex(eq(x), xs);
}
elemIndices
Prelude: elemIndices
Source:
function elemIndices(x, xs) {
return findIndices(eq(x), xs);
}
emptyList
Source:
function emptyList() {
return emptyList;
}
eq
==EQ
Prelude: ==
Source:
function eq(a, b) {
if (a === b) {
return true;
}
var ta = typeOf(a);
var tb = typeOf(b);
if (ta !== tb) {
return false;
}
switch (ta) {
case 'tuple':
return eq(a.fst(), b.fst()) && eq(a.snd(), b.snd());
case 'list':
return eq(a.head(), b.head()) && eq(a.tail(), b.tail());
case 'array':
case 'object':
if (a.constructor !== b.constructor) {
return false;
}
var k = union(Object.keys(a), Object.keys(b));
for (var i = 0; i < k.length; i++) {
if (!eq(a[k[i]], b[k[i]])) {
return false;
}
}
return true;
}
return false;
}
filter
Prelude: filter
Source:
function filter(p, xs) {
var ys;
switch (typeOf(xs)) {
case 'array':
case 'string':
ys = [];
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
ys.push(xs[i]);
}
}
return isString(xs) ? arrayToString(ys) : ys;
default:
ys = {};
var ks = Object.keys(xs);
for (var j = 0; j < ks.length; j++) {
if (p(xs[ks[j]])) {
ys[ks[j]] = xs[ks[j]];
}
}
return ys;
}
}
find
Prelude: find
Source:
function find(p, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
return xs[i];
}
}
return null;
}
findIndex
Prelude: findIndex
Source:
function findIndex(p, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
return i;
}
}
return null;
}
findIndices
Prelude: findIndices
Source:
function findIndices(p, xs) {
var zs = [];
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
zs.push(i);
}
}
return zs;
}
foldl1
foldl1'
Prelude: foldl1'
Source:
function foldl1(f, xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
var x = xs[0];
for (var i = 1; i < xs.length; i += 1) {
x = f(xs[i], x);
}
return x;
}
}
foldr1
Prelude: foldr1
Source:
function foldr1(f, xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
var x = xs[xs.length - 1];
for (var i = xs.length - 2; i >= 0; i -= 1) {
x = f(xs[i], x);
}
return x;
}
}
fromLeft
Source:
function fromLeft(thing) {
if (is(Left, thing)) {
return thing.value();
}
fail();
}
fromMaybe
Source:
function fromMaybe(def, maybe) {
if (isJust(maybe)) {
return maybe;
}
return def;
}
fromRight
Source:
function fromRight(thing) {
if (is(Right, thing)) {
return thing.value();
}
fail();
}
group
Prelude: group
Source:
var group = /* this is a composed function */
groupBy
Prelude: groupBy
Source:
function groupBy(p, xs) {
if (xs.length === 0) {
return [];
}
var zs = [];
var current = [xs[0]];
var last = xs[0];
for (var i = 1; i < xs.length; i++) {
if (p(xs[i], last)) {
current.push(xs[i]);
} else {
zs.push(current);
current = [xs[i]];
}
last = xs[i];
}
zs.push(current);
return isString(xs) ? map(arrayToString, zs) : zs;
}
gt
>GT
Prelude: >
Source:
function gt(a, b) {
return compare(a, b) > 0;
}
gte
>=GTE
Prelude: >=
Source:
function gte(a, b) {
return compare(a, b) >= 0;
}
head
Prelude: head
Source:
function head(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs[0];
case 'list':
case 'stream':
return xs.head();
default:
error(TypeError);
}
}
indexOf
Source:
function indexOf(word, string) {
'use strict';
var m = 0;
var i = 0;
var table = [];
var pos = 2;
var cnd = 0;
table[0] = -1;
table[1] = 0;
// build the table for KMP. This takes `O(word.length)` steps.
while (pos < word.length) {
if (word[pos - 1] == word[cnd]) {
cnd = cnd + 1;
table[pos] = cnd;
pos = pos + 1;
} else if (cnd > 0) {
cnd = table[cnd];
} else {
table[pos] = 0;
pos = pos + 1;
}
}
// scan the string. This takes `O(string.length)` steps.
while (m + i < string.length) {
if (word[i] == string[m + i]) {
if (i == word.length - 1) {
return m;
}
i = i + 1;
} else {
if (table[i] > -1) {
m = m + i - table[i];
i = table[i];
} else {
i = 0;
m = m + 1;
}
}
}
// Returns -1 if the subsequence was not found in the sequence.
return -1;
}
init
Prelude: init
Source:
function init(xs) {
if (isString(xs)) {
return xs.slice(0, xs.length - 1);
}
return [].slice.call(xs, 0, xs.length - 1);
}
inits
Prelude: inits
Source:
function inits(xs) {
var result, current, i, length;
if (isArray(xs)) {
result = [[]];
current = [];
length = xs.length;
for (i = 0; i < length; i += 1) {
current = current.concat(xs[i]);
result.push(current);
}
return result;
}
// TODO the assumption is it's a string now
result = [''];
current = '';
length = xs.length;
for (i = 0; i < length; i += 1) {
current += xs[i];
result.push(current);
}
return result;
}
insert
Prelude: insert
Source:
var insert = /* this is a composed function */
insertBy
Prelude: insertBy
Source:
function insertBy(f, x, xs) {
for (var i = 0; i < xs.length; i++) {
if (f(x, xs[i]) <= 0) {
return concat([xs.slice(0,i), x, xs.slice(i)]);
}
}
return append(xs, x);
}
intercalate
Prelude: intercalate
Source:
function intercalate(x, xs) {
return concat(intersperse(x, xs));
}
intersect
Prelude: intersect
Source:
function intersect(xs, ys) {
var set = new Set();
var zs = [];
var i;
for (i = 0; i < ys.length; i++) {
set.add(ys[i]);
}
for (i = 0; i < xs.length; i++) {
if (set.has(xs[i])) {
zs.push(xs[i]);
}
}
return zs;
}
intersperse
Prelude: intersperse
Source:
function intersperse(x, xs) {
if (xs.length === 0) {
return [];
}
var z = [xs[0]];
for (var i = 1; i < xs.length; i++) {
z.push(x);
z.push(xs[i]);
}
return z;
}
last
Prelude: last
Source:
function last(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs[xs.length - 1];
case 'list':
if (xs.isEmpty()) {
return undefined;
}
for (var ts = xs.tail(); !ts.isEmpty();) {
xs = xs.tail();
ts = xs.tail();
}
return xs.head();
default:
error(TypeError);
}
}
length
Prelude: length
Source:
function length(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs.length;
case 'list':
var count = 0;
while (!xs.isEmpty()) {
count += 1;
xs = xs.tail();
}
return count;
case 'stream':
return Infinity;
case 'object':
return Object.keys(xs).length;
default:
error(TypeError);
}
}
listToMaybe
Source:
function listToMaybe(xs) {
if (is(List, xs)) {
return xs.isEmpty() ? null : xs.head();
}
throw new TypeError();
}
lookup
Prelude: lookup
Source:
function lookup(x, xs) {
if (isArray(xs)) {
for (var i = 0; i < xs.length; i++) {
if (xs[i] && eq(xs[i][0], x)) {
return xs[i][1];
}
}
}
return xs[x];
}
lt
<LT
Prelude: <
Source:
function lt(a, b) {
return compare(a, b) < 0;
}
lte
<=LTE
Prelude: <=
Source:
function lte(a, b) {
return compare(a, b) <= 0;
}
map
fmap
Prelude: fmap
Source:
function map(f, xs) {
var i, ys;
switch (typeOf(xs)) {
case 'array':
return mapArray(f, xs);
case 'string':
return arrayToString(mapArray(f, xs));
case 'list':
if (xs.isEmpty()) {
return xs;
}
/* falls through */
case 'stream':
return new List(lazy(function () {
return f(xs.head());
}), lazy(function () {
return map(f, xs.tail());
}));
case 'object':
ys = {};
var ks = Object.keys(xs);
for (var j = 0; j < ks.length; j += 1) {
ys[ks[j]] = f(xs[ks[j]], ks[j]);
}
return ys;
}
}
max
Prelude: max
Source:
function max(a, b) {
return compare(a, b) > 0 ? a : b;
}
maximum
Prelude: maximum
Source:
var maximum = /* this is a composed function */
maximumBy
Prelude: maximumBy
Source:
function maximumBy(f, xs) {
return foldl1(function (a, b) {
if (f(a, b) > 0) {
return a;
}
return b;
}, xs);
}
min
Prelude: min
Source:
function min(a, b) {
return compare(a, b) < 0 ? a : b;
}
minimum
Prelude: minimum
Source:
var minimum = /* this is a composed function */
minimumBy
Prelude: minimumBy
Source:
function minimumBy(f, xs) {
return foldl1(function (a, b) {
if (f(a, b) < 0) {
return a;
}
return b;
}, xs);
}
neq
/=!=<>NEQ
Prelude: /=
Source:
function neq(a, b) {
return !eq(a, b);
}
notElem
Prelude: notElem
Source:
function notElem(x, xs) {
for (var i = 0; i < xs.length; i++) {
if (eq(xs[i], x)) {
return false;
}
}
return true;
}
nub
Prelude: nub
Source:
function nub(xs) {
var set = new Set();
var zs = [];
for (var i = 0; i < xs.length; i++) {
if (!set.has(xs[i])) {
zs.push(xs[i]);
set.add(xs[i]);
}
}
return zs;
}
or
Prelude: or
Source:
var or = /* this is a composed function */
partition
Prelude: partition
Source:
function _partition(p, xs) {
var as = [];
var bs = [];
for (var i = 0; i < xs.length; i++) {
(p(xs[i]) ? as : bs).push(xs[i]);
}
if (isString(xs)) {
return tuple(arrayToString(as), arrayToString(bs));
}
return tuple(as, bs);
}
product
Prelude: product
Source:
var product = /* this is a composed function */
replicate
Prelude: replicate
Source:
function replicate(n, x) {
var xs = [];
for (var i = 0; i < n; i++) {
xs.push(x);
}
return xs;
}
reverse
Prelude: reverse
Source:
function reverse(xs) {
var zs = isString(xs) ? ''.split.call(xs, '') : [].slice.call(xs);
zs.reverse();
return isString(xs) ? zs.join('') : zs;
}
scanl
Prelude: scanl
Source:
function scanl(f, x, xs) {
var zs = [x];
for (var i = 0; i < xs.length; i++) {
x = f(x, xs[i]);
zs.push(x);
}
return zs;
}
scanl1
Prelude: scanl1
Source:
function scanl1(f, xs) {
var x = xs[0];
var zs = [x];
for (var i = 1; i < xs.length; i++) {
x = f(x, xs[i]);
zs.push(x);
}
return zs;
}
scanr
Prelude: scanr
Source:
function scanr(f, x, xs) {
var zs = [x];
for (var i = xs.length - 1; i >= 0; i--) {
x = f(xs[i], x);
zs.unshift(x);
}
return zs;
}
scanr1
Prelude: scanr1
Source:
function scanr1(f, xs) {
var x = xs[xs.length - 1];
var zs = [x];
for (var i = xs.length - 2; i >= 0; i--) {
x = f(xs[i], x);
zs.unshift(x);
}
return zs;
}
select
Source:
function select(path, object) {
return foldl(at, object, path.split(/\./));
}
sinh
Prelude: sinh
Source:
function sinh(x) {
return (Math.exp(x) - Math.exp(-x)) / 2;
}
sort
Prelude: sort
Source:
function sort(xs) {
if (xs.length <= 1) {
return xs;
}
var zs = isString(xs) ? ''.split.call(xs, '') : [].slice.call(xs);
if (isNumber(zs[0])) {
zs.sort(function (a, b) { return a - b; });
} else if (isString(zs[0])) {
zs.sort(function (a, b) { return a.localeCompare(b); });
} else {
zs.sort(compare);
}
return isString(xs) ? zs.join('') : zs;
}
sortBy
Prelude: sortBy
Source:
function sortBy(fn, xs) {
if (xs.length <= 1) {
return xs;
}
var yesItsAString = isString(xs);
var zs = yesItsAString ? ''.split.call(xs, '') : [].slice.call(xs);
zs.sort(fn);
return yesItsAString ? zs.join('') : zs;
}
span
Prelude: span
Source:
function span(p, xs) {
var i = 0;
while (i < xs.length && p(xs[i])) {
i++;
}
return tuple(xs.slice(0, i), xs.slice(i));
}
splitAt
Prelude: splitAt
Source:
function splitAt(n, xs) {
return tuple(take(n, xs), drop(n, xs));
}
tail
Prelude: tail
Source:
function tail(xs) {
switch (typeOf(xs)) {
case 'array':
return [].slice.call(xs, 1);
case 'string':
return "".slice.call(xs, 1);
case 'list':
case 'stream':
return xs.tail();
default:
error(TypeError);
}
}
tails
Prelude: tails
Source:
function tails(xs) {
var result, current, i;
if (isArray(xs)) {
result = [[]];
current = [];
for (i = xs.length - 1; i >= 0; i -= 1) {
current = [xs[i]].concat(current);
result.unshift(current);
}
return result;
}
// TODO the assumption is it's a string now
result = [''];
current = '';
for (i = xs.length - 1; i >= 0; i -= 1) {
current = xs[i] + current;
result.unshift(current);
}
return result;
}
take
Prelude: take
Source:
function take(n, xs) {
switch (typeOf(xs)) {
case 'string':
return "".slice.call(xs, 0, n);
case 'array':
return [].slice.call(xs, 0, n);
case 'list':
case 'stream':
return takeGenerator(n, xs);
default:
error(TypeError);
}
}
takeWhile
Prelude: takeWhile
Source:
function takeWhile(p, xs) {
var i = 0;
while (i < xs.length && p(xs[i])) {
i++;
}
return xs.slice(0, i);
}
transpose
Prelude: transpose
Source:
function transpose(xss) {
if (!isArray(xss)) {
var zss = {};
var ks = Object.keys(xss);
for (var k = 0; k < ks.length; k++) {
zss[xss[ks[k]]] = ks[k];
}
return zss;
}
var j = 0;
var zs = [];
var current;
do {
current = [];
for (var i = 0; i < xss.length; i++) {
if (xss[i][j] !== undefined) {
current.push(xss[i][j]);
}
}
j += 1;
} while (current.length > 0 && zs.push(current));
if (isString(xss[0])) {
zs = map(arrayToString, zs);
}
return zs;
}
union
Prelude: union
Source:
function union(xs, ys) {
var set = new Set();
var zs = [];
var i;
for (i = 0; i < xs.length; i++) {
zs.push(xs[i]);
set.add(xs[i]);
}
for (i = 0; i < ys.length; i++) {
if (!set.has(ys[i])) {
zs.push(ys[i]);
}
}
return zs;
}
Appendix
Coverage of Haskell Prelude
Prelude functions supported in Nodash
- !!
- $
- &&
- *
- **
- +
- ++
- ,
- -
- .
- /
- /=
- :
- <
- <=
- ==
- >
- >=
- ^
- ^^
- abs
- acos
- acosh
- all
- and
- any
- asin
- asinh
- atan
- atanh
- break
- ceiling
- compare
- concat
- concatMap
- const
- cos
- cosh
- curry
- cycle
- div
- divMod
- drop
- either
- elem
- even
- exp
- filter
- flip
- floor
- fmap
- foldl
- foldl1
- foldr
- foldr1
- fst
- gcd
- head
- id
- init
- iterate
- last
- lcm
- length
- lines
- log
- logBase
- lookup
- map
- max
- maximum
- maybe
- min
- minimum
- mod
- negate
- not
- notElem
- odd
- or
- product
- properFraction
- quot
- quotRem
- recip
- rem
- repeat
- replicate
- reverse
- round
- scanl
- scanl1
- scanr
- scanr1
- signum
- sin
- sinh
- snd
- span
- splitAt
- sqrt
- subtract
- sum
- tail
- take
- takeWhile
- tan
- tanh
- truncate
- uncurry
- unlines
- until
- unwords
- words
- zip
- zip3
- zipWith
- zipWith3
- ||
Prelude functions missing from Nodash
- $!
- =<<
- >>
- >>=
- FilePath
- IOError
- appendFile
- asTypeOf
- atan2
- catch
- decodeFloat
- dropWhie
- encodeFloat
- enumFrom
- enumFromThen
- enumFromThenTo
- enumFromTo
- error
- exponent
- fail
- floatDigits
- floatRadix
- floatRange
- fromEnum
- fromInteger
- fromIntegral
- fromRational
- getChar
- getContents
- getLine
- interact
- ioError
- isDenormalized
- isIEEE
- isInfinite
- isNaN
- isNegativeZero
- lex
- mapM
- mapM_
- maxBound
- minBound
- null
- otherwise
- pi
- pitStr
- pred
- print
- putChar
- putStrLn
- read
- readFile
- readIO
- readList
- readLn
- readParen
- reads
- readsPrec
- realToFrac
- return
- scaleFloat
- seq
- sequence
- sequence_
- show
- showChar
- showList
- showParen
- showString
- shows
- showsPrec
- significand
- succ
- toEnum
- toInteger
- toRational
- undefined
- unzip
- unzip3
- userError
- writeFile
Nodash-specific additions
- Either
- Left
- List
- Right
- Stream
- Thunk
- Tuple
- arrayToString
- async
- bool
- catMaybes
- chr
- classOf
- clone
- comparing
- compose2
- curried
- each
- emptyList
- fromLeft
- fromMaybe
- fromRight
- idf
- indexOf
- install
- invoke
- is
- isArguments
- isArray
- isAsciiLetter
- isBoolean
- isDate
- isEmpty
- isFunction
- isInteger
- isJust
- isLeft
- isLetter
- isLower
- isNothing
- isNull
- isNumber
- isNumeric
- isObject
- isRegExp
- isRight
- isString
- isUndefined
- isUpper
- keys
- lazy
- lefts
- listToArray
- listToMaybe
- listToString
- mapMaybe
- match
- maybeToList
- objectToArray
- on
- ord
- partitionEithers
- pipe
- range
- rangeStep
- register
- resolveThunk
- rights
- run
- select
- singleton
- tuple3
- tuple4
- tuplesToObject
- typeOf
- values
Either
Source:
function Either() {
fail();
}
isLeft
Either a b → Boolean
Source:
var isLeft = /* this is a composed function */
isRight
Either a b → Boolean
Source:
var isRight = /* this is a composed function */
Left
Source:
function Left(value) {
if (!(this instanceof Left)) {
return new Left(value);
}
this.value = idf(value);
}
lefts
Source:
var lefts = /* this is a composed function */
partitionEithers
Source:
function partitionEithers(xs) {
return tuple(lefts(xs), rights(xs));
}
Right
Source:
function Right(value) {
if (!(this instanceof Right)) {
return new Right(value);
}
this.value = idf(value);
}
rights
Source:
var rights = /* this is a composed function */
apply $ Prelude: $
Haskell Definition:
apply func arg = func arg
Source:
function apply(f, x) {
return f(x);
}
compose . Prelude: .
(b → c) → (a → b) → a → c
Function composition.
Example:
var f = compose(plus(10), times(2));
f(3) === 16
Haskell Definition:
compose g f = \x -> g (f x)
Source:
function compose(f, g, x) {
return f(g(x));
}
compose2
Source:
function compose2(f, g, x, y) {
return f(g(x, y));
}
const const_constant Prelude: const
Haskell Definition:
const = \a _ -> a
Source:
function const(a, b) {
return a;
}
curry Prelude: curry
Source:
function curry(f) {
return curried(function (a, b) {
return f(tuple(a, b));
});
}
flip Prelude: flip
(a → b → c) → (b → a → c)
flip(f)
takes its (first) two arguments in the reverse order of f
.
Example:
minus(10, 8) === 2
var subtract = flip(minus)
subtract(10, 8) === -2
Haskell Definition:
flip f = \a b -> f b a
Source:
function flip(f) {
return curried(function (b, a) {
return f(a, b);
});
}
id Prelude: id
a → a
Identity function.
Example:
id(7) === 7
Haskell Definition:
id = \x -> x
Source:
function id(x) { return x; }
idf
Source:
function idf(x) {
return function () {
return x;
};
}
invoke
Source:
function invoke(f) {
return f();
}
on
(b → b → c) → (a → b) → a → a → c
Example:
var xs = [
{ firstName: 'Jonathan', secondName: 'Müller' },
{ firstName: 'Benjamin', secondName: 'Bamboo' }
];
var sortByFirstName = sortBy(on(compare, select('firstName')), xs);
Haskell Definition:
(.*.) `on` f = \x y -> f x .*. f y
Source:
function on(g, f, a, b) {
return g(f(a), f(b));
}
uncurry Prelude: uncurry
Source:
function uncurry(f) {
return function (t) {
return f(fst(t), snd(t));
};
}
List
arrayToString
Source:
function arrayToString(array) {
return array.join('');
}
lazy
arrayToList
Source:
function lazy(val) {
if (isFunction(val)) {
return new Thunk(val);
}
function generator(i) {
if (i < val.length) {
return new List(val[i], new Thunk(function () {
return generator(i + 1);
}));
}
return emptyList();
}
return generator(0);
}
List
new List(head, tail) :: a → [a] → [a]
Lists are immutable singly-linked sequences.
Methods:
- .head() → a
- Extract the first element in the list.
- .tail() → List a
- Extract the rest of the list.
Lists are typically not constructed by user code with this
constructor, but with builers such as arrayToList.
The purpose of the List type is to implement lazy evaluation.
Internally the head and the tail of a list may actually be Thunks
which are evaluated only if you call .head()
or .tail()
respectively.
To construct lazy lists, use lazy.
Example:
var xs = new List(38, new List(42, emptyList()))
console.log(xs.head()) // 38
console.log(xs.tail().head()) // 42
head
and tail
are functional forms of .head()
and .tail()
.
var xs = lazy([1, 2, 3, 4, 5]);
console.log(head(xs)); // 1
console.log(head(tail(xs))); // 2
Haskell Definition:
data List a = EmptyList | Cons { head :: a, tail :: (List a) }
Source:
function List(head, tail) {
var self = this;
this.head = function () {
if (is(Thunk, head)) {
var value = head.get();
self.head = head.get;
return value;
}
return head;
};
this.tail = function () {
if (is(Thunk, tail)) {
var value = tail.get();
self.tail = tail.get;
return value;
}
return tail;
};
}
listToArray
Source:
function listToArray(xs) {
var array = [];
each(function (x) {
array.push(x);
}, xs);
return array;
}
listToString
Source:
var listToString = /* this is a composed function */
range
..
Source:
function range(from, to) {
return rangeStep(1, from, to);
}
rangeStep
Source:
function rangeStep(step, from, to) {
step = from < to ? step : -step;
to = step > 0 ? Math.floor(to) : Math.ceil(to);
var current = from;
function gen() {
current += step;
return new List(current, current === to ? emptyList : new Thunk(gen));
}
return new List(from, new Thunk(gen));
}
singleton
Source:
function singleton(thing) {
return new List(thing, emptyList);
}
Maybe
catMaybes
Source:
var catMaybes = /* this is a composed function */
isJust
Source:
function isJust(thing) {
return thing !== null && thing !== undefined;
}
isNothing
Source:
function isNothing(thing) {
return !isJust(thing);
}
mapMaybe
Source:
var mapMaybe = /* this is a composed function */
maybe
Prelude: maybe
Source:
function maybe(def, fun, value) {
if (value === null || value === undefined) {
return def;
}
return fun(value);
}
maybeToList
Source:
function maybeToList(thing) {
if (isJust(thing)) {
return singleton(thing);
}
return emptyList();
}
Math
abs
Prelude: abs
Number → Number
Returns the absolute (positive, non-negative) value of a number.
Example:
abs(9) === 9
abs(-3) === 3
Haskell Definition:
abs x | x >= 0 = x
| x < 0 = -x
Source:
function abs() { [native code] }
acos
Prelude: acos
Number → Number
Source:
function acos() { [native code] }
acosh
Prelude: acosh
Number → Number
Source:
function acosh(x) {
return Math.log(x + Math.sqrt(x * x - 1));
}
add
+ADDplusPLUS
Prelude: +
Number → Number → Number
Source:
function add(a, b) {
return a + b;
}
asin
Prelude: asin
Number → Number
Source:
function asin() { [native code] }
asinh
Prelude: asinh
Number → Number
Source:
function asinh(x) {
if (x === -Infinity) {
return x;
} else {
return Math.log(x + Math.sqrt(x * x + 1));
}
}
atan
Prelude: atan
Number → Number
Source:
function atan() { [native code] }
atanh
Prelude: atanh
Number → Number
Source:
function atanh(x) {
return Math.log((1 + x) / (1 - x)) / 2;
}
ceiling
Prelude: ceiling
Number → Number
ceiling x
returns the least integer not less than x
.
Source:
function ceil() { [native code] }
cos
Prelude: cos
Number → Number
Source:
function cos() { [native code] }
cosh
Prelude: cosh
Number → Number
Source:
function cosh(x) {
return (Math.exp(x) + Math.exp(-x)) / 2;
}
div
Prelude: div
Number → Number
Source:
function div(a, b) {
return Math.floor(a / b);
}
divMod
Prelude: divMod
Number → Number → (Number, Number)
Source:
function divMod(a, b) {
return tuple(div(a, b), mod(a, b));
}
even
Prelude: even
Number → Bool
Source:
function even(x) {
return (x % 2) === 0;
}
exp
Prelude: exp
Number → Number
Source:
function exp() { [native code] }
floor
Prelude: floor
Number → Number
floor x
returns the greatest integer not greater than x
.
Source:
function floor() { [native code] }
frac
/
Prelude: /
Number → Number → Number
Source:
function frac(a, b) {
return a / b;
}
gcd
Prelude: gcd
Number → Number → Number
Source:
function gcd(a, b) {
var c;
while (b !== 0) {
c = rem(a, b);
a = b;
b = c;
}
return a;
}
lcm
Prelude: lcm
Number → Number → Number
Source:
function lcm(a, b) {
if (a === 0 || b === 0) {
return 0;
}
return Math.abs(quot(a, gcd(a, b)) * b);
}
log
Prelude: log
Number → Number
Source:
function log() { [native code] }
logBase
Prelude: logBase
Number → Number → Number
Haskell Definition:
logBase x y = log y / log x
Source:
function logBase(a, b) {
return Math.log(a) / Math.log(b);
}
minus
-MINUS
Prelude: -
Number → Number → Number
Source:
function minus(a, b) {
return a - b;
}
mod
Prelude: mod
Number → Number → Number
Source:
function mod(a, b) {
var q = quot(a, b);
var r = rem(a, b);
return signum(r) === -signum(b) ? r + b : r;
}
mul
*MULtimesTIMES
Prelude: *
Number → Number → Number
Source:
function mul(a, b) {
return a * b;
}
negate
Prelude: negate
Number → Number
Source:
function negate(x) {
return -x;
}
odd
Prelude: odd
Number → Boolean
Source:
function odd(x) {
return (x % 2) !== 0;
}
pow
**^^^
Prelude: ^^
Haskell Definition:
x ** y = exp (log x * y)
Source:
function pow() { [native code] }
properFraction
Prelude: properFraction
Number → (Number, Number)
properFraction
takes a real fractional
number x
and returns a pair (n, f)
such that x = n + f
,
and: n
is an integral number with the same sign as x
;
and f
is a fraction with the same type and sign as x
,
and with absolute value less than 1.
Source:
function properFraction(x) {
var num = truncate(x);
return tuple(num, -(num - x));
}
quot
Prelude: quot
Number → Number → Number
Source:
function quot(a, b) {
var r = a / b;
return r >= 0 ? Math.floor(r) : Math.ceil(r);
}
quotRem
Prelude: quotRem
Number → Number → (Number, Number)
Source:
function quotRem(a, b) {
return tuple(quot(a, b), rem(a, b));
}
recip
Prelude: recip
Haskell Definition:
recip = 1 / x
Source:
function recip(x) {
return 1 / x;
}
rem
Prelude: rem
Number → Number → Number
Source:
function rem(a, b) {
return a % b;
}
round
Prelude: round
Number → Number
round x
returns the nearest integer to x
; the even
integer if x
is equidistant between two integers.
Source:
function round(x) {
var fraction = properFraction(x);
var n = fraction[0];
var m = fraction[1] < 0 ? n - 1 : n + 1;
switch (signum(Math.abs(fraction[1]) - 0.5)) {
case -1:
return n;
case 0:
return n % 2 === 0 ? n : m;
case 1:
return m;
}
}
signum
Prelude: signum
Number → Number
Haskell Definition:
signum x | x > 0 = 1
| x == 0 = 0
| x < 0 = -1
Source:
function signum(x) {
if (x > 0) {
return 1;
} else if (x === 0) {
return 0;
}
return -1;
}
sin
Prelude: sin
Number → Number
Source:
function sin() { [native code] }
sqrt
Prelude: sqrt
Number → Number
Source:
function sqrt() { [native code] }
sub
subtract
Prelude: subtract
Number → Number
Source:
function sub(a, b) {
return b - a;
}
tan
Prelude: tan
Number → Number
Haskell Definition:
tan x = sin x / cos x
Source:
function tan() { [native code] }
tanh
Prelude: tanh
Number → Number
Haskell Definition:
tanh x = sinh x / cosh x
Source:
function tanh(x) {
if (x === Infinity) {
return 1;
} else if (x === -Infinity) {
return -1;
} else {
return (Math.exp(x) - Math.exp(-x)) / (Math.exp(x) + Math.exp(-x));
}
}
truncate
Prelude: truncate
Number → Number
truncate x
returns the integer nearest x
between zero and x
.
Source:
function truncate(x) {
switch (signum(x)) {
case -1:
return Math.ceil(x);
case 1:
return Math.floor(x);
}
return 0;
}
Nodash
install
Source:
function install(mountpoint) {
var options = arguments[1];
var nodashObject = Nodash;
var prefix = '';
var postfix = '';
if (!mountpoint) {
return Nodash;
}
if (options) {
nodashObject = makeNodash(options);
}
if (isArray(mountpoint)) {
if (isString(mountpoint[0])) {
prefix = [].shift.call(mountpoint);
}
if (isString(mountpoint[1])) {
postfix = mountpoint[1];
}
mountpoint = mountpoint[0] || {};
}
each(function (func, name) {
if (name[0] === '_') {
return;
}
var key = prefix + name + postfix;
if (!(key in mountpoint)) {
mountpoint[key] = func;
}
}, nodashObject);
return mountpoint;
}
register
Source:
function register() {
var args = [].slice.call(arguments);
if (arguments.length === 1) {
switch (typeof args[0]) {
case 'object':
if (Array.isArray(args[0])) {
registerInjected(args[0].slice());
} else {
registerLib(args[0]);
}
break;
case 'function':
register(args[0].call(Nodash));
break;
}
return;
}
var func = args.pop();
var aliases = [];
args.forEach(function (arg) {
[].push.apply(aliases, arg.split(/ +/));
});
var name = null;
for (var i = 0; i < aliases.length; i += 1) {
if (/^[a-z0-9]+$/i.test(aliases[i])) {
name = aliases[i];
break;
}
}
__metadata[name] = {
aliases: aliases,
definition: func
};
if (!/^[A-Z]/.test(name)) {
func = curried(func);
}
aliases.forEach(function (alias) {
Nodash[alias] = func;
});
}
Pattern
match
MatchSpec → Any → MatchResult
match(spec, value)
matches value
against the spec
, returning
what was captured in the spec.
A MatchSpec
is an array of arrays. Every array in the spec
must have two elements: [ 0: Pattern, 1: Result ]
. The first
Pattern
that matches value
will yield the associated Result
.
If Result
is a function it will be invoked with an object of
all captured variables in the Pattern
and the result will be returned,
otherwise the Result
itself.
Example:
var matchJohn = match([
[ { firstName: 'John' }, 'John is a fine name' ],
[ { firstName: '$firstName' },
function (result) {
return result.$firstName + ' is also a fine name'; } ]
]);
console.log(matchJohn({ firstName: 'John', lastName: 'Doe' }));
// → 'John is a fine name'
console.log(matchJohn({ firstName: 'Johnathan', lastName: 'X' }));
// → 'Jonathan is also a fine name'
Source:
function match(pattern, arg) {
for (var i = 0; i < pattern.length; i += 1) {
var result = {};
var p = pattern[i];
if (matchR(p[0], arg, result)) {
if (typeof p[1] === 'function') {
return p[1](result);
}
return p[1];
}
}
}
Object
each
Source:
function each(f, xs) {
if (is(List, xs)) {
while (!xs.isEmpty()) {
f(xs.head());
xs = xs.tail();
}
} else if (isArray(xs) || isString(xs)) {
for (var i = 0; i < xs.length; i++) {
f(xs[i], i);
}
} else if (isObject(xs)) {
var ks = Object.keys(xs);
for (var j = 0; j < ks.length; j += 1) {
f(xs[ks[j]], ks[j]);
}
}
}
keys
Source:
function keys() { [native code] }
values
Source:
function values(object) {
var values = [];
each(function (value) {
values.push(value);
}, object);
return values;
}
Stream
cycle
Prelude: cycle
Source:
function cycle(xs) {
if (isArray(xs)) {
xs = lazy(xs);
}
function generator(ys) {
if (ys.isEmpty()) {
ys = xs;
}
return function () {
return tuple(ys.head(), generator(ys.tail()));
};
}
return new Stream(generator(xs));
}
iterate
Prelude: iterate
Source:
function iterate(f, seed) {
function generator(seed) {
return function () {
var newSeed = f(seed);
return tuple(seed, generator(newSeed));
};
}
return new Stream(generator(seed));
}
repeat
Prelude: repeat
Source:
function repeat(x) {
function generator() {
return tuple(x, generator);
}
return new Stream(generator);
}
Stream
stream
new Stream(generator)
Streams are immutable, lazily evaluated, infinite Lists.
Methods:
- .head() → a
- Extract the first element of this stream.
- .tail() → List a
- Extract the rest of the stream.
Source:
function Stream(generator) {
if (!(this instanceof Stream)) {
return new Stream(generator);
}
var thunk = new Thunk(generator);
var self = this;
this.head = function () {
var value = thunk.get().fst();
self.head = idf(value);
return value;
};
this.tail = function () {
var value = thunk.get().snd();
switch (typeOf(value)) {
case 'list':
case 'stream':
break;
case 'function':
value = new Stream(value);
break;
default:
error(TypeError);
}
self.tail = idf(value);
return value;
};
}
until
Prelude: until
Source:
function until(p, f, v) {
while (!p(v)) {
v = f(v);
}
return v;
}
String
lines
Prelude: lines
Source:
function lines(string) {
var result = string.split(/\n/);
if (result[result.length - 1].length === 0) {
delete result[result.length - 1];
}
return result;
}
unlines
Prelude: unlines
Source:
function unlines(lines) {
return lines.join('\n');
}
unwords
Prelude: unwords
Source:
function unwords(words) {
return words.join(' ');
}
words
Prelude: words
Source:
function words(string) {
return string.split(/[\n\r\v\t ]/);
}
Tuple
fst
Prelude: fst
(a, b) → b
Extract the first component of a pair.
Tuples also have a fst()
method which does the same thing,
but this function is exposing that method as a function.
Haskell Definition:
fst (a, _) = a
Source:
function fst(t) {
return t.fst();
}
objectToArray
Object → [(String, Any)]
Turns an object into an associative list of tuples.
The objects keys are the first components of the tuples,
the values the second components.
eq( objectToArray({ a: 17, b: 20 }), [ tuple('a', 17), tuple('b', 20) ]) === true
Source:
function objectToArray(obj) {
var arr = [];
each(function (val, key) {
arr.push(new Tuple(key, val));
}, obj);
return arr;
}
snd
Prelude: snd
(a, b) → b
Extract the second component of a pair.
Tuples also have a fst()
method which does the same thing,
but this function is exposing that method as a function.
Haskell Definition:
snd (_, b) = b
Source:
function snd(t) {
return t.snd();
}
Tuple
new Tuple(first, second) :: a → b → (a, b)
Tuples are immutable pairs of a first and a second components.
Methods:
- .fst() → a
- Retrieves the first component of this tuple.
- .snd() → b
- Retrieves the second component of this tuple.
Example:
var t = new Tuple(4711, 8080);
console.log(t.fst()); // 4711
console.log(t.snd()); // 8080
fst
and snd
are functional forms of .fst()
and .snd()
.
tuple
is a convenience method for omitting new
:
var t = tuple(4711, 8080);
console.log(fst(t)); // 4711
console.log(snd(t)); // 8080
var extractFirsts = map(fst);
console.log(extractFirsts([
tuple(4711, 8080),
tuple(3000, 4444)
])); // [ 4711, 3000 ]
Haskell Definition:
data Tuple a b = Tuple { fst :: a, snd :: b }
Source:
function Tuple(fst, snd) {
if (!(this instanceof Tuple)) {
return new Tuple(fst, snd);
}
this.fst = idf(fst);
this.snd = idf(snd);
freeze(this);
}
tuple
,
Prelude: ,
Source:
function tuple(first, second) {
return new Tuple(first, second);
}
tuple3
,,
Source:
function tuple3(first, second, third) {
return tuple(first, tuple(second, third));
}
tuple4
,,,
Source:
function tuple4(first, second, third, fourth) {
return tuple3(first, second, tuple(third, fourth));
}
tuplesToObject
[(String, Any)] → Object
Turns an associative list of tuples into an object.
The first components of the tuples are the keys,
the second components the corresponding values.
Example:
eq( tuplesToObject([ tuple('a', 2), tuple('b', 3) ]), { a: 2, b: 3 }) === true
Source:
function tuplesToObject(xs) {
var obj = {};
each(function (t) {
obj[t.fst()] = t.snd();
}, xs);
return obj;
}
Type
classOf
Any → String
Determines the property of the internal
[[Class]]
attribute,
normalized to lower case.
Example:
classOf(new Date()) === 'date'
classOf(null) === 'null'
classOf([]) === 'array'
function f() {
return classOf(arguments)
}
f() === 'arguments'
Source:
function classOf(thing) {
var exactType = toString.call(thing);
return exactType.slice(8, exactType.length - 1).toLowerCase();
}
is
Source:
function is(type, thing) {
return thing instanceof type;
}
isArguments
Any → Boolean
Source:
function isArguments(thing) {
return toString.call(thing) === '[object Arguments]';
}
isArray
Any → Boolean
Determines whether something is an array or not.
This is exactly the same as Array.isArray
.
Example:
isArray([]) === true
isArray({}) === false
isArray(new Array(3)) === true
isArray(undefined) === false
isArray(3) === false
Source:
function isArray() { [native code] }
isBoolean
Any → Boolean
Returns true
if the argument is a boolean value, otherwise false
.
Example:
isBoolean(true) === true
isBoolean(false) === false
isBoolean({}) === false
isBoolean(undefined) === false
isBoolean(0) === false
isBoolean(1) === false
isBoolean("true") === false
Source:
function isBoolean(thing) {
return typeof thing === 'boolean';
}
isDate
Any → Boolean
Source:
function isDate(thing) {
return toString.call(thing) === '[object Date]';
}
isEmpty
null_
Prelude: null
Any → Boolean
Source:
function isEmpty(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs.length === 0;
case 'list':
case 'stream':
return xs.isEmpty();
default:
for (var _ in xs) {
return false;
}
return true;
}
}
isFunction
Any → Boolean
Source:
function isFunction(thing) {
return typeof thing === 'function';
}
isInteger
Any → Boolean
Returns true
is the argument is an integral number.
Numbers in JavaScript are floating point values and there is no proper integer type.
This function can be used to check whether a given number could be cast to an
integer without truncating.
isInteger(7) === true
isInteger(7.0) === true
isInteger(7.3) === false
Source:
function isInteger(thing) {
return isNumber(thing) && !isNaN(thing) &&
thing - Math.floor(thing) === 0 &&
thing !== Infinity && thing !== -Infinity;
}
isNull
Any → Boolean
Source:
function isNull(thing) {
return toString.call(thing) === '[object Null]';
}
isNumber
Source:
function isNumber(thing) {
return typeof thing === 'number';
}
isObject
Source:
function isObject(thing) {
return typeof thing === 'object' &&
thing !== null && !Array.isArray(thing);
}
isRegExp
Any → Boolean
Returns true
is the argument is a regular expression object.
Example:
isRegExp(/a+/) === true
isRegExp("a+") === false
isRegExp(new RegExp("a+")) === true
Source:
function isRegExp(thing) {
return toString.call(thing) === '[object RegExp]';
}
isString
Source:
function isString(thing) {
return typeof thing === 'string' || toString.call(thing) === '[object String]';
}
isUndefined
Source:
function isUndefined(thing) {
return typeof thing === 'undefined';
}
typeOf
Something → String
Returns the type of the given thing as a String.
This differs from JavaScripts typeof
in the way that it
distinguishes null
, object
, and array
and identifies
NaN
as not-a-number
(Infinity
and -Infinity
are both
reported as number
). Also it knows some types native to
nodash, such as list
, stream
, and tuple
.
The possible return values are:
boolean
for true
and false
,
number
for a number which is not NaN
,
string
for a JavaScript string,
function
for a JavaScript function,
not-a-number
if isNaN
would return true,
null
for null
,
undefined
for undefined
,
array
is Array.isArray
would return true,
list
if it is a List,
stream
if it is a Stream,
tuple
if it is a Tuple,
object
if it is an object but neither null
nor an array
or any of the previously mentioned object types (e.g. tuple
)
In ECMAScript 2015 (ES6) this function may also return symbol
for Symbols.
Source:
function typeOf(thing) {
var type = typeof thing;
switch (type) {
case 'number':
return isNaN(thing) ? 'not-a-number' : 'number';
case 'object':
var exactType = classOf(thing);
if (exactType === 'object' && thing.constructor && thing.constructor.__type) {
return thing.constructor.__type;
}
return exactType;
default:
return type;
}
}
(unclassified)
any
Prelude: any
Source:
function any(p, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
return true;
}
}
return false;
}
append
++
Prelude: ++
Source:
function append(xs, ys) {
switch (typeOf(xs)) {
case 'list':
return appendList(xs, ys);
case 'string':
return xs + ys;
case 'array':
return [].concat.call(xs, ys);
default:
error(TypeError);
}
}
at
!!AT
Prelude: !!
Source:
function at(xs, ix) {
if (xs === undefined) {
return xs;
}
return xs[ix];
}
break
break_
Prelude: break
Source:
function break(p, xs) {
var i = 0;
while (i < xs.length && !p(xs[i])) {
i++;
}
return tuple(xs.slice(0, i), xs.slice(i));
}
clone
Source:
function clone(thing) {
if (typeof thing === 'object') {
if (thing === null) {
return null;
}
return map(clone, thing);
}
return thing;
}
compare
Prelude: compare
Source:
function compare(a, b) {
switch (typeof a) {
case 'string':
return a.localeCompare(b);
case 'object':
if (isFunction(a.compareTo)) {
return a.compareTo(b);
} else if (isArray(a)) {
for (var i = 0; i < Math.min(a.length, b.length); i++) {
var r = compare(a[i], b[i]);
if (r !== 0) {
return r;
}
}
return 0;
}
return a.toString().localeCompare(b.toString());
case 'number':
return signum(a - b);
}
return undefined;
}
comparing
Source:
function comparing(f, a, b) {
return compare(f(a), f(b));
}
concat
Prelude: concat
Source:
function concat(xs) {
if (isString(xs[0])) {
return xs.join('');
}
var zs = [];
var ks = Object.keys(xs);
for (var i = 0; i < ks.length; i++) {
[].push.apply(zs, xs[ks[i]]);
}
return zs;
}
concatMap
Prelude: concatMap
Source:
var concatMap = /* this is a composed function */
cons
:
Prelude: :
Source:
function cons(x, xs) {
switch (typeOf(xs)) {
case 'array':
var zs = [].slice.call(xs);
zs.unshift(x);
return zs;
case 'string':
return x + xs;
case 'list':
return new List(x, xs);
case 'stream':
return new Stream(function () {
return tuple(x, xs);
});
default:
error(TypeError);
}
}
curried
Source:
function curried(fn) {
return funcs[fn.length](fn);
}
delete
delete_
Prelude: delete
Source:
function delete(x, xs) {
var i = xs.indexOf(x);
if (i >= 0) {
return append(xs.slice(0,i), xs.slice(i+1));
}
return xs;
}
deleteBy
Prelude: deleteBy
Source:
function deleteBy(p, x, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(x, xs[i])) {
return append(xs.slice(0,i), xs.slice(i+1));
}
}
return xs;
}
difference
\\
Prelude: \\
Source:
function difference(xs, ys) {
var set = new Set();
var i;
for (i = 0; i < ys.length; i++) {
set.add(ys[i]);
}
var zs = [];
for (i = 0; i < xs.length; i++) {
if (!set.has(xs[i])) {
zs.push(xs[i]);
}
}
return isString(xs) ? arrayToString(zs) : zs;
}
drop
Prelude: drop
Source:
function drop(n, xs) {
return xs.slice(n);
}
dropWhile
Prelude: dropWhile
Source:
function dropWhile(p, xs) {
var i = 0;
while (i < xs.length && p(xs[i])) {
i++;
}
return xs.slice(i);
}
either
Prelude: either
Source:
function either(afun, bfun, value) {
if (is(Left, value)) {
return afun(value.value());
} else if (is(Right, value)) {
return bfun(value.value());
} else {
fail();
}
}
elem
Prelude: elem
Source:
function elem(x, xs) {
for (var i = 0; i < xs.length; i++) {
if (eq(xs[i], x)) {
return true;
}
}
return false;
}
elemIndex
Prelude: elemIndex
Source:
function elemIndex(x, xs) {
return findIndex(eq(x), xs);
}
elemIndices
Prelude: elemIndices
Source:
function elemIndices(x, xs) {
return findIndices(eq(x), xs);
}
emptyList
Source:
function emptyList() {
return emptyList;
}
eq
==EQ
Prelude: ==
Source:
function eq(a, b) {
if (a === b) {
return true;
}
var ta = typeOf(a);
var tb = typeOf(b);
if (ta !== tb) {
return false;
}
switch (ta) {
case 'tuple':
return eq(a.fst(), b.fst()) && eq(a.snd(), b.snd());
case 'list':
return eq(a.head(), b.head()) && eq(a.tail(), b.tail());
case 'array':
case 'object':
if (a.constructor !== b.constructor) {
return false;
}
var k = union(Object.keys(a), Object.keys(b));
for (var i = 0; i < k.length; i++) {
if (!eq(a[k[i]], b[k[i]])) {
return false;
}
}
return true;
}
return false;
}
filter
Prelude: filter
Source:
function filter(p, xs) {
var ys;
switch (typeOf(xs)) {
case 'array':
case 'string':
ys = [];
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
ys.push(xs[i]);
}
}
return isString(xs) ? arrayToString(ys) : ys;
default:
ys = {};
var ks = Object.keys(xs);
for (var j = 0; j < ks.length; j++) {
if (p(xs[ks[j]])) {
ys[ks[j]] = xs[ks[j]];
}
}
return ys;
}
}
find
Prelude: find
Source:
function find(p, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
return xs[i];
}
}
return null;
}
findIndex
Prelude: findIndex
Source:
function findIndex(p, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
return i;
}
}
return null;
}
findIndices
Prelude: findIndices
Source:
function findIndices(p, xs) {
var zs = [];
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
zs.push(i);
}
}
return zs;
}
foldl1
foldl1'
Prelude: foldl1'
Source:
function foldl1(f, xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
var x = xs[0];
for (var i = 1; i < xs.length; i += 1) {
x = f(xs[i], x);
}
return x;
}
}
foldr1
Prelude: foldr1
Source:
function foldr1(f, xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
var x = xs[xs.length - 1];
for (var i = xs.length - 2; i >= 0; i -= 1) {
x = f(xs[i], x);
}
return x;
}
}
fromLeft
Source:
function fromLeft(thing) {
if (is(Left, thing)) {
return thing.value();
}
fail();
}
fromMaybe
Source:
function fromMaybe(def, maybe) {
if (isJust(maybe)) {
return maybe;
}
return def;
}
fromRight
Source:
function fromRight(thing) {
if (is(Right, thing)) {
return thing.value();
}
fail();
}
group
Prelude: group
Source:
var group = /* this is a composed function */
groupBy
Prelude: groupBy
Source:
function groupBy(p, xs) {
if (xs.length === 0) {
return [];
}
var zs = [];
var current = [xs[0]];
var last = xs[0];
for (var i = 1; i < xs.length; i++) {
if (p(xs[i], last)) {
current.push(xs[i]);
} else {
zs.push(current);
current = [xs[i]];
}
last = xs[i];
}
zs.push(current);
return isString(xs) ? map(arrayToString, zs) : zs;
}
gt
>GT
Prelude: >
Source:
function gt(a, b) {
return compare(a, b) > 0;
}
gte
>=GTE
Prelude: >=
Source:
function gte(a, b) {
return compare(a, b) >= 0;
}
head
Prelude: head
Source:
function head(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs[0];
case 'list':
case 'stream':
return xs.head();
default:
error(TypeError);
}
}
indexOf
Source:
function indexOf(word, string) {
'use strict';
var m = 0;
var i = 0;
var table = [];
var pos = 2;
var cnd = 0;
table[0] = -1;
table[1] = 0;
// build the table for KMP. This takes `O(word.length)` steps.
while (pos < word.length) {
if (word[pos - 1] == word[cnd]) {
cnd = cnd + 1;
table[pos] = cnd;
pos = pos + 1;
} else if (cnd > 0) {
cnd = table[cnd];
} else {
table[pos] = 0;
pos = pos + 1;
}
}
// scan the string. This takes `O(string.length)` steps.
while (m + i < string.length) {
if (word[i] == string[m + i]) {
if (i == word.length - 1) {
return m;
}
i = i + 1;
} else {
if (table[i] > -1) {
m = m + i - table[i];
i = table[i];
} else {
i = 0;
m = m + 1;
}
}
}
// Returns -1 if the subsequence was not found in the sequence.
return -1;
}
init
Prelude: init
Source:
function init(xs) {
if (isString(xs)) {
return xs.slice(0, xs.length - 1);
}
return [].slice.call(xs, 0, xs.length - 1);
}
inits
Prelude: inits
Source:
function inits(xs) {
var result, current, i, length;
if (isArray(xs)) {
result = [[]];
current = [];
length = xs.length;
for (i = 0; i < length; i += 1) {
current = current.concat(xs[i]);
result.push(current);
}
return result;
}
// TODO the assumption is it's a string now
result = [''];
current = '';
length = xs.length;
for (i = 0; i < length; i += 1) {
current += xs[i];
result.push(current);
}
return result;
}
insert
Prelude: insert
Source:
var insert = /* this is a composed function */
insertBy
Prelude: insertBy
Source:
function insertBy(f, x, xs) {
for (var i = 0; i < xs.length; i++) {
if (f(x, xs[i]) <= 0) {
return concat([xs.slice(0,i), x, xs.slice(i)]);
}
}
return append(xs, x);
}
intercalate
Prelude: intercalate
Source:
function intercalate(x, xs) {
return concat(intersperse(x, xs));
}
intersect
Prelude: intersect
Source:
function intersect(xs, ys) {
var set = new Set();
var zs = [];
var i;
for (i = 0; i < ys.length; i++) {
set.add(ys[i]);
}
for (i = 0; i < xs.length; i++) {
if (set.has(xs[i])) {
zs.push(xs[i]);
}
}
return zs;
}
intersperse
Prelude: intersperse
Source:
function intersperse(x, xs) {
if (xs.length === 0) {
return [];
}
var z = [xs[0]];
for (var i = 1; i < xs.length; i++) {
z.push(x);
z.push(xs[i]);
}
return z;
}
last
Prelude: last
Source:
function last(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs[xs.length - 1];
case 'list':
if (xs.isEmpty()) {
return undefined;
}
for (var ts = xs.tail(); !ts.isEmpty();) {
xs = xs.tail();
ts = xs.tail();
}
return xs.head();
default:
error(TypeError);
}
}
length
Prelude: length
Source:
function length(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs.length;
case 'list':
var count = 0;
while (!xs.isEmpty()) {
count += 1;
xs = xs.tail();
}
return count;
case 'stream':
return Infinity;
case 'object':
return Object.keys(xs).length;
default:
error(TypeError);
}
}
listToMaybe
Source:
function listToMaybe(xs) {
if (is(List, xs)) {
return xs.isEmpty() ? null : xs.head();
}
throw new TypeError();
}
lookup
Prelude: lookup
Source:
function lookup(x, xs) {
if (isArray(xs)) {
for (var i = 0; i < xs.length; i++) {
if (xs[i] && eq(xs[i][0], x)) {
return xs[i][1];
}
}
}
return xs[x];
}
lt
<LT
Prelude: <
Source:
function lt(a, b) {
return compare(a, b) < 0;
}
lte
<=LTE
Prelude: <=
Source:
function lte(a, b) {
return compare(a, b) <= 0;
}
map
fmap
Prelude: fmap
Source:
function map(f, xs) {
var i, ys;
switch (typeOf(xs)) {
case 'array':
return mapArray(f, xs);
case 'string':
return arrayToString(mapArray(f, xs));
case 'list':
if (xs.isEmpty()) {
return xs;
}
/* falls through */
case 'stream':
return new List(lazy(function () {
return f(xs.head());
}), lazy(function () {
return map(f, xs.tail());
}));
case 'object':
ys = {};
var ks = Object.keys(xs);
for (var j = 0; j < ks.length; j += 1) {
ys[ks[j]] = f(xs[ks[j]], ks[j]);
}
return ys;
}
}
max
Prelude: max
Source:
function max(a, b) {
return compare(a, b) > 0 ? a : b;
}
maximum
Prelude: maximum
Source:
var maximum = /* this is a composed function */
maximumBy
Prelude: maximumBy
Source:
function maximumBy(f, xs) {
return foldl1(function (a, b) {
if (f(a, b) > 0) {
return a;
}
return b;
}, xs);
}
min
Prelude: min
Source:
function min(a, b) {
return compare(a, b) < 0 ? a : b;
}
minimum
Prelude: minimum
Source:
var minimum = /* this is a composed function */
minimumBy
Prelude: minimumBy
Source:
function minimumBy(f, xs) {
return foldl1(function (a, b) {
if (f(a, b) < 0) {
return a;
}
return b;
}, xs);
}
neq
/=!=<>NEQ
Prelude: /=
Source:
function neq(a, b) {
return !eq(a, b);
}
notElem
Prelude: notElem
Source:
function notElem(x, xs) {
for (var i = 0; i < xs.length; i++) {
if (eq(xs[i], x)) {
return false;
}
}
return true;
}
nub
Prelude: nub
Source:
function nub(xs) {
var set = new Set();
var zs = [];
for (var i = 0; i < xs.length; i++) {
if (!set.has(xs[i])) {
zs.push(xs[i]);
set.add(xs[i]);
}
}
return zs;
}
or
Prelude: or
Source:
var or = /* this is a composed function */
partition
Prelude: partition
Source:
function _partition(p, xs) {
var as = [];
var bs = [];
for (var i = 0; i < xs.length; i++) {
(p(xs[i]) ? as : bs).push(xs[i]);
}
if (isString(xs)) {
return tuple(arrayToString(as), arrayToString(bs));
}
return tuple(as, bs);
}
product
Prelude: product
Source:
var product = /* this is a composed function */
replicate
Prelude: replicate
Source:
function replicate(n, x) {
var xs = [];
for (var i = 0; i < n; i++) {
xs.push(x);
}
return xs;
}
reverse
Prelude: reverse
Source:
function reverse(xs) {
var zs = isString(xs) ? ''.split.call(xs, '') : [].slice.call(xs);
zs.reverse();
return isString(xs) ? zs.join('') : zs;
}
scanl
Prelude: scanl
Source:
function scanl(f, x, xs) {
var zs = [x];
for (var i = 0; i < xs.length; i++) {
x = f(x, xs[i]);
zs.push(x);
}
return zs;
}
scanl1
Prelude: scanl1
Source:
function scanl1(f, xs) {
var x = xs[0];
var zs = [x];
for (var i = 1; i < xs.length; i++) {
x = f(x, xs[i]);
zs.push(x);
}
return zs;
}
scanr
Prelude: scanr
Source:
function scanr(f, x, xs) {
var zs = [x];
for (var i = xs.length - 1; i >= 0; i--) {
x = f(xs[i], x);
zs.unshift(x);
}
return zs;
}
scanr1
Prelude: scanr1
Source:
function scanr1(f, xs) {
var x = xs[xs.length - 1];
var zs = [x];
for (var i = xs.length - 2; i >= 0; i--) {
x = f(xs[i], x);
zs.unshift(x);
}
return zs;
}
select
Source:
function select(path, object) {
return foldl(at, object, path.split(/\./));
}
sinh
Prelude: sinh
Source:
function sinh(x) {
return (Math.exp(x) - Math.exp(-x)) / 2;
}
sort
Prelude: sort
Source:
function sort(xs) {
if (xs.length <= 1) {
return xs;
}
var zs = isString(xs) ? ''.split.call(xs, '') : [].slice.call(xs);
if (isNumber(zs[0])) {
zs.sort(function (a, b) { return a - b; });
} else if (isString(zs[0])) {
zs.sort(function (a, b) { return a.localeCompare(b); });
} else {
zs.sort(compare);
}
return isString(xs) ? zs.join('') : zs;
}
sortBy
Prelude: sortBy
Source:
function sortBy(fn, xs) {
if (xs.length <= 1) {
return xs;
}
var yesItsAString = isString(xs);
var zs = yesItsAString ? ''.split.call(xs, '') : [].slice.call(xs);
zs.sort(fn);
return yesItsAString ? zs.join('') : zs;
}
span
Prelude: span
Source:
function span(p, xs) {
var i = 0;
while (i < xs.length && p(xs[i])) {
i++;
}
return tuple(xs.slice(0, i), xs.slice(i));
}
splitAt
Prelude: splitAt
Source:
function splitAt(n, xs) {
return tuple(take(n, xs), drop(n, xs));
}
tail
Prelude: tail
Source:
function tail(xs) {
switch (typeOf(xs)) {
case 'array':
return [].slice.call(xs, 1);
case 'string':
return "".slice.call(xs, 1);
case 'list':
case 'stream':
return xs.tail();
default:
error(TypeError);
}
}
tails
Prelude: tails
Source:
function tails(xs) {
var result, current, i;
if (isArray(xs)) {
result = [[]];
current = [];
for (i = xs.length - 1; i >= 0; i -= 1) {
current = [xs[i]].concat(current);
result.unshift(current);
}
return result;
}
// TODO the assumption is it's a string now
result = [''];
current = '';
for (i = xs.length - 1; i >= 0; i -= 1) {
current = xs[i] + current;
result.unshift(current);
}
return result;
}
take
Prelude: take
Source:
function take(n, xs) {
switch (typeOf(xs)) {
case 'string':
return "".slice.call(xs, 0, n);
case 'array':
return [].slice.call(xs, 0, n);
case 'list':
case 'stream':
return takeGenerator(n, xs);
default:
error(TypeError);
}
}
takeWhile
Prelude: takeWhile
Source:
function takeWhile(p, xs) {
var i = 0;
while (i < xs.length && p(xs[i])) {
i++;
}
return xs.slice(0, i);
}
transpose
Prelude: transpose
Source:
function transpose(xss) {
if (!isArray(xss)) {
var zss = {};
var ks = Object.keys(xss);
for (var k = 0; k < ks.length; k++) {
zss[xss[ks[k]]] = ks[k];
}
return zss;
}
var j = 0;
var zs = [];
var current;
do {
current = [];
for (var i = 0; i < xss.length; i++) {
if (xss[i][j] !== undefined) {
current.push(xss[i][j]);
}
}
j += 1;
} while (current.length > 0 && zs.push(current));
if (isString(xss[0])) {
zs = map(arrayToString, zs);
}
return zs;
}
union
Prelude: union
Source:
function union(xs, ys) {
var set = new Set();
var zs = [];
var i;
for (i = 0; i < xs.length; i++) {
zs.push(xs[i]);
set.add(xs[i]);
}
for (i = 0; i < ys.length; i++) {
if (!set.has(ys[i])) {
zs.push(ys[i]);
}
}
return zs;
}
Appendix
Coverage of Haskell Prelude
Prelude functions supported in Nodash
- !!
- $
- &&
- *
- **
- +
- ++
- ,
- -
- .
- /
- /=
- :
- <
- <=
- ==
- >
- >=
- ^
- ^^
- abs
- acos
- acosh
- all
- and
- any
- asin
- asinh
- atan
- atanh
- break
- ceiling
- compare
- concat
- concatMap
- const
- cos
- cosh
- curry
- cycle
- div
- divMod
- drop
- either
- elem
- even
- exp
- filter
- flip
- floor
- fmap
- foldl
- foldl1
- foldr
- foldr1
- fst
- gcd
- head
- id
- init
- iterate
- last
- lcm
- length
- lines
- log
- logBase
- lookup
- map
- max
- maximum
- maybe
- min
- minimum
- mod
- negate
- not
- notElem
- odd
- or
- product
- properFraction
- quot
- quotRem
- recip
- rem
- repeat
- replicate
- reverse
- round
- scanl
- scanl1
- scanr
- scanr1
- signum
- sin
- sinh
- snd
- span
- splitAt
- sqrt
- subtract
- sum
- tail
- take
- takeWhile
- tan
- tanh
- truncate
- uncurry
- unlines
- until
- unwords
- words
- zip
- zip3
- zipWith
- zipWith3
- ||
Prelude functions missing from Nodash
- $!
- =<<
- >>
- >>=
- FilePath
- IOError
- appendFile
- asTypeOf
- atan2
- catch
- decodeFloat
- dropWhie
- encodeFloat
- enumFrom
- enumFromThen
- enumFromThenTo
- enumFromTo
- error
- exponent
- fail
- floatDigits
- floatRadix
- floatRange
- fromEnum
- fromInteger
- fromIntegral
- fromRational
- getChar
- getContents
- getLine
- interact
- ioError
- isDenormalized
- isIEEE
- isInfinite
- isNaN
- isNegativeZero
- lex
- mapM
- mapM_
- maxBound
- minBound
- null
- otherwise
- pi
- pitStr
- pred
- print
- putChar
- putStrLn
- read
- readFile
- readIO
- readList
- readLn
- readParen
- reads
- readsPrec
- realToFrac
- return
- scaleFloat
- seq
- sequence
- sequence_
- show
- showChar
- showList
- showParen
- showString
- shows
- showsPrec
- significand
- succ
- toEnum
- toInteger
- toRational
- undefined
- unzip
- unzip3
- userError
- writeFile
Nodash-specific additions
- Either
- Left
- List
- Right
- Stream
- Thunk
- Tuple
- arrayToString
- async
- bool
- catMaybes
- chr
- classOf
- clone
- comparing
- compose2
- curried
- each
- emptyList
- fromLeft
- fromMaybe
- fromRight
- idf
- indexOf
- install
- invoke
- is
- isArguments
- isArray
- isAsciiLetter
- isBoolean
- isDate
- isEmpty
- isFunction
- isInteger
- isJust
- isLeft
- isLetter
- isLower
- isNothing
- isNull
- isNumber
- isNumeric
- isObject
- isRegExp
- isRight
- isString
- isUndefined
- isUpper
- keys
- lazy
- lefts
- listToArray
- listToMaybe
- listToString
- mapMaybe
- match
- maybeToList
- objectToArray
- on
- ord
- partitionEithers
- pipe
- range
- rangeStep
- register
- resolveThunk
- rights
- run
- select
- singleton
- tuple3
- tuple4
- tuplesToObject
- typeOf
- values
arrayToString
Source:
function arrayToString(array) {
return array.join('');
}
lazy arrayToList
Source:
function lazy(val) {
if (isFunction(val)) {
return new Thunk(val);
}
function generator(i) {
if (i < val.length) {
return new List(val[i], new Thunk(function () {
return generator(i + 1);
}));
}
return emptyList();
}
return generator(0);
}
List
new List(head, tail) :: a → [a] → [a]
Lists are immutable singly-linked sequences.
Methods:
- .head() → a
- Extract the first element in the list.
- .tail() → List a
- Extract the rest of the list.
Lists are typically not constructed by user code with this constructor, but with builers such as arrayToList.
The purpose of the List type is to implement lazy evaluation.
Internally the head and the tail of a list may actually be Thunks
which are evaluated only if you call .head()
or .tail()
respectively.
To construct lazy lists, use lazy.
Example:
var xs = new List(38, new List(42, emptyList()))
console.log(xs.head()) // 38
console.log(xs.tail().head()) // 42
head
and tail
are functional forms of .head()
and .tail()
.
var xs = lazy([1, 2, 3, 4, 5]);
console.log(head(xs)); // 1
console.log(head(tail(xs))); // 2
Haskell Definition:
data List a = EmptyList | Cons { head :: a, tail :: (List a) }
Source:
function List(head, tail) {
var self = this;
this.head = function () {
if (is(Thunk, head)) {
var value = head.get();
self.head = head.get;
return value;
}
return head;
};
this.tail = function () {
if (is(Thunk, tail)) {
var value = tail.get();
self.tail = tail.get;
return value;
}
return tail;
};
}
listToArray
Source:
function listToArray(xs) {
var array = [];
each(function (x) {
array.push(x);
}, xs);
return array;
}
listToString
Source:
var listToString = /* this is a composed function */
range ..
Source:
function range(from, to) {
return rangeStep(1, from, to);
}
rangeStep
Source:
function rangeStep(step, from, to) {
step = from < to ? step : -step;
to = step > 0 ? Math.floor(to) : Math.ceil(to);
var current = from;
function gen() {
current += step;
return new List(current, current === to ? emptyList : new Thunk(gen));
}
return new List(from, new Thunk(gen));
}
singleton
Source:
function singleton(thing) {
return new List(thing, emptyList);
}
catMaybes
Source:
var catMaybes = /* this is a composed function */
isJust
Source:
function isJust(thing) {
return thing !== null && thing !== undefined;
}
isNothing
Source:
function isNothing(thing) {
return !isJust(thing);
}
mapMaybe
Source:
var mapMaybe = /* this is a composed function */
maybe Prelude: maybe
Source:
function maybe(def, fun, value) {
if (value === null || value === undefined) {
return def;
}
return fun(value);
}
maybeToList
Source:
function maybeToList(thing) {
if (isJust(thing)) {
return singleton(thing);
}
return emptyList();
}
Math
abs
Prelude: abs
Number → Number
Returns the absolute (positive, non-negative) value of a number.
Example:
abs(9) === 9
abs(-3) === 3
Haskell Definition:
abs x | x >= 0 = x
| x < 0 = -x
Source:
function abs() { [native code] }
acos
Prelude: acos
Number → Number
Source:
function acos() { [native code] }
acosh
Prelude: acosh
Number → Number
Source:
function acosh(x) {
return Math.log(x + Math.sqrt(x * x - 1));
}
add
+ADDplusPLUS
Prelude: +
Number → Number → Number
Source:
function add(a, b) {
return a + b;
}
asin
Prelude: asin
Number → Number
Source:
function asin() { [native code] }
asinh
Prelude: asinh
Number → Number
Source:
function asinh(x) {
if (x === -Infinity) {
return x;
} else {
return Math.log(x + Math.sqrt(x * x + 1));
}
}
atan
Prelude: atan
Number → Number
Source:
function atan() { [native code] }
atanh
Prelude: atanh
Number → Number
Source:
function atanh(x) {
return Math.log((1 + x) / (1 - x)) / 2;
}
ceiling
Prelude: ceiling
Number → Number
ceiling x
returns the least integer not less than x
.
Source:
function ceil() { [native code] }
cos
Prelude: cos
Number → Number
Source:
function cos() { [native code] }
cosh
Prelude: cosh
Number → Number
Source:
function cosh(x) {
return (Math.exp(x) + Math.exp(-x)) / 2;
}
div
Prelude: div
Number → Number
Source:
function div(a, b) {
return Math.floor(a / b);
}
divMod
Prelude: divMod
Number → Number → (Number, Number)
Source:
function divMod(a, b) {
return tuple(div(a, b), mod(a, b));
}
even
Prelude: even
Number → Bool
Source:
function even(x) {
return (x % 2) === 0;
}
exp
Prelude: exp
Number → Number
Source:
function exp() { [native code] }
floor
Prelude: floor
Number → Number
floor x
returns the greatest integer not greater than x
.
Source:
function floor() { [native code] }
frac
/
Prelude: /
Number → Number → Number
Source:
function frac(a, b) {
return a / b;
}
gcd
Prelude: gcd
Number → Number → Number
Source:
function gcd(a, b) {
var c;
while (b !== 0) {
c = rem(a, b);
a = b;
b = c;
}
return a;
}
lcm
Prelude: lcm
Number → Number → Number
Source:
function lcm(a, b) {
if (a === 0 || b === 0) {
return 0;
}
return Math.abs(quot(a, gcd(a, b)) * b);
}
log
Prelude: log
Number → Number
Source:
function log() { [native code] }
logBase
Prelude: logBase
Number → Number → Number
Haskell Definition:
logBase x y = log y / log x
Source:
function logBase(a, b) {
return Math.log(a) / Math.log(b);
}
minus
-MINUS
Prelude: -
Number → Number → Number
Source:
function minus(a, b) {
return a - b;
}
mod
Prelude: mod
Number → Number → Number
Source:
function mod(a, b) {
var q = quot(a, b);
var r = rem(a, b);
return signum(r) === -signum(b) ? r + b : r;
}
mul
*MULtimesTIMES
Prelude: *
Number → Number → Number
Source:
function mul(a, b) {
return a * b;
}
negate
Prelude: negate
Number → Number
Source:
function negate(x) {
return -x;
}
odd
Prelude: odd
Number → Boolean
Source:
function odd(x) {
return (x % 2) !== 0;
}
pow
**^^^
Prelude: ^^
Haskell Definition:
x ** y = exp (log x * y)
Source:
function pow() { [native code] }
properFraction
Prelude: properFraction
Number → (Number, Number)
properFraction
takes a real fractional
number x
and returns a pair (n, f)
such that x = n + f
,
and: n
is an integral number with the same sign as x
;
and f
is a fraction with the same type and sign as x
,
and with absolute value less than 1.
Source:
function properFraction(x) {
var num = truncate(x);
return tuple(num, -(num - x));
}
quot
Prelude: quot
Number → Number → Number
Source:
function quot(a, b) {
var r = a / b;
return r >= 0 ? Math.floor(r) : Math.ceil(r);
}
quotRem
Prelude: quotRem
Number → Number → (Number, Number)
Source:
function quotRem(a, b) {
return tuple(quot(a, b), rem(a, b));
}
recip
Prelude: recip
Haskell Definition:
recip = 1 / x
Source:
function recip(x) {
return 1 / x;
}
rem
Prelude: rem
Number → Number → Number
Source:
function rem(a, b) {
return a % b;
}
round
Prelude: round
Number → Number
round x
returns the nearest integer to x
; the even
integer if x
is equidistant between two integers.
Source:
function round(x) {
var fraction = properFraction(x);
var n = fraction[0];
var m = fraction[1] < 0 ? n - 1 : n + 1;
switch (signum(Math.abs(fraction[1]) - 0.5)) {
case -1:
return n;
case 0:
return n % 2 === 0 ? n : m;
case 1:
return m;
}
}
signum
Prelude: signum
Number → Number
Haskell Definition:
signum x | x > 0 = 1
| x == 0 = 0
| x < 0 = -1
Source:
function signum(x) {
if (x > 0) {
return 1;
} else if (x === 0) {
return 0;
}
return -1;
}
sin
Prelude: sin
Number → Number
Source:
function sin() { [native code] }
sqrt
Prelude: sqrt
Number → Number
Source:
function sqrt() { [native code] }
sub
subtract
Prelude: subtract
Number → Number
Source:
function sub(a, b) {
return b - a;
}
tan
Prelude: tan
Number → Number
Haskell Definition:
tan x = sin x / cos x
Source:
function tan() { [native code] }
tanh
Prelude: tanh
Number → Number
Haskell Definition:
tanh x = sinh x / cosh x
Source:
function tanh(x) {
if (x === Infinity) {
return 1;
} else if (x === -Infinity) {
return -1;
} else {
return (Math.exp(x) - Math.exp(-x)) / (Math.exp(x) + Math.exp(-x));
}
}
truncate
Prelude: truncate
Number → Number
truncate x
returns the integer nearest x
between zero and x
.
Source:
function truncate(x) {
switch (signum(x)) {
case -1:
return Math.ceil(x);
case 1:
return Math.floor(x);
}
return 0;
}
Nodash
install
Source:
function install(mountpoint) {
var options = arguments[1];
var nodashObject = Nodash;
var prefix = '';
var postfix = '';
if (!mountpoint) {
return Nodash;
}
if (options) {
nodashObject = makeNodash(options);
}
if (isArray(mountpoint)) {
if (isString(mountpoint[0])) {
prefix = [].shift.call(mountpoint);
}
if (isString(mountpoint[1])) {
postfix = mountpoint[1];
}
mountpoint = mountpoint[0] || {};
}
each(function (func, name) {
if (name[0] === '_') {
return;
}
var key = prefix + name + postfix;
if (!(key in mountpoint)) {
mountpoint[key] = func;
}
}, nodashObject);
return mountpoint;
}
register
Source:
function register() {
var args = [].slice.call(arguments);
if (arguments.length === 1) {
switch (typeof args[0]) {
case 'object':
if (Array.isArray(args[0])) {
registerInjected(args[0].slice());
} else {
registerLib(args[0]);
}
break;
case 'function':
register(args[0].call(Nodash));
break;
}
return;
}
var func = args.pop();
var aliases = [];
args.forEach(function (arg) {
[].push.apply(aliases, arg.split(/ +/));
});
var name = null;
for (var i = 0; i < aliases.length; i += 1) {
if (/^[a-z0-9]+$/i.test(aliases[i])) {
name = aliases[i];
break;
}
}
__metadata[name] = {
aliases: aliases,
definition: func
};
if (!/^[A-Z]/.test(name)) {
func = curried(func);
}
aliases.forEach(function (alias) {
Nodash[alias] = func;
});
}
Pattern
match
MatchSpec → Any → MatchResult
match(spec, value)
matches value
against the spec
, returning
what was captured in the spec.
A MatchSpec
is an array of arrays. Every array in the spec
must have two elements: [ 0: Pattern, 1: Result ]
. The first
Pattern
that matches value
will yield the associated Result
.
If Result
is a function it will be invoked with an object of
all captured variables in the Pattern
and the result will be returned,
otherwise the Result
itself.
Example:
var matchJohn = match([
[ { firstName: 'John' }, 'John is a fine name' ],
[ { firstName: '$firstName' },
function (result) {
return result.$firstName + ' is also a fine name'; } ]
]);
console.log(matchJohn({ firstName: 'John', lastName: 'Doe' }));
// → 'John is a fine name'
console.log(matchJohn({ firstName: 'Johnathan', lastName: 'X' }));
// → 'Jonathan is also a fine name'
Source:
function match(pattern, arg) {
for (var i = 0; i < pattern.length; i += 1) {
var result = {};
var p = pattern[i];
if (matchR(p[0], arg, result)) {
if (typeof p[1] === 'function') {
return p[1](result);
}
return p[1];
}
}
}
Object
each
Source:
function each(f, xs) {
if (is(List, xs)) {
while (!xs.isEmpty()) {
f(xs.head());
xs = xs.tail();
}
} else if (isArray(xs) || isString(xs)) {
for (var i = 0; i < xs.length; i++) {
f(xs[i], i);
}
} else if (isObject(xs)) {
var ks = Object.keys(xs);
for (var j = 0; j < ks.length; j += 1) {
f(xs[ks[j]], ks[j]);
}
}
}
keys
Source:
function keys() { [native code] }
values
Source:
function values(object) {
var values = [];
each(function (value) {
values.push(value);
}, object);
return values;
}
Stream
cycle
Prelude: cycle
Source:
function cycle(xs) {
if (isArray(xs)) {
xs = lazy(xs);
}
function generator(ys) {
if (ys.isEmpty()) {
ys = xs;
}
return function () {
return tuple(ys.head(), generator(ys.tail()));
};
}
return new Stream(generator(xs));
}
iterate
Prelude: iterate
Source:
function iterate(f, seed) {
function generator(seed) {
return function () {
var newSeed = f(seed);
return tuple(seed, generator(newSeed));
};
}
return new Stream(generator(seed));
}
repeat
Prelude: repeat
Source:
function repeat(x) {
function generator() {
return tuple(x, generator);
}
return new Stream(generator);
}
Stream
stream
new Stream(generator)
Streams are immutable, lazily evaluated, infinite Lists.
Methods:
- .head() → a
- Extract the first element of this stream.
- .tail() → List a
- Extract the rest of the stream.
Source:
function Stream(generator) {
if (!(this instanceof Stream)) {
return new Stream(generator);
}
var thunk = new Thunk(generator);
var self = this;
this.head = function () {
var value = thunk.get().fst();
self.head = idf(value);
return value;
};
this.tail = function () {
var value = thunk.get().snd();
switch (typeOf(value)) {
case 'list':
case 'stream':
break;
case 'function':
value = new Stream(value);
break;
default:
error(TypeError);
}
self.tail = idf(value);
return value;
};
}
until
Prelude: until
Source:
function until(p, f, v) {
while (!p(v)) {
v = f(v);
}
return v;
}
String
lines
Prelude: lines
Source:
function lines(string) {
var result = string.split(/\n/);
if (result[result.length - 1].length === 0) {
delete result[result.length - 1];
}
return result;
}
unlines
Prelude: unlines
Source:
function unlines(lines) {
return lines.join('\n');
}
unwords
Prelude: unwords
Source:
function unwords(words) {
return words.join(' ');
}
words
Prelude: words
Source:
function words(string) {
return string.split(/[\n\r\v\t ]/);
}
Tuple
fst
Prelude: fst
(a, b) → b
Extract the first component of a pair.
Tuples also have a fst()
method which does the same thing,
but this function is exposing that method as a function.
Haskell Definition:
fst (a, _) = a
Source:
function fst(t) {
return t.fst();
}
objectToArray
Object → [(String, Any)]
Turns an object into an associative list of tuples.
The objects keys are the first components of the tuples,
the values the second components.
eq( objectToArray({ a: 17, b: 20 }), [ tuple('a', 17), tuple('b', 20) ]) === true
Source:
function objectToArray(obj) {
var arr = [];
each(function (val, key) {
arr.push(new Tuple(key, val));
}, obj);
return arr;
}
snd
Prelude: snd
(a, b) → b
Extract the second component of a pair.
Tuples also have a fst()
method which does the same thing,
but this function is exposing that method as a function.
Haskell Definition:
snd (_, b) = b
Source:
function snd(t) {
return t.snd();
}
Tuple
new Tuple(first, second) :: a → b → (a, b)
Tuples are immutable pairs of a first and a second components.
Methods:
- .fst() → a
- Retrieves the first component of this tuple.
- .snd() → b
- Retrieves the second component of this tuple.
Example:
var t = new Tuple(4711, 8080);
console.log(t.fst()); // 4711
console.log(t.snd()); // 8080
fst
and snd
are functional forms of .fst()
and .snd()
.
tuple
is a convenience method for omitting new
:
var t = tuple(4711, 8080);
console.log(fst(t)); // 4711
console.log(snd(t)); // 8080
var extractFirsts = map(fst);
console.log(extractFirsts([
tuple(4711, 8080),
tuple(3000, 4444)
])); // [ 4711, 3000 ]
Haskell Definition:
data Tuple a b = Tuple { fst :: a, snd :: b }
Source:
function Tuple(fst, snd) {
if (!(this instanceof Tuple)) {
return new Tuple(fst, snd);
}
this.fst = idf(fst);
this.snd = idf(snd);
freeze(this);
}
tuple
,
Prelude: ,
Source:
function tuple(first, second) {
return new Tuple(first, second);
}
tuple3
,,
Source:
function tuple3(first, second, third) {
return tuple(first, tuple(second, third));
}
tuple4
,,,
Source:
function tuple4(first, second, third, fourth) {
return tuple3(first, second, tuple(third, fourth));
}
tuplesToObject
[(String, Any)] → Object
Turns an associative list of tuples into an object.
The first components of the tuples are the keys,
the second components the corresponding values.
Example:
eq( tuplesToObject([ tuple('a', 2), tuple('b', 3) ]), { a: 2, b: 3 }) === true
Source:
function tuplesToObject(xs) {
var obj = {};
each(function (t) {
obj[t.fst()] = t.snd();
}, xs);
return obj;
}
Type
classOf
Any → String
Determines the property of the internal
[[Class]]
attribute,
normalized to lower case.
Example:
classOf(new Date()) === 'date'
classOf(null) === 'null'
classOf([]) === 'array'
function f() {
return classOf(arguments)
}
f() === 'arguments'
Source:
function classOf(thing) {
var exactType = toString.call(thing);
return exactType.slice(8, exactType.length - 1).toLowerCase();
}
is
Source:
function is(type, thing) {
return thing instanceof type;
}
isArguments
Any → Boolean
Source:
function isArguments(thing) {
return toString.call(thing) === '[object Arguments]';
}
isArray
Any → Boolean
Determines whether something is an array or not.
This is exactly the same as Array.isArray
.
Example:
isArray([]) === true
isArray({}) === false
isArray(new Array(3)) === true
isArray(undefined) === false
isArray(3) === false
Source:
function isArray() { [native code] }
isBoolean
Any → Boolean
Returns true
if the argument is a boolean value, otherwise false
.
Example:
isBoolean(true) === true
isBoolean(false) === false
isBoolean({}) === false
isBoolean(undefined) === false
isBoolean(0) === false
isBoolean(1) === false
isBoolean("true") === false
Source:
function isBoolean(thing) {
return typeof thing === 'boolean';
}
isDate
Any → Boolean
Source:
function isDate(thing) {
return toString.call(thing) === '[object Date]';
}
isEmpty
null_
Prelude: null
Any → Boolean
Source:
function isEmpty(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs.length === 0;
case 'list':
case 'stream':
return xs.isEmpty();
default:
for (var _ in xs) {
return false;
}
return true;
}
}
isFunction
Any → Boolean
Source:
function isFunction(thing) {
return typeof thing === 'function';
}
isInteger
Any → Boolean
Returns true
is the argument is an integral number.
Numbers in JavaScript are floating point values and there is no proper integer type.
This function can be used to check whether a given number could be cast to an
integer without truncating.
isInteger(7) === true
isInteger(7.0) === true
isInteger(7.3) === false
Source:
function isInteger(thing) {
return isNumber(thing) && !isNaN(thing) &&
thing - Math.floor(thing) === 0 &&
thing !== Infinity && thing !== -Infinity;
}
isNull
Any → Boolean
Source:
function isNull(thing) {
return toString.call(thing) === '[object Null]';
}
isNumber
Source:
function isNumber(thing) {
return typeof thing === 'number';
}
isObject
Source:
function isObject(thing) {
return typeof thing === 'object' &&
thing !== null && !Array.isArray(thing);
}
isRegExp
Any → Boolean
Returns true
is the argument is a regular expression object.
Example:
isRegExp(/a+/) === true
isRegExp("a+") === false
isRegExp(new RegExp("a+")) === true
Source:
function isRegExp(thing) {
return toString.call(thing) === '[object RegExp]';
}
isString
Source:
function isString(thing) {
return typeof thing === 'string' || toString.call(thing) === '[object String]';
}
isUndefined
Source:
function isUndefined(thing) {
return typeof thing === 'undefined';
}
typeOf
Something → String
Returns the type of the given thing as a String.
This differs from JavaScripts typeof
in the way that it
distinguishes null
, object
, and array
and identifies
NaN
as not-a-number
(Infinity
and -Infinity
are both
reported as number
). Also it knows some types native to
nodash, such as list
, stream
, and tuple
.
The possible return values are:
boolean
for true
and false
,
number
for a number which is not NaN
,
string
for a JavaScript string,
function
for a JavaScript function,
not-a-number
if isNaN
would return true,
null
for null
,
undefined
for undefined
,
array
is Array.isArray
would return true,
list
if it is a List,
stream
if it is a Stream,
tuple
if it is a Tuple,
object
if it is an object but neither null
nor an array
or any of the previously mentioned object types (e.g. tuple
)
In ECMAScript 2015 (ES6) this function may also return symbol
for Symbols.
Source:
function typeOf(thing) {
var type = typeof thing;
switch (type) {
case 'number':
return isNaN(thing) ? 'not-a-number' : 'number';
case 'object':
var exactType = classOf(thing);
if (exactType === 'object' && thing.constructor && thing.constructor.__type) {
return thing.constructor.__type;
}
return exactType;
default:
return type;
}
}
(unclassified)
any
Prelude: any
Source:
function any(p, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
return true;
}
}
return false;
}
append
++
Prelude: ++
Source:
function append(xs, ys) {
switch (typeOf(xs)) {
case 'list':
return appendList(xs, ys);
case 'string':
return xs + ys;
case 'array':
return [].concat.call(xs, ys);
default:
error(TypeError);
}
}
at
!!AT
Prelude: !!
Source:
function at(xs, ix) {
if (xs === undefined) {
return xs;
}
return xs[ix];
}
break
break_
Prelude: break
Source:
function break(p, xs) {
var i = 0;
while (i < xs.length && !p(xs[i])) {
i++;
}
return tuple(xs.slice(0, i), xs.slice(i));
}
clone
Source:
function clone(thing) {
if (typeof thing === 'object') {
if (thing === null) {
return null;
}
return map(clone, thing);
}
return thing;
}
compare
Prelude: compare
Source:
function compare(a, b) {
switch (typeof a) {
case 'string':
return a.localeCompare(b);
case 'object':
if (isFunction(a.compareTo)) {
return a.compareTo(b);
} else if (isArray(a)) {
for (var i = 0; i < Math.min(a.length, b.length); i++) {
var r = compare(a[i], b[i]);
if (r !== 0) {
return r;
}
}
return 0;
}
return a.toString().localeCompare(b.toString());
case 'number':
return signum(a - b);
}
return undefined;
}
comparing
Source:
function comparing(f, a, b) {
return compare(f(a), f(b));
}
concat
Prelude: concat
Source:
function concat(xs) {
if (isString(xs[0])) {
return xs.join('');
}
var zs = [];
var ks = Object.keys(xs);
for (var i = 0; i < ks.length; i++) {
[].push.apply(zs, xs[ks[i]]);
}
return zs;
}
concatMap
Prelude: concatMap
Source:
var concatMap = /* this is a composed function */
cons
:
Prelude: :
Source:
function cons(x, xs) {
switch (typeOf(xs)) {
case 'array':
var zs = [].slice.call(xs);
zs.unshift(x);
return zs;
case 'string':
return x + xs;
case 'list':
return new List(x, xs);
case 'stream':
return new Stream(function () {
return tuple(x, xs);
});
default:
error(TypeError);
}
}
curried
Source:
function curried(fn) {
return funcs[fn.length](fn);
}
delete
delete_
Prelude: delete
Source:
function delete(x, xs) {
var i = xs.indexOf(x);
if (i >= 0) {
return append(xs.slice(0,i), xs.slice(i+1));
}
return xs;
}
deleteBy
Prelude: deleteBy
Source:
function deleteBy(p, x, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(x, xs[i])) {
return append(xs.slice(0,i), xs.slice(i+1));
}
}
return xs;
}
difference
\\
Prelude: \\
Source:
function difference(xs, ys) {
var set = new Set();
var i;
for (i = 0; i < ys.length; i++) {
set.add(ys[i]);
}
var zs = [];
for (i = 0; i < xs.length; i++) {
if (!set.has(xs[i])) {
zs.push(xs[i]);
}
}
return isString(xs) ? arrayToString(zs) : zs;
}
drop
Prelude: drop
Source:
function drop(n, xs) {
return xs.slice(n);
}
dropWhile
Prelude: dropWhile
Source:
function dropWhile(p, xs) {
var i = 0;
while (i < xs.length && p(xs[i])) {
i++;
}
return xs.slice(i);
}
either
Prelude: either
Source:
function either(afun, bfun, value) {
if (is(Left, value)) {
return afun(value.value());
} else if (is(Right, value)) {
return bfun(value.value());
} else {
fail();
}
}
elem
Prelude: elem
Source:
function elem(x, xs) {
for (var i = 0; i < xs.length; i++) {
if (eq(xs[i], x)) {
return true;
}
}
return false;
}
elemIndex
Prelude: elemIndex
Source:
function elemIndex(x, xs) {
return findIndex(eq(x), xs);
}
elemIndices
Prelude: elemIndices
Source:
function elemIndices(x, xs) {
return findIndices(eq(x), xs);
}
emptyList
Source:
function emptyList() {
return emptyList;
}
eq
==EQ
Prelude: ==
Source:
function eq(a, b) {
if (a === b) {
return true;
}
var ta = typeOf(a);
var tb = typeOf(b);
if (ta !== tb) {
return false;
}
switch (ta) {
case 'tuple':
return eq(a.fst(), b.fst()) && eq(a.snd(), b.snd());
case 'list':
return eq(a.head(), b.head()) && eq(a.tail(), b.tail());
case 'array':
case 'object':
if (a.constructor !== b.constructor) {
return false;
}
var k = union(Object.keys(a), Object.keys(b));
for (var i = 0; i < k.length; i++) {
if (!eq(a[k[i]], b[k[i]])) {
return false;
}
}
return true;
}
return false;
}
filter
Prelude: filter
Source:
function filter(p, xs) {
var ys;
switch (typeOf(xs)) {
case 'array':
case 'string':
ys = [];
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
ys.push(xs[i]);
}
}
return isString(xs) ? arrayToString(ys) : ys;
default:
ys = {};
var ks = Object.keys(xs);
for (var j = 0; j < ks.length; j++) {
if (p(xs[ks[j]])) {
ys[ks[j]] = xs[ks[j]];
}
}
return ys;
}
}
find
Prelude: find
Source:
function find(p, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
return xs[i];
}
}
return null;
}
findIndex
Prelude: findIndex
Source:
function findIndex(p, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
return i;
}
}
return null;
}
findIndices
Prelude: findIndices
Source:
function findIndices(p, xs) {
var zs = [];
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
zs.push(i);
}
}
return zs;
}
foldl1
foldl1'
Prelude: foldl1'
Source:
function foldl1(f, xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
var x = xs[0];
for (var i = 1; i < xs.length; i += 1) {
x = f(xs[i], x);
}
return x;
}
}
foldr1
Prelude: foldr1
Source:
function foldr1(f, xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
var x = xs[xs.length - 1];
for (var i = xs.length - 2; i >= 0; i -= 1) {
x = f(xs[i], x);
}
return x;
}
}
fromLeft
Source:
function fromLeft(thing) {
if (is(Left, thing)) {
return thing.value();
}
fail();
}
fromMaybe
Source:
function fromMaybe(def, maybe) {
if (isJust(maybe)) {
return maybe;
}
return def;
}
fromRight
Source:
function fromRight(thing) {
if (is(Right, thing)) {
return thing.value();
}
fail();
}
group
Prelude: group
Source:
var group = /* this is a composed function */
groupBy
Prelude: groupBy
Source:
function groupBy(p, xs) {
if (xs.length === 0) {
return [];
}
var zs = [];
var current = [xs[0]];
var last = xs[0];
for (var i = 1; i < xs.length; i++) {
if (p(xs[i], last)) {
current.push(xs[i]);
} else {
zs.push(current);
current = [xs[i]];
}
last = xs[i];
}
zs.push(current);
return isString(xs) ? map(arrayToString, zs) : zs;
}
gt
>GT
Prelude: >
Source:
function gt(a, b) {
return compare(a, b) > 0;
}
gte
>=GTE
Prelude: >=
Source:
function gte(a, b) {
return compare(a, b) >= 0;
}
head
Prelude: head
Source:
function head(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs[0];
case 'list':
case 'stream':
return xs.head();
default:
error(TypeError);
}
}
indexOf
Source:
function indexOf(word, string) {
'use strict';
var m = 0;
var i = 0;
var table = [];
var pos = 2;
var cnd = 0;
table[0] = -1;
table[1] = 0;
// build the table for KMP. This takes `O(word.length)` steps.
while (pos < word.length) {
if (word[pos - 1] == word[cnd]) {
cnd = cnd + 1;
table[pos] = cnd;
pos = pos + 1;
} else if (cnd > 0) {
cnd = table[cnd];
} else {
table[pos] = 0;
pos = pos + 1;
}
}
// scan the string. This takes `O(string.length)` steps.
while (m + i < string.length) {
if (word[i] == string[m + i]) {
if (i == word.length - 1) {
return m;
}
i = i + 1;
} else {
if (table[i] > -1) {
m = m + i - table[i];
i = table[i];
} else {
i = 0;
m = m + 1;
}
}
}
// Returns -1 if the subsequence was not found in the sequence.
return -1;
}
init
Prelude: init
Source:
function init(xs) {
if (isString(xs)) {
return xs.slice(0, xs.length - 1);
}
return [].slice.call(xs, 0, xs.length - 1);
}
inits
Prelude: inits
Source:
function inits(xs) {
var result, current, i, length;
if (isArray(xs)) {
result = [[]];
current = [];
length = xs.length;
for (i = 0; i < length; i += 1) {
current = current.concat(xs[i]);
result.push(current);
}
return result;
}
// TODO the assumption is it's a string now
result = [''];
current = '';
length = xs.length;
for (i = 0; i < length; i += 1) {
current += xs[i];
result.push(current);
}
return result;
}
insert
Prelude: insert
Source:
var insert = /* this is a composed function */
insertBy
Prelude: insertBy
Source:
function insertBy(f, x, xs) {
for (var i = 0; i < xs.length; i++) {
if (f(x, xs[i]) <= 0) {
return concat([xs.slice(0,i), x, xs.slice(i)]);
}
}
return append(xs, x);
}
intercalate
Prelude: intercalate
Source:
function intercalate(x, xs) {
return concat(intersperse(x, xs));
}
intersect
Prelude: intersect
Source:
function intersect(xs, ys) {
var set = new Set();
var zs = [];
var i;
for (i = 0; i < ys.length; i++) {
set.add(ys[i]);
}
for (i = 0; i < xs.length; i++) {
if (set.has(xs[i])) {
zs.push(xs[i]);
}
}
return zs;
}
intersperse
Prelude: intersperse
Source:
function intersperse(x, xs) {
if (xs.length === 0) {
return [];
}
var z = [xs[0]];
for (var i = 1; i < xs.length; i++) {
z.push(x);
z.push(xs[i]);
}
return z;
}
last
Prelude: last
Source:
function last(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs[xs.length - 1];
case 'list':
if (xs.isEmpty()) {
return undefined;
}
for (var ts = xs.tail(); !ts.isEmpty();) {
xs = xs.tail();
ts = xs.tail();
}
return xs.head();
default:
error(TypeError);
}
}
length
Prelude: length
Source:
function length(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs.length;
case 'list':
var count = 0;
while (!xs.isEmpty()) {
count += 1;
xs = xs.tail();
}
return count;
case 'stream':
return Infinity;
case 'object':
return Object.keys(xs).length;
default:
error(TypeError);
}
}
listToMaybe
Source:
function listToMaybe(xs) {
if (is(List, xs)) {
return xs.isEmpty() ? null : xs.head();
}
throw new TypeError();
}
lookup
Prelude: lookup
Source:
function lookup(x, xs) {
if (isArray(xs)) {
for (var i = 0; i < xs.length; i++) {
if (xs[i] && eq(xs[i][0], x)) {
return xs[i][1];
}
}
}
return xs[x];
}
lt
<LT
Prelude: <
Source:
function lt(a, b) {
return compare(a, b) < 0;
}
lte
<=LTE
Prelude: <=
Source:
function lte(a, b) {
return compare(a, b) <= 0;
}
map
fmap
Prelude: fmap
Source:
function map(f, xs) {
var i, ys;
switch (typeOf(xs)) {
case 'array':
return mapArray(f, xs);
case 'string':
return arrayToString(mapArray(f, xs));
case 'list':
if (xs.isEmpty()) {
return xs;
}
/* falls through */
case 'stream':
return new List(lazy(function () {
return f(xs.head());
}), lazy(function () {
return map(f, xs.tail());
}));
case 'object':
ys = {};
var ks = Object.keys(xs);
for (var j = 0; j < ks.length; j += 1) {
ys[ks[j]] = f(xs[ks[j]], ks[j]);
}
return ys;
}
}
max
Prelude: max
Source:
function max(a, b) {
return compare(a, b) > 0 ? a : b;
}
maximum
Prelude: maximum
Source:
var maximum = /* this is a composed function */
maximumBy
Prelude: maximumBy
Source:
function maximumBy(f, xs) {
return foldl1(function (a, b) {
if (f(a, b) > 0) {
return a;
}
return b;
}, xs);
}
min
Prelude: min
Source:
function min(a, b) {
return compare(a, b) < 0 ? a : b;
}
minimum
Prelude: minimum
Source:
var minimum = /* this is a composed function */
minimumBy
Prelude: minimumBy
Source:
function minimumBy(f, xs) {
return foldl1(function (a, b) {
if (f(a, b) < 0) {
return a;
}
return b;
}, xs);
}
neq
/=!=<>NEQ
Prelude: /=
Source:
function neq(a, b) {
return !eq(a, b);
}
notElem
Prelude: notElem
Source:
function notElem(x, xs) {
for (var i = 0; i < xs.length; i++) {
if (eq(xs[i], x)) {
return false;
}
}
return true;
}
nub
Prelude: nub
Source:
function nub(xs) {
var set = new Set();
var zs = [];
for (var i = 0; i < xs.length; i++) {
if (!set.has(xs[i])) {
zs.push(xs[i]);
set.add(xs[i]);
}
}
return zs;
}
or
Prelude: or
Source:
var or = /* this is a composed function */
partition
Prelude: partition
Source:
function _partition(p, xs) {
var as = [];
var bs = [];
for (var i = 0; i < xs.length; i++) {
(p(xs[i]) ? as : bs).push(xs[i]);
}
if (isString(xs)) {
return tuple(arrayToString(as), arrayToString(bs));
}
return tuple(as, bs);
}
product
Prelude: product
Source:
var product = /* this is a composed function */
replicate
Prelude: replicate
Source:
function replicate(n, x) {
var xs = [];
for (var i = 0; i < n; i++) {
xs.push(x);
}
return xs;
}
reverse
Prelude: reverse
Source:
function reverse(xs) {
var zs = isString(xs) ? ''.split.call(xs, '') : [].slice.call(xs);
zs.reverse();
return isString(xs) ? zs.join('') : zs;
}
scanl
Prelude: scanl
Source:
function scanl(f, x, xs) {
var zs = [x];
for (var i = 0; i < xs.length; i++) {
x = f(x, xs[i]);
zs.push(x);
}
return zs;
}
scanl1
Prelude: scanl1
Source:
function scanl1(f, xs) {
var x = xs[0];
var zs = [x];
for (var i = 1; i < xs.length; i++) {
x = f(x, xs[i]);
zs.push(x);
}
return zs;
}
scanr
Prelude: scanr
Source:
function scanr(f, x, xs) {
var zs = [x];
for (var i = xs.length - 1; i >= 0; i--) {
x = f(xs[i], x);
zs.unshift(x);
}
return zs;
}
scanr1
Prelude: scanr1
Source:
function scanr1(f, xs) {
var x = xs[xs.length - 1];
var zs = [x];
for (var i = xs.length - 2; i >= 0; i--) {
x = f(xs[i], x);
zs.unshift(x);
}
return zs;
}
select
Source:
function select(path, object) {
return foldl(at, object, path.split(/\./));
}
sinh
Prelude: sinh
Source:
function sinh(x) {
return (Math.exp(x) - Math.exp(-x)) / 2;
}
sort
Prelude: sort
Source:
function sort(xs) {
if (xs.length <= 1) {
return xs;
}
var zs = isString(xs) ? ''.split.call(xs, '') : [].slice.call(xs);
if (isNumber(zs[0])) {
zs.sort(function (a, b) { return a - b; });
} else if (isString(zs[0])) {
zs.sort(function (a, b) { return a.localeCompare(b); });
} else {
zs.sort(compare);
}
return isString(xs) ? zs.join('') : zs;
}
sortBy
Prelude: sortBy
Source:
function sortBy(fn, xs) {
if (xs.length <= 1) {
return xs;
}
var yesItsAString = isString(xs);
var zs = yesItsAString ? ''.split.call(xs, '') : [].slice.call(xs);
zs.sort(fn);
return yesItsAString ? zs.join('') : zs;
}
span
Prelude: span
Source:
function span(p, xs) {
var i = 0;
while (i < xs.length && p(xs[i])) {
i++;
}
return tuple(xs.slice(0, i), xs.slice(i));
}
splitAt
Prelude: splitAt
Source:
function splitAt(n, xs) {
return tuple(take(n, xs), drop(n, xs));
}
tail
Prelude: tail
Source:
function tail(xs) {
switch (typeOf(xs)) {
case 'array':
return [].slice.call(xs, 1);
case 'string':
return "".slice.call(xs, 1);
case 'list':
case 'stream':
return xs.tail();
default:
error(TypeError);
}
}
tails
Prelude: tails
Source:
function tails(xs) {
var result, current, i;
if (isArray(xs)) {
result = [[]];
current = [];
for (i = xs.length - 1; i >= 0; i -= 1) {
current = [xs[i]].concat(current);
result.unshift(current);
}
return result;
}
// TODO the assumption is it's a string now
result = [''];
current = '';
for (i = xs.length - 1; i >= 0; i -= 1) {
current = xs[i] + current;
result.unshift(current);
}
return result;
}
take
Prelude: take
Source:
function take(n, xs) {
switch (typeOf(xs)) {
case 'string':
return "".slice.call(xs, 0, n);
case 'array':
return [].slice.call(xs, 0, n);
case 'list':
case 'stream':
return takeGenerator(n, xs);
default:
error(TypeError);
}
}
takeWhile
Prelude: takeWhile
Source:
function takeWhile(p, xs) {
var i = 0;
while (i < xs.length && p(xs[i])) {
i++;
}
return xs.slice(0, i);
}
transpose
Prelude: transpose
Source:
function transpose(xss) {
if (!isArray(xss)) {
var zss = {};
var ks = Object.keys(xss);
for (var k = 0; k < ks.length; k++) {
zss[xss[ks[k]]] = ks[k];
}
return zss;
}
var j = 0;
var zs = [];
var current;
do {
current = [];
for (var i = 0; i < xss.length; i++) {
if (xss[i][j] !== undefined) {
current.push(xss[i][j]);
}
}
j += 1;
} while (current.length > 0 && zs.push(current));
if (isString(xss[0])) {
zs = map(arrayToString, zs);
}
return zs;
}
union
Prelude: union
Source:
function union(xs, ys) {
var set = new Set();
var zs = [];
var i;
for (i = 0; i < xs.length; i++) {
zs.push(xs[i]);
set.add(xs[i]);
}
for (i = 0; i < ys.length; i++) {
if (!set.has(ys[i])) {
zs.push(ys[i]);
}
}
return zs;
}
Appendix
Coverage of Haskell Prelude
Prelude functions supported in Nodash
- !!
- $
- &&
- *
- **
- +
- ++
- ,
- -
- .
- /
- /=
- :
- <
- <=
- ==
- >
- >=
- ^
- ^^
- abs
- acos
- acosh
- all
- and
- any
- asin
- asinh
- atan
- atanh
- break
- ceiling
- compare
- concat
- concatMap
- const
- cos
- cosh
- curry
- cycle
- div
- divMod
- drop
- either
- elem
- even
- exp
- filter
- flip
- floor
- fmap
- foldl
- foldl1
- foldr
- foldr1
- fst
- gcd
- head
- id
- init
- iterate
- last
- lcm
- length
- lines
- log
- logBase
- lookup
- map
- max
- maximum
- maybe
- min
- minimum
- mod
- negate
- not
- notElem
- odd
- or
- product
- properFraction
- quot
- quotRem
- recip
- rem
- repeat
- replicate
- reverse
- round
- scanl
- scanl1
- scanr
- scanr1
- signum
- sin
- sinh
- snd
- span
- splitAt
- sqrt
- subtract
- sum
- tail
- take
- takeWhile
- tan
- tanh
- truncate
- uncurry
- unlines
- until
- unwords
- words
- zip
- zip3
- zipWith
- zipWith3
- ||
Prelude functions missing from Nodash
- $!
- =<<
- >>
- >>=
- FilePath
- IOError
- appendFile
- asTypeOf
- atan2
- catch
- decodeFloat
- dropWhie
- encodeFloat
- enumFrom
- enumFromThen
- enumFromThenTo
- enumFromTo
- error
- exponent
- fail
- floatDigits
- floatRadix
- floatRange
- fromEnum
- fromInteger
- fromIntegral
- fromRational
- getChar
- getContents
- getLine
- interact
- ioError
- isDenormalized
- isIEEE
- isInfinite
- isNaN
- isNegativeZero
- lex
- mapM
- mapM_
- maxBound
- minBound
- null
- otherwise
- pi
- pitStr
- pred
- print
- putChar
- putStrLn
- read
- readFile
- readIO
- readList
- readLn
- readParen
- reads
- readsPrec
- realToFrac
- return
- scaleFloat
- seq
- sequence
- sequence_
- show
- showChar
- showList
- showParen
- showString
- shows
- showsPrec
- significand
- succ
- toEnum
- toInteger
- toRational
- undefined
- unzip
- unzip3
- userError
- writeFile
Nodash-specific additions
- Either
- Left
- List
- Right
- Stream
- Thunk
- Tuple
- arrayToString
- async
- bool
- catMaybes
- chr
- classOf
- clone
- comparing
- compose2
- curried
- each
- emptyList
- fromLeft
- fromMaybe
- fromRight
- idf
- indexOf
- install
- invoke
- is
- isArguments
- isArray
- isAsciiLetter
- isBoolean
- isDate
- isEmpty
- isFunction
- isInteger
- isJust
- isLeft
- isLetter
- isLower
- isNothing
- isNull
- isNumber
- isNumeric
- isObject
- isRegExp
- isRight
- isString
- isUndefined
- isUpper
- keys
- lazy
- lefts
- listToArray
- listToMaybe
- listToString
- mapMaybe
- match
- maybeToList
- objectToArray
- on
- ord
- partitionEithers
- pipe
- range
- rangeStep
- register
- resolveThunk
- rights
- run
- select
- singleton
- tuple3
- tuple4
- tuplesToObject
- typeOf
- values
abs Prelude: abs
Number → Number
Returns the absolute (positive, non-negative) value of a number.
Example:
abs(9) === 9
abs(-3) === 3
Haskell Definition:
abs x | x >= 0 = x
| x < 0 = -x
Source:
function abs() { [native code] }
acos Prelude: acos
Number → Number
Source:
function acos() { [native code] }
acosh Prelude: acosh
Number → Number
Source:
function acosh(x) {
return Math.log(x + Math.sqrt(x * x - 1));
}
add +ADDplusPLUS Prelude: +
Number → Number → Number
Source:
function add(a, b) {
return a + b;
}
asin Prelude: asin
Number → Number
Source:
function asin() { [native code] }
asinh Prelude: asinh
Number → Number
Source:
function asinh(x) {
if (x === -Infinity) {
return x;
} else {
return Math.log(x + Math.sqrt(x * x + 1));
}
}
atan Prelude: atan
Number → Number
Source:
function atan() { [native code] }
atanh Prelude: atanh
Number → Number
Source:
function atanh(x) {
return Math.log((1 + x) / (1 - x)) / 2;
}
ceiling Prelude: ceiling
Number → Number
ceiling x
returns the least integer not less than x
.
Source:
function ceil() { [native code] }
cos Prelude: cos
Number → Number
Source:
function cos() { [native code] }
cosh Prelude: cosh
Number → Number
Source:
function cosh(x) {
return (Math.exp(x) + Math.exp(-x)) / 2;
}
div Prelude: div
Number → Number
Source:
function div(a, b) {
return Math.floor(a / b);
}
divMod Prelude: divMod
Number → Number → (Number, Number)
Source:
function divMod(a, b) {
return tuple(div(a, b), mod(a, b));
}
even Prelude: even
Number → Bool
Source:
function even(x) {
return (x % 2) === 0;
}
exp Prelude: exp
Number → Number
Source:
function exp() { [native code] }
floor Prelude: floor
Number → Number
floor x
returns the greatest integer not greater than x
.
Source:
function floor() { [native code] }
frac / Prelude: /
Number → Number → Number
Source:
function frac(a, b) {
return a / b;
}
gcd Prelude: gcd
Number → Number → Number
Source:
function gcd(a, b) {
var c;
while (b !== 0) {
c = rem(a, b);
a = b;
b = c;
}
return a;
}
lcm Prelude: lcm
Number → Number → Number
Source:
function lcm(a, b) {
if (a === 0 || b === 0) {
return 0;
}
return Math.abs(quot(a, gcd(a, b)) * b);
}
log Prelude: log
Number → Number
Source:
function log() { [native code] }
logBase Prelude: logBase
Number → Number → Number
Haskell Definition:
logBase x y = log y / log x
Source:
function logBase(a, b) {
return Math.log(a) / Math.log(b);
}
minus -MINUS Prelude: -
Number → Number → Number
Source:
function minus(a, b) {
return a - b;
}
mod Prelude: mod
Number → Number → Number
Source:
function mod(a, b) {
var q = quot(a, b);
var r = rem(a, b);
return signum(r) === -signum(b) ? r + b : r;
}
mul *MULtimesTIMES Prelude: *
Number → Number → Number
Source:
function mul(a, b) {
return a * b;
}
negate Prelude: negate
Number → Number
Source:
function negate(x) {
return -x;
}
odd Prelude: odd
Number → Boolean
Source:
function odd(x) {
return (x % 2) !== 0;
}
pow **^^^ Prelude: ^^
Haskell Definition:
x ** y = exp (log x * y)
Source:
function pow() { [native code] }
properFraction Prelude: properFraction
Number → (Number, Number)
properFraction
takes a real fractional
number x
and returns a pair (n, f)
such that x = n + f
,
and: n
is an integral number with the same sign as x
;
and f
is a fraction with the same type and sign as x
,
and with absolute value less than 1.
Source:
function properFraction(x) {
var num = truncate(x);
return tuple(num, -(num - x));
}
quot Prelude: quot
Number → Number → Number
Source:
function quot(a, b) {
var r = a / b;
return r >= 0 ? Math.floor(r) : Math.ceil(r);
}
quotRem Prelude: quotRem
Number → Number → (Number, Number)
Source:
function quotRem(a, b) {
return tuple(quot(a, b), rem(a, b));
}
recip Prelude: recip
Haskell Definition:
recip = 1 / x
Source:
function recip(x) {
return 1 / x;
}
rem Prelude: rem
Number → Number → Number
Source:
function rem(a, b) {
return a % b;
}
round Prelude: round
Number → Number
round x
returns the nearest integer to x
; the even
integer if x
is equidistant between two integers.
Source:
function round(x) {
var fraction = properFraction(x);
var n = fraction[0];
var m = fraction[1] < 0 ? n - 1 : n + 1;
switch (signum(Math.abs(fraction[1]) - 0.5)) {
case -1:
return n;
case 0:
return n % 2 === 0 ? n : m;
case 1:
return m;
}
}
signum Prelude: signum
Number → Number
Haskell Definition:
signum x | x > 0 = 1
| x == 0 = 0
| x < 0 = -1
Source:
function signum(x) {
if (x > 0) {
return 1;
} else if (x === 0) {
return 0;
}
return -1;
}
sin Prelude: sin
Number → Number
Source:
function sin() { [native code] }
sqrt Prelude: sqrt
Number → Number
Source:
function sqrt() { [native code] }
sub subtract Prelude: subtract
Number → Number
Source:
function sub(a, b) {
return b - a;
}
tan Prelude: tan
Number → Number
Haskell Definition:
tan x = sin x / cos x
Source:
function tan() { [native code] }
tanh Prelude: tanh
Number → Number
Haskell Definition:
tanh x = sinh x / cosh x
Source:
function tanh(x) {
if (x === Infinity) {
return 1;
} else if (x === -Infinity) {
return -1;
} else {
return (Math.exp(x) - Math.exp(-x)) / (Math.exp(x) + Math.exp(-x));
}
}
truncate Prelude: truncate
Number → Number
truncate x
returns the integer nearest x
between zero and x
.
Source:
function truncate(x) {
switch (signum(x)) {
case -1:
return Math.ceil(x);
case 1:
return Math.floor(x);
}
return 0;
}
install
Source:
function install(mountpoint) {
var options = arguments[1];
var nodashObject = Nodash;
var prefix = '';
var postfix = '';
if (!mountpoint) {
return Nodash;
}
if (options) {
nodashObject = makeNodash(options);
}
if (isArray(mountpoint)) {
if (isString(mountpoint[0])) {
prefix = [].shift.call(mountpoint);
}
if (isString(mountpoint[1])) {
postfix = mountpoint[1];
}
mountpoint = mountpoint[0] || {};
}
each(function (func, name) {
if (name[0] === '_') {
return;
}
var key = prefix + name + postfix;
if (!(key in mountpoint)) {
mountpoint[key] = func;
}
}, nodashObject);
return mountpoint;
}
register
Source:
function register() {
var args = [].slice.call(arguments);
if (arguments.length === 1) {
switch (typeof args[0]) {
case 'object':
if (Array.isArray(args[0])) {
registerInjected(args[0].slice());
} else {
registerLib(args[0]);
}
break;
case 'function':
register(args[0].call(Nodash));
break;
}
return;
}
var func = args.pop();
var aliases = [];
args.forEach(function (arg) {
[].push.apply(aliases, arg.split(/ +/));
});
var name = null;
for (var i = 0; i < aliases.length; i += 1) {
if (/^[a-z0-9]+$/i.test(aliases[i])) {
name = aliases[i];
break;
}
}
__metadata[name] = {
aliases: aliases,
definition: func
};
if (!/^[A-Z]/.test(name)) {
func = curried(func);
}
aliases.forEach(function (alias) {
Nodash[alias] = func;
});
}
Pattern
match
MatchSpec → Any → MatchResult
match(spec, value)
matches value
against the spec
, returning
what was captured in the spec.
A MatchSpec
is an array of arrays. Every array in the spec
must have two elements: [ 0: Pattern, 1: Result ]
. The first
Pattern
that matches value
will yield the associated Result
.
If Result
is a function it will be invoked with an object of
all captured variables in the Pattern
and the result will be returned,
otherwise the Result
itself.
Example:
var matchJohn = match([
[ { firstName: 'John' }, 'John is a fine name' ],
[ { firstName: '$firstName' },
function (result) {
return result.$firstName + ' is also a fine name'; } ]
]);
console.log(matchJohn({ firstName: 'John', lastName: 'Doe' }));
// → 'John is a fine name'
console.log(matchJohn({ firstName: 'Johnathan', lastName: 'X' }));
// → 'Jonathan is also a fine name'
Source:
function match(pattern, arg) {
for (var i = 0; i < pattern.length; i += 1) {
var result = {};
var p = pattern[i];
if (matchR(p[0], arg, result)) {
if (typeof p[1] === 'function') {
return p[1](result);
}
return p[1];
}
}
}
Object
each
Source:
function each(f, xs) {
if (is(List, xs)) {
while (!xs.isEmpty()) {
f(xs.head());
xs = xs.tail();
}
} else if (isArray(xs) || isString(xs)) {
for (var i = 0; i < xs.length; i++) {
f(xs[i], i);
}
} else if (isObject(xs)) {
var ks = Object.keys(xs);
for (var j = 0; j < ks.length; j += 1) {
f(xs[ks[j]], ks[j]);
}
}
}
keys
Source:
function keys() { [native code] }
values
Source:
function values(object) {
var values = [];
each(function (value) {
values.push(value);
}, object);
return values;
}
Stream
cycle
Prelude: cycle
Source:
function cycle(xs) {
if (isArray(xs)) {
xs = lazy(xs);
}
function generator(ys) {
if (ys.isEmpty()) {
ys = xs;
}
return function () {
return tuple(ys.head(), generator(ys.tail()));
};
}
return new Stream(generator(xs));
}
iterate
Prelude: iterate
Source:
function iterate(f, seed) {
function generator(seed) {
return function () {
var newSeed = f(seed);
return tuple(seed, generator(newSeed));
};
}
return new Stream(generator(seed));
}
repeat
Prelude: repeat
Source:
function repeat(x) {
function generator() {
return tuple(x, generator);
}
return new Stream(generator);
}
Stream
stream
new Stream(generator)
Streams are immutable, lazily evaluated, infinite Lists.
Methods:
- .head() → a
- Extract the first element of this stream.
- .tail() → List a
- Extract the rest of the stream.
Source:
function Stream(generator) {
if (!(this instanceof Stream)) {
return new Stream(generator);
}
var thunk = new Thunk(generator);
var self = this;
this.head = function () {
var value = thunk.get().fst();
self.head = idf(value);
return value;
};
this.tail = function () {
var value = thunk.get().snd();
switch (typeOf(value)) {
case 'list':
case 'stream':
break;
case 'function':
value = new Stream(value);
break;
default:
error(TypeError);
}
self.tail = idf(value);
return value;
};
}
until
Prelude: until
Source:
function until(p, f, v) {
while (!p(v)) {
v = f(v);
}
return v;
}
String
lines
Prelude: lines
Source:
function lines(string) {
var result = string.split(/\n/);
if (result[result.length - 1].length === 0) {
delete result[result.length - 1];
}
return result;
}
unlines
Prelude: unlines
Source:
function unlines(lines) {
return lines.join('\n');
}
unwords
Prelude: unwords
Source:
function unwords(words) {
return words.join(' ');
}
words
Prelude: words
Source:
function words(string) {
return string.split(/[\n\r\v\t ]/);
}
Tuple
fst
Prelude: fst
(a, b) → b
Extract the first component of a pair.
Tuples also have a fst()
method which does the same thing,
but this function is exposing that method as a function.
Haskell Definition:
fst (a, _) = a
Source:
function fst(t) {
return t.fst();
}
objectToArray
Object → [(String, Any)]
Turns an object into an associative list of tuples.
The objects keys are the first components of the tuples,
the values the second components.
eq( objectToArray({ a: 17, b: 20 }), [ tuple('a', 17), tuple('b', 20) ]) === true
Source:
function objectToArray(obj) {
var arr = [];
each(function (val, key) {
arr.push(new Tuple(key, val));
}, obj);
return arr;
}
snd
Prelude: snd
(a, b) → b
Extract the second component of a pair.
Tuples also have a fst()
method which does the same thing,
but this function is exposing that method as a function.
Haskell Definition:
snd (_, b) = b
Source:
function snd(t) {
return t.snd();
}
Tuple
new Tuple(first, second) :: a → b → (a, b)
Tuples are immutable pairs of a first and a second components.
Methods:
- .fst() → a
- Retrieves the first component of this tuple.
- .snd() → b
- Retrieves the second component of this tuple.
Example:
var t = new Tuple(4711, 8080);
console.log(t.fst()); // 4711
console.log(t.snd()); // 8080
fst
and snd
are functional forms of .fst()
and .snd()
.
tuple
is a convenience method for omitting new
:
var t = tuple(4711, 8080);
console.log(fst(t)); // 4711
console.log(snd(t)); // 8080
var extractFirsts = map(fst);
console.log(extractFirsts([
tuple(4711, 8080),
tuple(3000, 4444)
])); // [ 4711, 3000 ]
Haskell Definition:
data Tuple a b = Tuple { fst :: a, snd :: b }
Source:
function Tuple(fst, snd) {
if (!(this instanceof Tuple)) {
return new Tuple(fst, snd);
}
this.fst = idf(fst);
this.snd = idf(snd);
freeze(this);
}
tuple
,
Prelude: ,
Source:
function tuple(first, second) {
return new Tuple(first, second);
}
tuple3
,,
Source:
function tuple3(first, second, third) {
return tuple(first, tuple(second, third));
}
tuple4
,,,
Source:
function tuple4(first, second, third, fourth) {
return tuple3(first, second, tuple(third, fourth));
}
tuplesToObject
[(String, Any)] → Object
Turns an associative list of tuples into an object.
The first components of the tuples are the keys,
the second components the corresponding values.
Example:
eq( tuplesToObject([ tuple('a', 2), tuple('b', 3) ]), { a: 2, b: 3 }) === true
Source:
function tuplesToObject(xs) {
var obj = {};
each(function (t) {
obj[t.fst()] = t.snd();
}, xs);
return obj;
}
Type
classOf
Any → String
Determines the property of the internal
[[Class]]
attribute,
normalized to lower case.
Example:
classOf(new Date()) === 'date'
classOf(null) === 'null'
classOf([]) === 'array'
function f() {
return classOf(arguments)
}
f() === 'arguments'
Source:
function classOf(thing) {
var exactType = toString.call(thing);
return exactType.slice(8, exactType.length - 1).toLowerCase();
}
is
Source:
function is(type, thing) {
return thing instanceof type;
}
isArguments
Any → Boolean
Source:
function isArguments(thing) {
return toString.call(thing) === '[object Arguments]';
}
isArray
Any → Boolean
Determines whether something is an array or not.
This is exactly the same as Array.isArray
.
Example:
isArray([]) === true
isArray({}) === false
isArray(new Array(3)) === true
isArray(undefined) === false
isArray(3) === false
Source:
function isArray() { [native code] }
isBoolean
Any → Boolean
Returns true
if the argument is a boolean value, otherwise false
.
Example:
isBoolean(true) === true
isBoolean(false) === false
isBoolean({}) === false
isBoolean(undefined) === false
isBoolean(0) === false
isBoolean(1) === false
isBoolean("true") === false
Source:
function isBoolean(thing) {
return typeof thing === 'boolean';
}
isDate
Any → Boolean
Source:
function isDate(thing) {
return toString.call(thing) === '[object Date]';
}
isEmpty
null_
Prelude: null
Any → Boolean
Source:
function isEmpty(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs.length === 0;
case 'list':
case 'stream':
return xs.isEmpty();
default:
for (var _ in xs) {
return false;
}
return true;
}
}
isFunction
Any → Boolean
Source:
function isFunction(thing) {
return typeof thing === 'function';
}
isInteger
Any → Boolean
Returns true
is the argument is an integral number.
Numbers in JavaScript are floating point values and there is no proper integer type.
This function can be used to check whether a given number could be cast to an
integer without truncating.
isInteger(7) === true
isInteger(7.0) === true
isInteger(7.3) === false
Source:
function isInteger(thing) {
return isNumber(thing) && !isNaN(thing) &&
thing - Math.floor(thing) === 0 &&
thing !== Infinity && thing !== -Infinity;
}
isNull
Any → Boolean
Source:
function isNull(thing) {
return toString.call(thing) === '[object Null]';
}
isNumber
Source:
function isNumber(thing) {
return typeof thing === 'number';
}
isObject
Source:
function isObject(thing) {
return typeof thing === 'object' &&
thing !== null && !Array.isArray(thing);
}
isRegExp
Any → Boolean
Returns true
is the argument is a regular expression object.
Example:
isRegExp(/a+/) === true
isRegExp("a+") === false
isRegExp(new RegExp("a+")) === true
Source:
function isRegExp(thing) {
return toString.call(thing) === '[object RegExp]';
}
isString
Source:
function isString(thing) {
return typeof thing === 'string' || toString.call(thing) === '[object String]';
}
isUndefined
Source:
function isUndefined(thing) {
return typeof thing === 'undefined';
}
typeOf
Something → String
Returns the type of the given thing as a String.
This differs from JavaScripts typeof
in the way that it
distinguishes null
, object
, and array
and identifies
NaN
as not-a-number
(Infinity
and -Infinity
are both
reported as number
). Also it knows some types native to
nodash, such as list
, stream
, and tuple
.
The possible return values are:
boolean
for true
and false
,
number
for a number which is not NaN
,
string
for a JavaScript string,
function
for a JavaScript function,
not-a-number
if isNaN
would return true,
null
for null
,
undefined
for undefined
,
array
is Array.isArray
would return true,
list
if it is a List,
stream
if it is a Stream,
tuple
if it is a Tuple,
object
if it is an object but neither null
nor an array
or any of the previously mentioned object types (e.g. tuple
)
In ECMAScript 2015 (ES6) this function may also return symbol
for Symbols.
Source:
function typeOf(thing) {
var type = typeof thing;
switch (type) {
case 'number':
return isNaN(thing) ? 'not-a-number' : 'number';
case 'object':
var exactType = classOf(thing);
if (exactType === 'object' && thing.constructor && thing.constructor.__type) {
return thing.constructor.__type;
}
return exactType;
default:
return type;
}
}
(unclassified)
any
Prelude: any
Source:
function any(p, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
return true;
}
}
return false;
}
append
++
Prelude: ++
Source:
function append(xs, ys) {
switch (typeOf(xs)) {
case 'list':
return appendList(xs, ys);
case 'string':
return xs + ys;
case 'array':
return [].concat.call(xs, ys);
default:
error(TypeError);
}
}
at
!!AT
Prelude: !!
Source:
function at(xs, ix) {
if (xs === undefined) {
return xs;
}
return xs[ix];
}
break
break_
Prelude: break
Source:
function break(p, xs) {
var i = 0;
while (i < xs.length && !p(xs[i])) {
i++;
}
return tuple(xs.slice(0, i), xs.slice(i));
}
clone
Source:
function clone(thing) {
if (typeof thing === 'object') {
if (thing === null) {
return null;
}
return map(clone, thing);
}
return thing;
}
compare
Prelude: compare
Source:
function compare(a, b) {
switch (typeof a) {
case 'string':
return a.localeCompare(b);
case 'object':
if (isFunction(a.compareTo)) {
return a.compareTo(b);
} else if (isArray(a)) {
for (var i = 0; i < Math.min(a.length, b.length); i++) {
var r = compare(a[i], b[i]);
if (r !== 0) {
return r;
}
}
return 0;
}
return a.toString().localeCompare(b.toString());
case 'number':
return signum(a - b);
}
return undefined;
}
comparing
Source:
function comparing(f, a, b) {
return compare(f(a), f(b));
}
concat
Prelude: concat
Source:
function concat(xs) {
if (isString(xs[0])) {
return xs.join('');
}
var zs = [];
var ks = Object.keys(xs);
for (var i = 0; i < ks.length; i++) {
[].push.apply(zs, xs[ks[i]]);
}
return zs;
}
concatMap
Prelude: concatMap
Source:
var concatMap = /* this is a composed function */
cons
:
Prelude: :
Source:
function cons(x, xs) {
switch (typeOf(xs)) {
case 'array':
var zs = [].slice.call(xs);
zs.unshift(x);
return zs;
case 'string':
return x + xs;
case 'list':
return new List(x, xs);
case 'stream':
return new Stream(function () {
return tuple(x, xs);
});
default:
error(TypeError);
}
}
curried
Source:
function curried(fn) {
return funcs[fn.length](fn);
}
delete
delete_
Prelude: delete
Source:
function delete(x, xs) {
var i = xs.indexOf(x);
if (i >= 0) {
return append(xs.slice(0,i), xs.slice(i+1));
}
return xs;
}
deleteBy
Prelude: deleteBy
Source:
function deleteBy(p, x, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(x, xs[i])) {
return append(xs.slice(0,i), xs.slice(i+1));
}
}
return xs;
}
difference
\\
Prelude: \\
Source:
function difference(xs, ys) {
var set = new Set();
var i;
for (i = 0; i < ys.length; i++) {
set.add(ys[i]);
}
var zs = [];
for (i = 0; i < xs.length; i++) {
if (!set.has(xs[i])) {
zs.push(xs[i]);
}
}
return isString(xs) ? arrayToString(zs) : zs;
}
drop
Prelude: drop
Source:
function drop(n, xs) {
return xs.slice(n);
}
dropWhile
Prelude: dropWhile
Source:
function dropWhile(p, xs) {
var i = 0;
while (i < xs.length && p(xs[i])) {
i++;
}
return xs.slice(i);
}
either
Prelude: either
Source:
function either(afun, bfun, value) {
if (is(Left, value)) {
return afun(value.value());
} else if (is(Right, value)) {
return bfun(value.value());
} else {
fail();
}
}
elem
Prelude: elem
Source:
function elem(x, xs) {
for (var i = 0; i < xs.length; i++) {
if (eq(xs[i], x)) {
return true;
}
}
return false;
}
elemIndex
Prelude: elemIndex
Source:
function elemIndex(x, xs) {
return findIndex(eq(x), xs);
}
elemIndices
Prelude: elemIndices
Source:
function elemIndices(x, xs) {
return findIndices(eq(x), xs);
}
emptyList
Source:
function emptyList() {
return emptyList;
}
eq
==EQ
Prelude: ==
Source:
function eq(a, b) {
if (a === b) {
return true;
}
var ta = typeOf(a);
var tb = typeOf(b);
if (ta !== tb) {
return false;
}
switch (ta) {
case 'tuple':
return eq(a.fst(), b.fst()) && eq(a.snd(), b.snd());
case 'list':
return eq(a.head(), b.head()) && eq(a.tail(), b.tail());
case 'array':
case 'object':
if (a.constructor !== b.constructor) {
return false;
}
var k = union(Object.keys(a), Object.keys(b));
for (var i = 0; i < k.length; i++) {
if (!eq(a[k[i]], b[k[i]])) {
return false;
}
}
return true;
}
return false;
}
filter
Prelude: filter
Source:
function filter(p, xs) {
var ys;
switch (typeOf(xs)) {
case 'array':
case 'string':
ys = [];
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
ys.push(xs[i]);
}
}
return isString(xs) ? arrayToString(ys) : ys;
default:
ys = {};
var ks = Object.keys(xs);
for (var j = 0; j < ks.length; j++) {
if (p(xs[ks[j]])) {
ys[ks[j]] = xs[ks[j]];
}
}
return ys;
}
}
find
Prelude: find
Source:
function find(p, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
return xs[i];
}
}
return null;
}
findIndex
Prelude: findIndex
Source:
function findIndex(p, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
return i;
}
}
return null;
}
findIndices
Prelude: findIndices
Source:
function findIndices(p, xs) {
var zs = [];
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
zs.push(i);
}
}
return zs;
}
foldl1
foldl1'
Prelude: foldl1'
Source:
function foldl1(f, xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
var x = xs[0];
for (var i = 1; i < xs.length; i += 1) {
x = f(xs[i], x);
}
return x;
}
}
foldr1
Prelude: foldr1
Source:
function foldr1(f, xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
var x = xs[xs.length - 1];
for (var i = xs.length - 2; i >= 0; i -= 1) {
x = f(xs[i], x);
}
return x;
}
}
fromLeft
Source:
function fromLeft(thing) {
if (is(Left, thing)) {
return thing.value();
}
fail();
}
fromMaybe
Source:
function fromMaybe(def, maybe) {
if (isJust(maybe)) {
return maybe;
}
return def;
}
fromRight
Source:
function fromRight(thing) {
if (is(Right, thing)) {
return thing.value();
}
fail();
}
group
Prelude: group
Source:
var group = /* this is a composed function */
groupBy
Prelude: groupBy
Source:
function groupBy(p, xs) {
if (xs.length === 0) {
return [];
}
var zs = [];
var current = [xs[0]];
var last = xs[0];
for (var i = 1; i < xs.length; i++) {
if (p(xs[i], last)) {
current.push(xs[i]);
} else {
zs.push(current);
current = [xs[i]];
}
last = xs[i];
}
zs.push(current);
return isString(xs) ? map(arrayToString, zs) : zs;
}
gt
>GT
Prelude: >
Source:
function gt(a, b) {
return compare(a, b) > 0;
}
gte
>=GTE
Prelude: >=
Source:
function gte(a, b) {
return compare(a, b) >= 0;
}
head
Prelude: head
Source:
function head(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs[0];
case 'list':
case 'stream':
return xs.head();
default:
error(TypeError);
}
}
indexOf
Source:
function indexOf(word, string) {
'use strict';
var m = 0;
var i = 0;
var table = [];
var pos = 2;
var cnd = 0;
table[0] = -1;
table[1] = 0;
// build the table for KMP. This takes `O(word.length)` steps.
while (pos < word.length) {
if (word[pos - 1] == word[cnd]) {
cnd = cnd + 1;
table[pos] = cnd;
pos = pos + 1;
} else if (cnd > 0) {
cnd = table[cnd];
} else {
table[pos] = 0;
pos = pos + 1;
}
}
// scan the string. This takes `O(string.length)` steps.
while (m + i < string.length) {
if (word[i] == string[m + i]) {
if (i == word.length - 1) {
return m;
}
i = i + 1;
} else {
if (table[i] > -1) {
m = m + i - table[i];
i = table[i];
} else {
i = 0;
m = m + 1;
}
}
}
// Returns -1 if the subsequence was not found in the sequence.
return -1;
}
init
Prelude: init
Source:
function init(xs) {
if (isString(xs)) {
return xs.slice(0, xs.length - 1);
}
return [].slice.call(xs, 0, xs.length - 1);
}
inits
Prelude: inits
Source:
function inits(xs) {
var result, current, i, length;
if (isArray(xs)) {
result = [[]];
current = [];
length = xs.length;
for (i = 0; i < length; i += 1) {
current = current.concat(xs[i]);
result.push(current);
}
return result;
}
// TODO the assumption is it's a string now
result = [''];
current = '';
length = xs.length;
for (i = 0; i < length; i += 1) {
current += xs[i];
result.push(current);
}
return result;
}
insert
Prelude: insert
Source:
var insert = /* this is a composed function */
insertBy
Prelude: insertBy
Source:
function insertBy(f, x, xs) {
for (var i = 0; i < xs.length; i++) {
if (f(x, xs[i]) <= 0) {
return concat([xs.slice(0,i), x, xs.slice(i)]);
}
}
return append(xs, x);
}
intercalate
Prelude: intercalate
Source:
function intercalate(x, xs) {
return concat(intersperse(x, xs));
}
intersect
Prelude: intersect
Source:
function intersect(xs, ys) {
var set = new Set();
var zs = [];
var i;
for (i = 0; i < ys.length; i++) {
set.add(ys[i]);
}
for (i = 0; i < xs.length; i++) {
if (set.has(xs[i])) {
zs.push(xs[i]);
}
}
return zs;
}
intersperse
Prelude: intersperse
Source:
function intersperse(x, xs) {
if (xs.length === 0) {
return [];
}
var z = [xs[0]];
for (var i = 1; i < xs.length; i++) {
z.push(x);
z.push(xs[i]);
}
return z;
}
last
Prelude: last
Source:
function last(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs[xs.length - 1];
case 'list':
if (xs.isEmpty()) {
return undefined;
}
for (var ts = xs.tail(); !ts.isEmpty();) {
xs = xs.tail();
ts = xs.tail();
}
return xs.head();
default:
error(TypeError);
}
}
length
Prelude: length
Source:
function length(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs.length;
case 'list':
var count = 0;
while (!xs.isEmpty()) {
count += 1;
xs = xs.tail();
}
return count;
case 'stream':
return Infinity;
case 'object':
return Object.keys(xs).length;
default:
error(TypeError);
}
}
listToMaybe
Source:
function listToMaybe(xs) {
if (is(List, xs)) {
return xs.isEmpty() ? null : xs.head();
}
throw new TypeError();
}
lookup
Prelude: lookup
Source:
function lookup(x, xs) {
if (isArray(xs)) {
for (var i = 0; i < xs.length; i++) {
if (xs[i] && eq(xs[i][0], x)) {
return xs[i][1];
}
}
}
return xs[x];
}
lt
<LT
Prelude: <
Source:
function lt(a, b) {
return compare(a, b) < 0;
}
lte
<=LTE
Prelude: <=
Source:
function lte(a, b) {
return compare(a, b) <= 0;
}
map
fmap
Prelude: fmap
Source:
function map(f, xs) {
var i, ys;
switch (typeOf(xs)) {
case 'array':
return mapArray(f, xs);
case 'string':
return arrayToString(mapArray(f, xs));
case 'list':
if (xs.isEmpty()) {
return xs;
}
/* falls through */
case 'stream':
return new List(lazy(function () {
return f(xs.head());
}), lazy(function () {
return map(f, xs.tail());
}));
case 'object':
ys = {};
var ks = Object.keys(xs);
for (var j = 0; j < ks.length; j += 1) {
ys[ks[j]] = f(xs[ks[j]], ks[j]);
}
return ys;
}
}
max
Prelude: max
Source:
function max(a, b) {
return compare(a, b) > 0 ? a : b;
}
maximum
Prelude: maximum
Source:
var maximum = /* this is a composed function */
maximumBy
Prelude: maximumBy
Source:
function maximumBy(f, xs) {
return foldl1(function (a, b) {
if (f(a, b) > 0) {
return a;
}
return b;
}, xs);
}
min
Prelude: min
Source:
function min(a, b) {
return compare(a, b) < 0 ? a : b;
}
minimum
Prelude: minimum
Source:
var minimum = /* this is a composed function */
minimumBy
Prelude: minimumBy
Source:
function minimumBy(f, xs) {
return foldl1(function (a, b) {
if (f(a, b) < 0) {
return a;
}
return b;
}, xs);
}
neq
/=!=<>NEQ
Prelude: /=
Source:
function neq(a, b) {
return !eq(a, b);
}
notElem
Prelude: notElem
Source:
function notElem(x, xs) {
for (var i = 0; i < xs.length; i++) {
if (eq(xs[i], x)) {
return false;
}
}
return true;
}
nub
Prelude: nub
Source:
function nub(xs) {
var set = new Set();
var zs = [];
for (var i = 0; i < xs.length; i++) {
if (!set.has(xs[i])) {
zs.push(xs[i]);
set.add(xs[i]);
}
}
return zs;
}
or
Prelude: or
Source:
var or = /* this is a composed function */
partition
Prelude: partition
Source:
function _partition(p, xs) {
var as = [];
var bs = [];
for (var i = 0; i < xs.length; i++) {
(p(xs[i]) ? as : bs).push(xs[i]);
}
if (isString(xs)) {
return tuple(arrayToString(as), arrayToString(bs));
}
return tuple(as, bs);
}
product
Prelude: product
Source:
var product = /* this is a composed function */
replicate
Prelude: replicate
Source:
function replicate(n, x) {
var xs = [];
for (var i = 0; i < n; i++) {
xs.push(x);
}
return xs;
}
reverse
Prelude: reverse
Source:
function reverse(xs) {
var zs = isString(xs) ? ''.split.call(xs, '') : [].slice.call(xs);
zs.reverse();
return isString(xs) ? zs.join('') : zs;
}
scanl
Prelude: scanl
Source:
function scanl(f, x, xs) {
var zs = [x];
for (var i = 0; i < xs.length; i++) {
x = f(x, xs[i]);
zs.push(x);
}
return zs;
}
scanl1
Prelude: scanl1
Source:
function scanl1(f, xs) {
var x = xs[0];
var zs = [x];
for (var i = 1; i < xs.length; i++) {
x = f(x, xs[i]);
zs.push(x);
}
return zs;
}
scanr
Prelude: scanr
Source:
function scanr(f, x, xs) {
var zs = [x];
for (var i = xs.length - 1; i >= 0; i--) {
x = f(xs[i], x);
zs.unshift(x);
}
return zs;
}
scanr1
Prelude: scanr1
Source:
function scanr1(f, xs) {
var x = xs[xs.length - 1];
var zs = [x];
for (var i = xs.length - 2; i >= 0; i--) {
x = f(xs[i], x);
zs.unshift(x);
}
return zs;
}
select
Source:
function select(path, object) {
return foldl(at, object, path.split(/\./));
}
sinh
Prelude: sinh
Source:
function sinh(x) {
return (Math.exp(x) - Math.exp(-x)) / 2;
}
sort
Prelude: sort
Source:
function sort(xs) {
if (xs.length <= 1) {
return xs;
}
var zs = isString(xs) ? ''.split.call(xs, '') : [].slice.call(xs);
if (isNumber(zs[0])) {
zs.sort(function (a, b) { return a - b; });
} else if (isString(zs[0])) {
zs.sort(function (a, b) { return a.localeCompare(b); });
} else {
zs.sort(compare);
}
return isString(xs) ? zs.join('') : zs;
}
sortBy
Prelude: sortBy
Source:
function sortBy(fn, xs) {
if (xs.length <= 1) {
return xs;
}
var yesItsAString = isString(xs);
var zs = yesItsAString ? ''.split.call(xs, '') : [].slice.call(xs);
zs.sort(fn);
return yesItsAString ? zs.join('') : zs;
}
span
Prelude: span
Source:
function span(p, xs) {
var i = 0;
while (i < xs.length && p(xs[i])) {
i++;
}
return tuple(xs.slice(0, i), xs.slice(i));
}
splitAt
Prelude: splitAt
Source:
function splitAt(n, xs) {
return tuple(take(n, xs), drop(n, xs));
}
tail
Prelude: tail
Source:
function tail(xs) {
switch (typeOf(xs)) {
case 'array':
return [].slice.call(xs, 1);
case 'string':
return "".slice.call(xs, 1);
case 'list':
case 'stream':
return xs.tail();
default:
error(TypeError);
}
}
tails
Prelude: tails
Source:
function tails(xs) {
var result, current, i;
if (isArray(xs)) {
result = [[]];
current = [];
for (i = xs.length - 1; i >= 0; i -= 1) {
current = [xs[i]].concat(current);
result.unshift(current);
}
return result;
}
// TODO the assumption is it's a string now
result = [''];
current = '';
for (i = xs.length - 1; i >= 0; i -= 1) {
current = xs[i] + current;
result.unshift(current);
}
return result;
}
take
Prelude: take
Source:
function take(n, xs) {
switch (typeOf(xs)) {
case 'string':
return "".slice.call(xs, 0, n);
case 'array':
return [].slice.call(xs, 0, n);
case 'list':
case 'stream':
return takeGenerator(n, xs);
default:
error(TypeError);
}
}
takeWhile
Prelude: takeWhile
Source:
function takeWhile(p, xs) {
var i = 0;
while (i < xs.length && p(xs[i])) {
i++;
}
return xs.slice(0, i);
}
transpose
Prelude: transpose
Source:
function transpose(xss) {
if (!isArray(xss)) {
var zss = {};
var ks = Object.keys(xss);
for (var k = 0; k < ks.length; k++) {
zss[xss[ks[k]]] = ks[k];
}
return zss;
}
var j = 0;
var zs = [];
var current;
do {
current = [];
for (var i = 0; i < xss.length; i++) {
if (xss[i][j] !== undefined) {
current.push(xss[i][j]);
}
}
j += 1;
} while (current.length > 0 && zs.push(current));
if (isString(xss[0])) {
zs = map(arrayToString, zs);
}
return zs;
}
union
Prelude: union
Source:
function union(xs, ys) {
var set = new Set();
var zs = [];
var i;
for (i = 0; i < xs.length; i++) {
zs.push(xs[i]);
set.add(xs[i]);
}
for (i = 0; i < ys.length; i++) {
if (!set.has(ys[i])) {
zs.push(ys[i]);
}
}
return zs;
}
Appendix
Coverage of Haskell Prelude
Prelude functions supported in Nodash
- !!
- $
- &&
- *
- **
- +
- ++
- ,
- -
- .
- /
- /=
- :
- <
- <=
- ==
- >
- >=
- ^
- ^^
- abs
- acos
- acosh
- all
- and
- any
- asin
- asinh
- atan
- atanh
- break
- ceiling
- compare
- concat
- concatMap
- const
- cos
- cosh
- curry
- cycle
- div
- divMod
- drop
- either
- elem
- even
- exp
- filter
- flip
- floor
- fmap
- foldl
- foldl1
- foldr
- foldr1
- fst
- gcd
- head
- id
- init
- iterate
- last
- lcm
- length
- lines
- log
- logBase
- lookup
- map
- max
- maximum
- maybe
- min
- minimum
- mod
- negate
- not
- notElem
- odd
- or
- product
- properFraction
- quot
- quotRem
- recip
- rem
- repeat
- replicate
- reverse
- round
- scanl
- scanl1
- scanr
- scanr1
- signum
- sin
- sinh
- snd
- span
- splitAt
- sqrt
- subtract
- sum
- tail
- take
- takeWhile
- tan
- tanh
- truncate
- uncurry
- unlines
- until
- unwords
- words
- zip
- zip3
- zipWith
- zipWith3
- ||
Prelude functions missing from Nodash
- $!
- =<<
- >>
- >>=
- FilePath
- IOError
- appendFile
- asTypeOf
- atan2
- catch
- decodeFloat
- dropWhie
- encodeFloat
- enumFrom
- enumFromThen
- enumFromThenTo
- enumFromTo
- error
- exponent
- fail
- floatDigits
- floatRadix
- floatRange
- fromEnum
- fromInteger
- fromIntegral
- fromRational
- getChar
- getContents
- getLine
- interact
- ioError
- isDenormalized
- isIEEE
- isInfinite
- isNaN
- isNegativeZero
- lex
- mapM
- mapM_
- maxBound
- minBound
- null
- otherwise
- pi
- pitStr
- pred
- print
- putChar
- putStrLn
- read
- readFile
- readIO
- readList
- readLn
- readParen
- reads
- readsPrec
- realToFrac
- return
- scaleFloat
- seq
- sequence
- sequence_
- show
- showChar
- showList
- showParen
- showString
- shows
- showsPrec
- significand
- succ
- toEnum
- toInteger
- toRational
- undefined
- unzip
- unzip3
- userError
- writeFile
Nodash-specific additions
- Either
- Left
- List
- Right
- Stream
- Thunk
- Tuple
- arrayToString
- async
- bool
- catMaybes
- chr
- classOf
- clone
- comparing
- compose2
- curried
- each
- emptyList
- fromLeft
- fromMaybe
- fromRight
- idf
- indexOf
- install
- invoke
- is
- isArguments
- isArray
- isAsciiLetter
- isBoolean
- isDate
- isEmpty
- isFunction
- isInteger
- isJust
- isLeft
- isLetter
- isLower
- isNothing
- isNull
- isNumber
- isNumeric
- isObject
- isRegExp
- isRight
- isString
- isUndefined
- isUpper
- keys
- lazy
- lefts
- listToArray
- listToMaybe
- listToString
- mapMaybe
- match
- maybeToList
- objectToArray
- on
- ord
- partitionEithers
- pipe
- range
- rangeStep
- register
- resolveThunk
- rights
- run
- select
- singleton
- tuple3
- tuple4
- tuplesToObject
- typeOf
- values
match
MatchSpec → Any → MatchResult
match(spec, value)
matches value
against the spec
, returning
what was captured in the spec.
A MatchSpec
is an array of arrays. Every array in the spec
must have two elements: [ 0: Pattern, 1: Result ]
. The first
Pattern
that matches value
will yield the associated Result
.
If Result
is a function it will be invoked with an object of
all captured variables in the Pattern
and the result will be returned,
otherwise the Result
itself.
Example:
var matchJohn = match([
[ { firstName: 'John' }, 'John is a fine name' ],
[ { firstName: '$firstName' },
function (result) {
return result.$firstName + ' is also a fine name'; } ]
]);
console.log(matchJohn({ firstName: 'John', lastName: 'Doe' }));
// → 'John is a fine name'
console.log(matchJohn({ firstName: 'Johnathan', lastName: 'X' }));
// → 'Jonathan is also a fine name'
Source:
function match(pattern, arg) {
for (var i = 0; i < pattern.length; i += 1) {
var result = {};
var p = pattern[i];
if (matchR(p[0], arg, result)) {
if (typeof p[1] === 'function') {
return p[1](result);
}
return p[1];
}
}
}
each
Source:
function each(f, xs) {
if (is(List, xs)) {
while (!xs.isEmpty()) {
f(xs.head());
xs = xs.tail();
}
} else if (isArray(xs) || isString(xs)) {
for (var i = 0; i < xs.length; i++) {
f(xs[i], i);
}
} else if (isObject(xs)) {
var ks = Object.keys(xs);
for (var j = 0; j < ks.length; j += 1) {
f(xs[ks[j]], ks[j]);
}
}
}
keys
Source:
function keys() { [native code] }
values
Source:
function values(object) {
var values = [];
each(function (value) {
values.push(value);
}, object);
return values;
}
Stream
cycle
Prelude: cycle
Source:
function cycle(xs) {
if (isArray(xs)) {
xs = lazy(xs);
}
function generator(ys) {
if (ys.isEmpty()) {
ys = xs;
}
return function () {
return tuple(ys.head(), generator(ys.tail()));
};
}
return new Stream(generator(xs));
}
iterate
Prelude: iterate
Source:
function iterate(f, seed) {
function generator(seed) {
return function () {
var newSeed = f(seed);
return tuple(seed, generator(newSeed));
};
}
return new Stream(generator(seed));
}
repeat
Prelude: repeat
Source:
function repeat(x) {
function generator() {
return tuple(x, generator);
}
return new Stream(generator);
}
Stream
stream
new Stream(generator)
Streams are immutable, lazily evaluated, infinite Lists.
Methods:
- .head() → a
- Extract the first element of this stream.
- .tail() → List a
- Extract the rest of the stream.
Source:
function Stream(generator) {
if (!(this instanceof Stream)) {
return new Stream(generator);
}
var thunk = new Thunk(generator);
var self = this;
this.head = function () {
var value = thunk.get().fst();
self.head = idf(value);
return value;
};
this.tail = function () {
var value = thunk.get().snd();
switch (typeOf(value)) {
case 'list':
case 'stream':
break;
case 'function':
value = new Stream(value);
break;
default:
error(TypeError);
}
self.tail = idf(value);
return value;
};
}
until
Prelude: until
Source:
function until(p, f, v) {
while (!p(v)) {
v = f(v);
}
return v;
}
String
lines
Prelude: lines
Source:
function lines(string) {
var result = string.split(/\n/);
if (result[result.length - 1].length === 0) {
delete result[result.length - 1];
}
return result;
}
unlines
Prelude: unlines
Source:
function unlines(lines) {
return lines.join('\n');
}
unwords
Prelude: unwords
Source:
function unwords(words) {
return words.join(' ');
}
words
Prelude: words
Source:
function words(string) {
return string.split(/[\n\r\v\t ]/);
}
Tuple
fst
Prelude: fst
(a, b) → b
Extract the first component of a pair.
Tuples also have a fst()
method which does the same thing,
but this function is exposing that method as a function.
Haskell Definition:
fst (a, _) = a
Source:
function fst(t) {
return t.fst();
}
objectToArray
Object → [(String, Any)]
Turns an object into an associative list of tuples.
The objects keys are the first components of the tuples,
the values the second components.
eq( objectToArray({ a: 17, b: 20 }), [ tuple('a', 17), tuple('b', 20) ]) === true
Source:
function objectToArray(obj) {
var arr = [];
each(function (val, key) {
arr.push(new Tuple(key, val));
}, obj);
return arr;
}
snd
Prelude: snd
(a, b) → b
Extract the second component of a pair.
Tuples also have a fst()
method which does the same thing,
but this function is exposing that method as a function.
Haskell Definition:
snd (_, b) = b
Source:
function snd(t) {
return t.snd();
}
Tuple
new Tuple(first, second) :: a → b → (a, b)
Tuples are immutable pairs of a first and a second components.
Methods:
- .fst() → a
- Retrieves the first component of this tuple.
- .snd() → b
- Retrieves the second component of this tuple.
Example:
var t = new Tuple(4711, 8080);
console.log(t.fst()); // 4711
console.log(t.snd()); // 8080
fst
and snd
are functional forms of .fst()
and .snd()
.
tuple
is a convenience method for omitting new
:
var t = tuple(4711, 8080);
console.log(fst(t)); // 4711
console.log(snd(t)); // 8080
var extractFirsts = map(fst);
console.log(extractFirsts([
tuple(4711, 8080),
tuple(3000, 4444)
])); // [ 4711, 3000 ]
Haskell Definition:
data Tuple a b = Tuple { fst :: a, snd :: b }
Source:
function Tuple(fst, snd) {
if (!(this instanceof Tuple)) {
return new Tuple(fst, snd);
}
this.fst = idf(fst);
this.snd = idf(snd);
freeze(this);
}
tuple
,
Prelude: ,
Source:
function tuple(first, second) {
return new Tuple(first, second);
}
tuple3
,,
Source:
function tuple3(first, second, third) {
return tuple(first, tuple(second, third));
}
tuple4
,,,
Source:
function tuple4(first, second, third, fourth) {
return tuple3(first, second, tuple(third, fourth));
}
tuplesToObject
[(String, Any)] → Object
Turns an associative list of tuples into an object.
The first components of the tuples are the keys,
the second components the corresponding values.
Example:
eq( tuplesToObject([ tuple('a', 2), tuple('b', 3) ]), { a: 2, b: 3 }) === true
Source:
function tuplesToObject(xs) {
var obj = {};
each(function (t) {
obj[t.fst()] = t.snd();
}, xs);
return obj;
}
Type
classOf
Any → String
Determines the property of the internal
[[Class]]
attribute,
normalized to lower case.
Example:
classOf(new Date()) === 'date'
classOf(null) === 'null'
classOf([]) === 'array'
function f() {
return classOf(arguments)
}
f() === 'arguments'
Source:
function classOf(thing) {
var exactType = toString.call(thing);
return exactType.slice(8, exactType.length - 1).toLowerCase();
}
is
Source:
function is(type, thing) {
return thing instanceof type;
}
isArguments
Any → Boolean
Source:
function isArguments(thing) {
return toString.call(thing) === '[object Arguments]';
}
isArray
Any → Boolean
Determines whether something is an array or not.
This is exactly the same as Array.isArray
.
Example:
isArray([]) === true
isArray({}) === false
isArray(new Array(3)) === true
isArray(undefined) === false
isArray(3) === false
Source:
function isArray() { [native code] }
isBoolean
Any → Boolean
Returns true
if the argument is a boolean value, otherwise false
.
Example:
isBoolean(true) === true
isBoolean(false) === false
isBoolean({}) === false
isBoolean(undefined) === false
isBoolean(0) === false
isBoolean(1) === false
isBoolean("true") === false
Source:
function isBoolean(thing) {
return typeof thing === 'boolean';
}
isDate
Any → Boolean
Source:
function isDate(thing) {
return toString.call(thing) === '[object Date]';
}
isEmpty
null_
Prelude: null
Any → Boolean
Source:
function isEmpty(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs.length === 0;
case 'list':
case 'stream':
return xs.isEmpty();
default:
for (var _ in xs) {
return false;
}
return true;
}
}
isFunction
Any → Boolean
Source:
function isFunction(thing) {
return typeof thing === 'function';
}
isInteger
Any → Boolean
Returns true
is the argument is an integral number.
Numbers in JavaScript are floating point values and there is no proper integer type.
This function can be used to check whether a given number could be cast to an
integer without truncating.
isInteger(7) === true
isInteger(7.0) === true
isInteger(7.3) === false
Source:
function isInteger(thing) {
return isNumber(thing) && !isNaN(thing) &&
thing - Math.floor(thing) === 0 &&
thing !== Infinity && thing !== -Infinity;
}
isNull
Any → Boolean
Source:
function isNull(thing) {
return toString.call(thing) === '[object Null]';
}
isNumber
Source:
function isNumber(thing) {
return typeof thing === 'number';
}
isObject
Source:
function isObject(thing) {
return typeof thing === 'object' &&
thing !== null && !Array.isArray(thing);
}
isRegExp
Any → Boolean
Returns true
is the argument is a regular expression object.
Example:
isRegExp(/a+/) === true
isRegExp("a+") === false
isRegExp(new RegExp("a+")) === true
Source:
function isRegExp(thing) {
return toString.call(thing) === '[object RegExp]';
}
isString
Source:
function isString(thing) {
return typeof thing === 'string' || toString.call(thing) === '[object String]';
}
isUndefined
Source:
function isUndefined(thing) {
return typeof thing === 'undefined';
}
typeOf
Something → String
Returns the type of the given thing as a String.
This differs from JavaScripts typeof
in the way that it
distinguishes null
, object
, and array
and identifies
NaN
as not-a-number
(Infinity
and -Infinity
are both
reported as number
). Also it knows some types native to
nodash, such as list
, stream
, and tuple
.
The possible return values are:
boolean
for true
and false
,
number
for a number which is not NaN
,
string
for a JavaScript string,
function
for a JavaScript function,
not-a-number
if isNaN
would return true,
null
for null
,
undefined
for undefined
,
array
is Array.isArray
would return true,
list
if it is a List,
stream
if it is a Stream,
tuple
if it is a Tuple,
object
if it is an object but neither null
nor an array
or any of the previously mentioned object types (e.g. tuple
)
In ECMAScript 2015 (ES6) this function may also return symbol
for Symbols.
Source:
function typeOf(thing) {
var type = typeof thing;
switch (type) {
case 'number':
return isNaN(thing) ? 'not-a-number' : 'number';
case 'object':
var exactType = classOf(thing);
if (exactType === 'object' && thing.constructor && thing.constructor.__type) {
return thing.constructor.__type;
}
return exactType;
default:
return type;
}
}
(unclassified)
any
Prelude: any
Source:
function any(p, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
return true;
}
}
return false;
}
append
++
Prelude: ++
Source:
function append(xs, ys) {
switch (typeOf(xs)) {
case 'list':
return appendList(xs, ys);
case 'string':
return xs + ys;
case 'array':
return [].concat.call(xs, ys);
default:
error(TypeError);
}
}
at
!!AT
Prelude: !!
Source:
function at(xs, ix) {
if (xs === undefined) {
return xs;
}
return xs[ix];
}
break
break_
Prelude: break
Source:
function break(p, xs) {
var i = 0;
while (i < xs.length && !p(xs[i])) {
i++;
}
return tuple(xs.slice(0, i), xs.slice(i));
}
clone
Source:
function clone(thing) {
if (typeof thing === 'object') {
if (thing === null) {
return null;
}
return map(clone, thing);
}
return thing;
}
compare
Prelude: compare
Source:
function compare(a, b) {
switch (typeof a) {
case 'string':
return a.localeCompare(b);
case 'object':
if (isFunction(a.compareTo)) {
return a.compareTo(b);
} else if (isArray(a)) {
for (var i = 0; i < Math.min(a.length, b.length); i++) {
var r = compare(a[i], b[i]);
if (r !== 0) {
return r;
}
}
return 0;
}
return a.toString().localeCompare(b.toString());
case 'number':
return signum(a - b);
}
return undefined;
}
comparing
Source:
function comparing(f, a, b) {
return compare(f(a), f(b));
}
concat
Prelude: concat
Source:
function concat(xs) {
if (isString(xs[0])) {
return xs.join('');
}
var zs = [];
var ks = Object.keys(xs);
for (var i = 0; i < ks.length; i++) {
[].push.apply(zs, xs[ks[i]]);
}
return zs;
}
concatMap
Prelude: concatMap
Source:
var concatMap = /* this is a composed function */
cons
:
Prelude: :
Source:
function cons(x, xs) {
switch (typeOf(xs)) {
case 'array':
var zs = [].slice.call(xs);
zs.unshift(x);
return zs;
case 'string':
return x + xs;
case 'list':
return new List(x, xs);
case 'stream':
return new Stream(function () {
return tuple(x, xs);
});
default:
error(TypeError);
}
}
curried
Source:
function curried(fn) {
return funcs[fn.length](fn);
}
delete
delete_
Prelude: delete
Source:
function delete(x, xs) {
var i = xs.indexOf(x);
if (i >= 0) {
return append(xs.slice(0,i), xs.slice(i+1));
}
return xs;
}
deleteBy
Prelude: deleteBy
Source:
function deleteBy(p, x, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(x, xs[i])) {
return append(xs.slice(0,i), xs.slice(i+1));
}
}
return xs;
}
difference
\\
Prelude: \\
Source:
function difference(xs, ys) {
var set = new Set();
var i;
for (i = 0; i < ys.length; i++) {
set.add(ys[i]);
}
var zs = [];
for (i = 0; i < xs.length; i++) {
if (!set.has(xs[i])) {
zs.push(xs[i]);
}
}
return isString(xs) ? arrayToString(zs) : zs;
}
drop
Prelude: drop
Source:
function drop(n, xs) {
return xs.slice(n);
}
dropWhile
Prelude: dropWhile
Source:
function dropWhile(p, xs) {
var i = 0;
while (i < xs.length && p(xs[i])) {
i++;
}
return xs.slice(i);
}
either
Prelude: either
Source:
function either(afun, bfun, value) {
if (is(Left, value)) {
return afun(value.value());
} else if (is(Right, value)) {
return bfun(value.value());
} else {
fail();
}
}
elem
Prelude: elem
Source:
function elem(x, xs) {
for (var i = 0; i < xs.length; i++) {
if (eq(xs[i], x)) {
return true;
}
}
return false;
}
elemIndex
Prelude: elemIndex
Source:
function elemIndex(x, xs) {
return findIndex(eq(x), xs);
}
elemIndices
Prelude: elemIndices
Source:
function elemIndices(x, xs) {
return findIndices(eq(x), xs);
}
emptyList
Source:
function emptyList() {
return emptyList;
}
eq
==EQ
Prelude: ==
Source:
function eq(a, b) {
if (a === b) {
return true;
}
var ta = typeOf(a);
var tb = typeOf(b);
if (ta !== tb) {
return false;
}
switch (ta) {
case 'tuple':
return eq(a.fst(), b.fst()) && eq(a.snd(), b.snd());
case 'list':
return eq(a.head(), b.head()) && eq(a.tail(), b.tail());
case 'array':
case 'object':
if (a.constructor !== b.constructor) {
return false;
}
var k = union(Object.keys(a), Object.keys(b));
for (var i = 0; i < k.length; i++) {
if (!eq(a[k[i]], b[k[i]])) {
return false;
}
}
return true;
}
return false;
}
filter
Prelude: filter
Source:
function filter(p, xs) {
var ys;
switch (typeOf(xs)) {
case 'array':
case 'string':
ys = [];
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
ys.push(xs[i]);
}
}
return isString(xs) ? arrayToString(ys) : ys;
default:
ys = {};
var ks = Object.keys(xs);
for (var j = 0; j < ks.length; j++) {
if (p(xs[ks[j]])) {
ys[ks[j]] = xs[ks[j]];
}
}
return ys;
}
}
find
Prelude: find
Source:
function find(p, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
return xs[i];
}
}
return null;
}
findIndex
Prelude: findIndex
Source:
function findIndex(p, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
return i;
}
}
return null;
}
findIndices
Prelude: findIndices
Source:
function findIndices(p, xs) {
var zs = [];
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
zs.push(i);
}
}
return zs;
}
foldl1
foldl1'
Prelude: foldl1'
Source:
function foldl1(f, xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
var x = xs[0];
for (var i = 1; i < xs.length; i += 1) {
x = f(xs[i], x);
}
return x;
}
}
foldr1
Prelude: foldr1
Source:
function foldr1(f, xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
var x = xs[xs.length - 1];
for (var i = xs.length - 2; i >= 0; i -= 1) {
x = f(xs[i], x);
}
return x;
}
}
fromLeft
Source:
function fromLeft(thing) {
if (is(Left, thing)) {
return thing.value();
}
fail();
}
fromMaybe
Source:
function fromMaybe(def, maybe) {
if (isJust(maybe)) {
return maybe;
}
return def;
}
fromRight
Source:
function fromRight(thing) {
if (is(Right, thing)) {
return thing.value();
}
fail();
}
group
Prelude: group
Source:
var group = /* this is a composed function */
groupBy
Prelude: groupBy
Source:
function groupBy(p, xs) {
if (xs.length === 0) {
return [];
}
var zs = [];
var current = [xs[0]];
var last = xs[0];
for (var i = 1; i < xs.length; i++) {
if (p(xs[i], last)) {
current.push(xs[i]);
} else {
zs.push(current);
current = [xs[i]];
}
last = xs[i];
}
zs.push(current);
return isString(xs) ? map(arrayToString, zs) : zs;
}
gt
>GT
Prelude: >
Source:
function gt(a, b) {
return compare(a, b) > 0;
}
gte
>=GTE
Prelude: >=
Source:
function gte(a, b) {
return compare(a, b) >= 0;
}
head
Prelude: head
Source:
function head(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs[0];
case 'list':
case 'stream':
return xs.head();
default:
error(TypeError);
}
}
indexOf
Source:
function indexOf(word, string) {
'use strict';
var m = 0;
var i = 0;
var table = [];
var pos = 2;
var cnd = 0;
table[0] = -1;
table[1] = 0;
// build the table for KMP. This takes `O(word.length)` steps.
while (pos < word.length) {
if (word[pos - 1] == word[cnd]) {
cnd = cnd + 1;
table[pos] = cnd;
pos = pos + 1;
} else if (cnd > 0) {
cnd = table[cnd];
} else {
table[pos] = 0;
pos = pos + 1;
}
}
// scan the string. This takes `O(string.length)` steps.
while (m + i < string.length) {
if (word[i] == string[m + i]) {
if (i == word.length - 1) {
return m;
}
i = i + 1;
} else {
if (table[i] > -1) {
m = m + i - table[i];
i = table[i];
} else {
i = 0;
m = m + 1;
}
}
}
// Returns -1 if the subsequence was not found in the sequence.
return -1;
}
init
Prelude: init
Source:
function init(xs) {
if (isString(xs)) {
return xs.slice(0, xs.length - 1);
}
return [].slice.call(xs, 0, xs.length - 1);
}
inits
Prelude: inits
Source:
function inits(xs) {
var result, current, i, length;
if (isArray(xs)) {
result = [[]];
current = [];
length = xs.length;
for (i = 0; i < length; i += 1) {
current = current.concat(xs[i]);
result.push(current);
}
return result;
}
// TODO the assumption is it's a string now
result = [''];
current = '';
length = xs.length;
for (i = 0; i < length; i += 1) {
current += xs[i];
result.push(current);
}
return result;
}
insert
Prelude: insert
Source:
var insert = /* this is a composed function */
insertBy
Prelude: insertBy
Source:
function insertBy(f, x, xs) {
for (var i = 0; i < xs.length; i++) {
if (f(x, xs[i]) <= 0) {
return concat([xs.slice(0,i), x, xs.slice(i)]);
}
}
return append(xs, x);
}
intercalate
Prelude: intercalate
Source:
function intercalate(x, xs) {
return concat(intersperse(x, xs));
}
intersect
Prelude: intersect
Source:
function intersect(xs, ys) {
var set = new Set();
var zs = [];
var i;
for (i = 0; i < ys.length; i++) {
set.add(ys[i]);
}
for (i = 0; i < xs.length; i++) {
if (set.has(xs[i])) {
zs.push(xs[i]);
}
}
return zs;
}
intersperse
Prelude: intersperse
Source:
function intersperse(x, xs) {
if (xs.length === 0) {
return [];
}
var z = [xs[0]];
for (var i = 1; i < xs.length; i++) {
z.push(x);
z.push(xs[i]);
}
return z;
}
last
Prelude: last
Source:
function last(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs[xs.length - 1];
case 'list':
if (xs.isEmpty()) {
return undefined;
}
for (var ts = xs.tail(); !ts.isEmpty();) {
xs = xs.tail();
ts = xs.tail();
}
return xs.head();
default:
error(TypeError);
}
}
length
Prelude: length
Source:
function length(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs.length;
case 'list':
var count = 0;
while (!xs.isEmpty()) {
count += 1;
xs = xs.tail();
}
return count;
case 'stream':
return Infinity;
case 'object':
return Object.keys(xs).length;
default:
error(TypeError);
}
}
listToMaybe
Source:
function listToMaybe(xs) {
if (is(List, xs)) {
return xs.isEmpty() ? null : xs.head();
}
throw new TypeError();
}
lookup
Prelude: lookup
Source:
function lookup(x, xs) {
if (isArray(xs)) {
for (var i = 0; i < xs.length; i++) {
if (xs[i] && eq(xs[i][0], x)) {
return xs[i][1];
}
}
}
return xs[x];
}
lt
<LT
Prelude: <
Source:
function lt(a, b) {
return compare(a, b) < 0;
}
lte
<=LTE
Prelude: <=
Source:
function lte(a, b) {
return compare(a, b) <= 0;
}
map
fmap
Prelude: fmap
Source:
function map(f, xs) {
var i, ys;
switch (typeOf(xs)) {
case 'array':
return mapArray(f, xs);
case 'string':
return arrayToString(mapArray(f, xs));
case 'list':
if (xs.isEmpty()) {
return xs;
}
/* falls through */
case 'stream':
return new List(lazy(function () {
return f(xs.head());
}), lazy(function () {
return map(f, xs.tail());
}));
case 'object':
ys = {};
var ks = Object.keys(xs);
for (var j = 0; j < ks.length; j += 1) {
ys[ks[j]] = f(xs[ks[j]], ks[j]);
}
return ys;
}
}
max
Prelude: max
Source:
function max(a, b) {
return compare(a, b) > 0 ? a : b;
}
maximum
Prelude: maximum
Source:
var maximum = /* this is a composed function */
maximumBy
Prelude: maximumBy
Source:
function maximumBy(f, xs) {
return foldl1(function (a, b) {
if (f(a, b) > 0) {
return a;
}
return b;
}, xs);
}
min
Prelude: min
Source:
function min(a, b) {
return compare(a, b) < 0 ? a : b;
}
minimum
Prelude: minimum
Source:
var minimum = /* this is a composed function */
minimumBy
Prelude: minimumBy
Source:
function minimumBy(f, xs) {
return foldl1(function (a, b) {
if (f(a, b) < 0) {
return a;
}
return b;
}, xs);
}
neq
/=!=<>NEQ
Prelude: /=
Source:
function neq(a, b) {
return !eq(a, b);
}
notElem
Prelude: notElem
Source:
function notElem(x, xs) {
for (var i = 0; i < xs.length; i++) {
if (eq(xs[i], x)) {
return false;
}
}
return true;
}
nub
Prelude: nub
Source:
function nub(xs) {
var set = new Set();
var zs = [];
for (var i = 0; i < xs.length; i++) {
if (!set.has(xs[i])) {
zs.push(xs[i]);
set.add(xs[i]);
}
}
return zs;
}
or
Prelude: or
Source:
var or = /* this is a composed function */
partition
Prelude: partition
Source:
function _partition(p, xs) {
var as = [];
var bs = [];
for (var i = 0; i < xs.length; i++) {
(p(xs[i]) ? as : bs).push(xs[i]);
}
if (isString(xs)) {
return tuple(arrayToString(as), arrayToString(bs));
}
return tuple(as, bs);
}
product
Prelude: product
Source:
var product = /* this is a composed function */
replicate
Prelude: replicate
Source:
function replicate(n, x) {
var xs = [];
for (var i = 0; i < n; i++) {
xs.push(x);
}
return xs;
}
reverse
Prelude: reverse
Source:
function reverse(xs) {
var zs = isString(xs) ? ''.split.call(xs, '') : [].slice.call(xs);
zs.reverse();
return isString(xs) ? zs.join('') : zs;
}
scanl
Prelude: scanl
Source:
function scanl(f, x, xs) {
var zs = [x];
for (var i = 0; i < xs.length; i++) {
x = f(x, xs[i]);
zs.push(x);
}
return zs;
}
scanl1
Prelude: scanl1
Source:
function scanl1(f, xs) {
var x = xs[0];
var zs = [x];
for (var i = 1; i < xs.length; i++) {
x = f(x, xs[i]);
zs.push(x);
}
return zs;
}
scanr
Prelude: scanr
Source:
function scanr(f, x, xs) {
var zs = [x];
for (var i = xs.length - 1; i >= 0; i--) {
x = f(xs[i], x);
zs.unshift(x);
}
return zs;
}
scanr1
Prelude: scanr1
Source:
function scanr1(f, xs) {
var x = xs[xs.length - 1];
var zs = [x];
for (var i = xs.length - 2; i >= 0; i--) {
x = f(xs[i], x);
zs.unshift(x);
}
return zs;
}
select
Source:
function select(path, object) {
return foldl(at, object, path.split(/\./));
}
sinh
Prelude: sinh
Source:
function sinh(x) {
return (Math.exp(x) - Math.exp(-x)) / 2;
}
sort
Prelude: sort
Source:
function sort(xs) {
if (xs.length <= 1) {
return xs;
}
var zs = isString(xs) ? ''.split.call(xs, '') : [].slice.call(xs);
if (isNumber(zs[0])) {
zs.sort(function (a, b) { return a - b; });
} else if (isString(zs[0])) {
zs.sort(function (a, b) { return a.localeCompare(b); });
} else {
zs.sort(compare);
}
return isString(xs) ? zs.join('') : zs;
}
sortBy
Prelude: sortBy
Source:
function sortBy(fn, xs) {
if (xs.length <= 1) {
return xs;
}
var yesItsAString = isString(xs);
var zs = yesItsAString ? ''.split.call(xs, '') : [].slice.call(xs);
zs.sort(fn);
return yesItsAString ? zs.join('') : zs;
}
span
Prelude: span
Source:
function span(p, xs) {
var i = 0;
while (i < xs.length && p(xs[i])) {
i++;
}
return tuple(xs.slice(0, i), xs.slice(i));
}
splitAt
Prelude: splitAt
Source:
function splitAt(n, xs) {
return tuple(take(n, xs), drop(n, xs));
}
tail
Prelude: tail
Source:
function tail(xs) {
switch (typeOf(xs)) {
case 'array':
return [].slice.call(xs, 1);
case 'string':
return "".slice.call(xs, 1);
case 'list':
case 'stream':
return xs.tail();
default:
error(TypeError);
}
}
tails
Prelude: tails
Source:
function tails(xs) {
var result, current, i;
if (isArray(xs)) {
result = [[]];
current = [];
for (i = xs.length - 1; i >= 0; i -= 1) {
current = [xs[i]].concat(current);
result.unshift(current);
}
return result;
}
// TODO the assumption is it's a string now
result = [''];
current = '';
for (i = xs.length - 1; i >= 0; i -= 1) {
current = xs[i] + current;
result.unshift(current);
}
return result;
}
take
Prelude: take
Source:
function take(n, xs) {
switch (typeOf(xs)) {
case 'string':
return "".slice.call(xs, 0, n);
case 'array':
return [].slice.call(xs, 0, n);
case 'list':
case 'stream':
return takeGenerator(n, xs);
default:
error(TypeError);
}
}
takeWhile
Prelude: takeWhile
Source:
function takeWhile(p, xs) {
var i = 0;
while (i < xs.length && p(xs[i])) {
i++;
}
return xs.slice(0, i);
}
transpose
Prelude: transpose
Source:
function transpose(xss) {
if (!isArray(xss)) {
var zss = {};
var ks = Object.keys(xss);
for (var k = 0; k < ks.length; k++) {
zss[xss[ks[k]]] = ks[k];
}
return zss;
}
var j = 0;
var zs = [];
var current;
do {
current = [];
for (var i = 0; i < xss.length; i++) {
if (xss[i][j] !== undefined) {
current.push(xss[i][j]);
}
}
j += 1;
} while (current.length > 0 && zs.push(current));
if (isString(xss[0])) {
zs = map(arrayToString, zs);
}
return zs;
}
union
Prelude: union
Source:
function union(xs, ys) {
var set = new Set();
var zs = [];
var i;
for (i = 0; i < xs.length; i++) {
zs.push(xs[i]);
set.add(xs[i]);
}
for (i = 0; i < ys.length; i++) {
if (!set.has(ys[i])) {
zs.push(ys[i]);
}
}
return zs;
}
Appendix
Coverage of Haskell Prelude
Prelude functions supported in Nodash
- !!
- $
- &&
- *
- **
- +
- ++
- ,
- -
- .
- /
- /=
- :
- <
- <=
- ==
- >
- >=
- ^
- ^^
- abs
- acos
- acosh
- all
- and
- any
- asin
- asinh
- atan
- atanh
- break
- ceiling
- compare
- concat
- concatMap
- const
- cos
- cosh
- curry
- cycle
- div
- divMod
- drop
- either
- elem
- even
- exp
- filter
- flip
- floor
- fmap
- foldl
- foldl1
- foldr
- foldr1
- fst
- gcd
- head
- id
- init
- iterate
- last
- lcm
- length
- lines
- log
- logBase
- lookup
- map
- max
- maximum
- maybe
- min
- minimum
- mod
- negate
- not
- notElem
- odd
- or
- product
- properFraction
- quot
- quotRem
- recip
- rem
- repeat
- replicate
- reverse
- round
- scanl
- scanl1
- scanr
- scanr1
- signum
- sin
- sinh
- snd
- span
- splitAt
- sqrt
- subtract
- sum
- tail
- take
- takeWhile
- tan
- tanh
- truncate
- uncurry
- unlines
- until
- unwords
- words
- zip
- zip3
- zipWith
- zipWith3
- ||
Prelude functions missing from Nodash
- $!
- =<<
- >>
- >>=
- FilePath
- IOError
- appendFile
- asTypeOf
- atan2
- catch
- decodeFloat
- dropWhie
- encodeFloat
- enumFrom
- enumFromThen
- enumFromThenTo
- enumFromTo
- error
- exponent
- fail
- floatDigits
- floatRadix
- floatRange
- fromEnum
- fromInteger
- fromIntegral
- fromRational
- getChar
- getContents
- getLine
- interact
- ioError
- isDenormalized
- isIEEE
- isInfinite
- isNaN
- isNegativeZero
- lex
- mapM
- mapM_
- maxBound
- minBound
- null
- otherwise
- pi
- pitStr
- pred
- print
- putChar
- putStrLn
- read
- readFile
- readIO
- readList
- readLn
- readParen
- reads
- readsPrec
- realToFrac
- return
- scaleFloat
- seq
- sequence
- sequence_
- show
- showChar
- showList
- showParen
- showString
- shows
- showsPrec
- significand
- succ
- toEnum
- toInteger
- toRational
- undefined
- unzip
- unzip3
- userError
- writeFile
Nodash-specific additions
- Either
- Left
- List
- Right
- Stream
- Thunk
- Tuple
- arrayToString
- async
- bool
- catMaybes
- chr
- classOf
- clone
- comparing
- compose2
- curried
- each
- emptyList
- fromLeft
- fromMaybe
- fromRight
- idf
- indexOf
- install
- invoke
- is
- isArguments
- isArray
- isAsciiLetter
- isBoolean
- isDate
- isEmpty
- isFunction
- isInteger
- isJust
- isLeft
- isLetter
- isLower
- isNothing
- isNull
- isNumber
- isNumeric
- isObject
- isRegExp
- isRight
- isString
- isUndefined
- isUpper
- keys
- lazy
- lefts
- listToArray
- listToMaybe
- listToString
- mapMaybe
- match
- maybeToList
- objectToArray
- on
- ord
- partitionEithers
- pipe
- range
- rangeStep
- register
- resolveThunk
- rights
- run
- select
- singleton
- tuple3
- tuple4
- tuplesToObject
- typeOf
- values
cycle Prelude: cycle
Source:
function cycle(xs) {
if (isArray(xs)) {
xs = lazy(xs);
}
function generator(ys) {
if (ys.isEmpty()) {
ys = xs;
}
return function () {
return tuple(ys.head(), generator(ys.tail()));
};
}
return new Stream(generator(xs));
}
iterate Prelude: iterate
Source:
function iterate(f, seed) {
function generator(seed) {
return function () {
var newSeed = f(seed);
return tuple(seed, generator(newSeed));
};
}
return new Stream(generator(seed));
}
repeat Prelude: repeat
Source:
function repeat(x) {
function generator() {
return tuple(x, generator);
}
return new Stream(generator);
}
Stream stream
new Stream(generator)
Streams are immutable, lazily evaluated, infinite Lists.
Methods:
- .head() → a
- Extract the first element of this stream.
- .tail() → List a
- Extract the rest of the stream.
Source:
function Stream(generator) {
if (!(this instanceof Stream)) {
return new Stream(generator);
}
var thunk = new Thunk(generator);
var self = this;
this.head = function () {
var value = thunk.get().fst();
self.head = idf(value);
return value;
};
this.tail = function () {
var value = thunk.get().snd();
switch (typeOf(value)) {
case 'list':
case 'stream':
break;
case 'function':
value = new Stream(value);
break;
default:
error(TypeError);
}
self.tail = idf(value);
return value;
};
}
until Prelude: until
Source:
function until(p, f, v) {
while (!p(v)) {
v = f(v);
}
return v;
}
lines Prelude: lines
Source:
function lines(string) {
var result = string.split(/\n/);
if (result[result.length - 1].length === 0) {
delete result[result.length - 1];
}
return result;
}
unlines Prelude: unlines
Source:
function unlines(lines) {
return lines.join('\n');
}
unwords Prelude: unwords
Source:
function unwords(words) {
return words.join(' ');
}
words Prelude: words
Source:
function words(string) {
return string.split(/[\n\r\v\t ]/);
}
Tuple
fst
Prelude: fst
(a, b) → b
Extract the first component of a pair.
Tuples also have a fst()
method which does the same thing,
but this function is exposing that method as a function.
Haskell Definition:
fst (a, _) = a
Source:
function fst(t) {
return t.fst();
}
objectToArray
Object → [(String, Any)]
Turns an object into an associative list of tuples.
The objects keys are the first components of the tuples,
the values the second components.
eq( objectToArray({ a: 17, b: 20 }), [ tuple('a', 17), tuple('b', 20) ]) === true
Source:
function objectToArray(obj) {
var arr = [];
each(function (val, key) {
arr.push(new Tuple(key, val));
}, obj);
return arr;
}
snd
Prelude: snd
(a, b) → b
Extract the second component of a pair.
Tuples also have a fst()
method which does the same thing,
but this function is exposing that method as a function.
Haskell Definition:
snd (_, b) = b
Source:
function snd(t) {
return t.snd();
}
Tuple
new Tuple(first, second) :: a → b → (a, b)
Tuples are immutable pairs of a first and a second components.
Methods:
- .fst() → a
- Retrieves the first component of this tuple.
- .snd() → b
- Retrieves the second component of this tuple.
Example:
var t = new Tuple(4711, 8080);
console.log(t.fst()); // 4711
console.log(t.snd()); // 8080
fst
and snd
are functional forms of .fst()
and .snd()
.
tuple
is a convenience method for omitting new
:
var t = tuple(4711, 8080);
console.log(fst(t)); // 4711
console.log(snd(t)); // 8080
var extractFirsts = map(fst);
console.log(extractFirsts([
tuple(4711, 8080),
tuple(3000, 4444)
])); // [ 4711, 3000 ]
Haskell Definition:
data Tuple a b = Tuple { fst :: a, snd :: b }
Source:
function Tuple(fst, snd) {
if (!(this instanceof Tuple)) {
return new Tuple(fst, snd);
}
this.fst = idf(fst);
this.snd = idf(snd);
freeze(this);
}
tuple
,
Prelude: ,
Source:
function tuple(first, second) {
return new Tuple(first, second);
}
tuple3
,,
Source:
function tuple3(first, second, third) {
return tuple(first, tuple(second, third));
}
tuple4
,,,
Source:
function tuple4(first, second, third, fourth) {
return tuple3(first, second, tuple(third, fourth));
}
tuplesToObject
[(String, Any)] → Object
Turns an associative list of tuples into an object.
The first components of the tuples are the keys,
the second components the corresponding values.
Example:
eq( tuplesToObject([ tuple('a', 2), tuple('b', 3) ]), { a: 2, b: 3 }) === true
Source:
function tuplesToObject(xs) {
var obj = {};
each(function (t) {
obj[t.fst()] = t.snd();
}, xs);
return obj;
}
Type
classOf
Any → String
Determines the property of the internal
[[Class]]
attribute,
normalized to lower case.
Example:
classOf(new Date()) === 'date'
classOf(null) === 'null'
classOf([]) === 'array'
function f() {
return classOf(arguments)
}
f() === 'arguments'
Source:
function classOf(thing) {
var exactType = toString.call(thing);
return exactType.slice(8, exactType.length - 1).toLowerCase();
}
is
Source:
function is(type, thing) {
return thing instanceof type;
}
isArguments
Any → Boolean
Source:
function isArguments(thing) {
return toString.call(thing) === '[object Arguments]';
}
isArray
Any → Boolean
Determines whether something is an array or not.
This is exactly the same as Array.isArray
.
Example:
isArray([]) === true
isArray({}) === false
isArray(new Array(3)) === true
isArray(undefined) === false
isArray(3) === false
Source:
function isArray() { [native code] }
isBoolean
Any → Boolean
Returns true
if the argument is a boolean value, otherwise false
.
Example:
isBoolean(true) === true
isBoolean(false) === false
isBoolean({}) === false
isBoolean(undefined) === false
isBoolean(0) === false
isBoolean(1) === false
isBoolean("true") === false
Source:
function isBoolean(thing) {
return typeof thing === 'boolean';
}
isDate
Any → Boolean
Source:
function isDate(thing) {
return toString.call(thing) === '[object Date]';
}
isEmpty
null_
Prelude: null
Any → Boolean
Source:
function isEmpty(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs.length === 0;
case 'list':
case 'stream':
return xs.isEmpty();
default:
for (var _ in xs) {
return false;
}
return true;
}
}
isFunction
Any → Boolean
Source:
function isFunction(thing) {
return typeof thing === 'function';
}
isInteger
Any → Boolean
Returns true
is the argument is an integral number.
Numbers in JavaScript are floating point values and there is no proper integer type.
This function can be used to check whether a given number could be cast to an
integer without truncating.
isInteger(7) === true
isInteger(7.0) === true
isInteger(7.3) === false
Source:
function isInteger(thing) {
return isNumber(thing) && !isNaN(thing) &&
thing - Math.floor(thing) === 0 &&
thing !== Infinity && thing !== -Infinity;
}
isNull
Any → Boolean
Source:
function isNull(thing) {
return toString.call(thing) === '[object Null]';
}
isNumber
Source:
function isNumber(thing) {
return typeof thing === 'number';
}
isObject
Source:
function isObject(thing) {
return typeof thing === 'object' &&
thing !== null && !Array.isArray(thing);
}
isRegExp
Any → Boolean
Returns true
is the argument is a regular expression object.
Example:
isRegExp(/a+/) === true
isRegExp("a+") === false
isRegExp(new RegExp("a+")) === true
Source:
function isRegExp(thing) {
return toString.call(thing) === '[object RegExp]';
}
isString
Source:
function isString(thing) {
return typeof thing === 'string' || toString.call(thing) === '[object String]';
}
isUndefined
Source:
function isUndefined(thing) {
return typeof thing === 'undefined';
}
typeOf
Something → String
Returns the type of the given thing as a String.
This differs from JavaScripts typeof
in the way that it
distinguishes null
, object
, and array
and identifies
NaN
as not-a-number
(Infinity
and -Infinity
are both
reported as number
). Also it knows some types native to
nodash, such as list
, stream
, and tuple
.
The possible return values are:
boolean
for true
and false
,
number
for a number which is not NaN
,
string
for a JavaScript string,
function
for a JavaScript function,
not-a-number
if isNaN
would return true,
null
for null
,
undefined
for undefined
,
array
is Array.isArray
would return true,
list
if it is a List,
stream
if it is a Stream,
tuple
if it is a Tuple,
object
if it is an object but neither null
nor an array
or any of the previously mentioned object types (e.g. tuple
)
In ECMAScript 2015 (ES6) this function may also return symbol
for Symbols.
Source:
function typeOf(thing) {
var type = typeof thing;
switch (type) {
case 'number':
return isNaN(thing) ? 'not-a-number' : 'number';
case 'object':
var exactType = classOf(thing);
if (exactType === 'object' && thing.constructor && thing.constructor.__type) {
return thing.constructor.__type;
}
return exactType;
default:
return type;
}
}
(unclassified)
any
Prelude: any
Source:
function any(p, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
return true;
}
}
return false;
}
append
++
Prelude: ++
Source:
function append(xs, ys) {
switch (typeOf(xs)) {
case 'list':
return appendList(xs, ys);
case 'string':
return xs + ys;
case 'array':
return [].concat.call(xs, ys);
default:
error(TypeError);
}
}
at
!!AT
Prelude: !!
Source:
function at(xs, ix) {
if (xs === undefined) {
return xs;
}
return xs[ix];
}
break
break_
Prelude: break
Source:
function break(p, xs) {
var i = 0;
while (i < xs.length && !p(xs[i])) {
i++;
}
return tuple(xs.slice(0, i), xs.slice(i));
}
clone
Source:
function clone(thing) {
if (typeof thing === 'object') {
if (thing === null) {
return null;
}
return map(clone, thing);
}
return thing;
}
compare
Prelude: compare
Source:
function compare(a, b) {
switch (typeof a) {
case 'string':
return a.localeCompare(b);
case 'object':
if (isFunction(a.compareTo)) {
return a.compareTo(b);
} else if (isArray(a)) {
for (var i = 0; i < Math.min(a.length, b.length); i++) {
var r = compare(a[i], b[i]);
if (r !== 0) {
return r;
}
}
return 0;
}
return a.toString().localeCompare(b.toString());
case 'number':
return signum(a - b);
}
return undefined;
}
comparing
Source:
function comparing(f, a, b) {
return compare(f(a), f(b));
}
concat
Prelude: concat
Source:
function concat(xs) {
if (isString(xs[0])) {
return xs.join('');
}
var zs = [];
var ks = Object.keys(xs);
for (var i = 0; i < ks.length; i++) {
[].push.apply(zs, xs[ks[i]]);
}
return zs;
}
concatMap
Prelude: concatMap
Source:
var concatMap = /* this is a composed function */
cons
:
Prelude: :
Source:
function cons(x, xs) {
switch (typeOf(xs)) {
case 'array':
var zs = [].slice.call(xs);
zs.unshift(x);
return zs;
case 'string':
return x + xs;
case 'list':
return new List(x, xs);
case 'stream':
return new Stream(function () {
return tuple(x, xs);
});
default:
error(TypeError);
}
}
curried
Source:
function curried(fn) {
return funcs[fn.length](fn);
}
delete
delete_
Prelude: delete
Source:
function delete(x, xs) {
var i = xs.indexOf(x);
if (i >= 0) {
return append(xs.slice(0,i), xs.slice(i+1));
}
return xs;
}
deleteBy
Prelude: deleteBy
Source:
function deleteBy(p, x, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(x, xs[i])) {
return append(xs.slice(0,i), xs.slice(i+1));
}
}
return xs;
}
difference
\\
Prelude: \\
Source:
function difference(xs, ys) {
var set = new Set();
var i;
for (i = 0; i < ys.length; i++) {
set.add(ys[i]);
}
var zs = [];
for (i = 0; i < xs.length; i++) {
if (!set.has(xs[i])) {
zs.push(xs[i]);
}
}
return isString(xs) ? arrayToString(zs) : zs;
}
drop
Prelude: drop
Source:
function drop(n, xs) {
return xs.slice(n);
}
dropWhile
Prelude: dropWhile
Source:
function dropWhile(p, xs) {
var i = 0;
while (i < xs.length && p(xs[i])) {
i++;
}
return xs.slice(i);
}
either
Prelude: either
Source:
function either(afun, bfun, value) {
if (is(Left, value)) {
return afun(value.value());
} else if (is(Right, value)) {
return bfun(value.value());
} else {
fail();
}
}
elem
Prelude: elem
Source:
function elem(x, xs) {
for (var i = 0; i < xs.length; i++) {
if (eq(xs[i], x)) {
return true;
}
}
return false;
}
elemIndex
Prelude: elemIndex
Source:
function elemIndex(x, xs) {
return findIndex(eq(x), xs);
}
elemIndices
Prelude: elemIndices
Source:
function elemIndices(x, xs) {
return findIndices(eq(x), xs);
}
emptyList
Source:
function emptyList() {
return emptyList;
}
eq
==EQ
Prelude: ==
Source:
function eq(a, b) {
if (a === b) {
return true;
}
var ta = typeOf(a);
var tb = typeOf(b);
if (ta !== tb) {
return false;
}
switch (ta) {
case 'tuple':
return eq(a.fst(), b.fst()) && eq(a.snd(), b.snd());
case 'list':
return eq(a.head(), b.head()) && eq(a.tail(), b.tail());
case 'array':
case 'object':
if (a.constructor !== b.constructor) {
return false;
}
var k = union(Object.keys(a), Object.keys(b));
for (var i = 0; i < k.length; i++) {
if (!eq(a[k[i]], b[k[i]])) {
return false;
}
}
return true;
}
return false;
}
filter
Prelude: filter
Source:
function filter(p, xs) {
var ys;
switch (typeOf(xs)) {
case 'array':
case 'string':
ys = [];
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
ys.push(xs[i]);
}
}
return isString(xs) ? arrayToString(ys) : ys;
default:
ys = {};
var ks = Object.keys(xs);
for (var j = 0; j < ks.length; j++) {
if (p(xs[ks[j]])) {
ys[ks[j]] = xs[ks[j]];
}
}
return ys;
}
}
find
Prelude: find
Source:
function find(p, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
return xs[i];
}
}
return null;
}
findIndex
Prelude: findIndex
Source:
function findIndex(p, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
return i;
}
}
return null;
}
findIndices
Prelude: findIndices
Source:
function findIndices(p, xs) {
var zs = [];
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
zs.push(i);
}
}
return zs;
}
foldl1
foldl1'
Prelude: foldl1'
Source:
function foldl1(f, xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
var x = xs[0];
for (var i = 1; i < xs.length; i += 1) {
x = f(xs[i], x);
}
return x;
}
}
foldr1
Prelude: foldr1
Source:
function foldr1(f, xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
var x = xs[xs.length - 1];
for (var i = xs.length - 2; i >= 0; i -= 1) {
x = f(xs[i], x);
}
return x;
}
}
fromLeft
Source:
function fromLeft(thing) {
if (is(Left, thing)) {
return thing.value();
}
fail();
}
fromMaybe
Source:
function fromMaybe(def, maybe) {
if (isJust(maybe)) {
return maybe;
}
return def;
}
fromRight
Source:
function fromRight(thing) {
if (is(Right, thing)) {
return thing.value();
}
fail();
}
group
Prelude: group
Source:
var group = /* this is a composed function */
groupBy
Prelude: groupBy
Source:
function groupBy(p, xs) {
if (xs.length === 0) {
return [];
}
var zs = [];
var current = [xs[0]];
var last = xs[0];
for (var i = 1; i < xs.length; i++) {
if (p(xs[i], last)) {
current.push(xs[i]);
} else {
zs.push(current);
current = [xs[i]];
}
last = xs[i];
}
zs.push(current);
return isString(xs) ? map(arrayToString, zs) : zs;
}
gt
>GT
Prelude: >
Source:
function gt(a, b) {
return compare(a, b) > 0;
}
gte
>=GTE
Prelude: >=
Source:
function gte(a, b) {
return compare(a, b) >= 0;
}
head
Prelude: head
Source:
function head(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs[0];
case 'list':
case 'stream':
return xs.head();
default:
error(TypeError);
}
}
indexOf
Source:
function indexOf(word, string) {
'use strict';
var m = 0;
var i = 0;
var table = [];
var pos = 2;
var cnd = 0;
table[0] = -1;
table[1] = 0;
// build the table for KMP. This takes `O(word.length)` steps.
while (pos < word.length) {
if (word[pos - 1] == word[cnd]) {
cnd = cnd + 1;
table[pos] = cnd;
pos = pos + 1;
} else if (cnd > 0) {
cnd = table[cnd];
} else {
table[pos] = 0;
pos = pos + 1;
}
}
// scan the string. This takes `O(string.length)` steps.
while (m + i < string.length) {
if (word[i] == string[m + i]) {
if (i == word.length - 1) {
return m;
}
i = i + 1;
} else {
if (table[i] > -1) {
m = m + i - table[i];
i = table[i];
} else {
i = 0;
m = m + 1;
}
}
}
// Returns -1 if the subsequence was not found in the sequence.
return -1;
}
init
Prelude: init
Source:
function init(xs) {
if (isString(xs)) {
return xs.slice(0, xs.length - 1);
}
return [].slice.call(xs, 0, xs.length - 1);
}
inits
Prelude: inits
Source:
function inits(xs) {
var result, current, i, length;
if (isArray(xs)) {
result = [[]];
current = [];
length = xs.length;
for (i = 0; i < length; i += 1) {
current = current.concat(xs[i]);
result.push(current);
}
return result;
}
// TODO the assumption is it's a string now
result = [''];
current = '';
length = xs.length;
for (i = 0; i < length; i += 1) {
current += xs[i];
result.push(current);
}
return result;
}
insert
Prelude: insert
Source:
var insert = /* this is a composed function */
insertBy
Prelude: insertBy
Source:
function insertBy(f, x, xs) {
for (var i = 0; i < xs.length; i++) {
if (f(x, xs[i]) <= 0) {
return concat([xs.slice(0,i), x, xs.slice(i)]);
}
}
return append(xs, x);
}
intercalate
Prelude: intercalate
Source:
function intercalate(x, xs) {
return concat(intersperse(x, xs));
}
intersect
Prelude: intersect
Source:
function intersect(xs, ys) {
var set = new Set();
var zs = [];
var i;
for (i = 0; i < ys.length; i++) {
set.add(ys[i]);
}
for (i = 0; i < xs.length; i++) {
if (set.has(xs[i])) {
zs.push(xs[i]);
}
}
return zs;
}
intersperse
Prelude: intersperse
Source:
function intersperse(x, xs) {
if (xs.length === 0) {
return [];
}
var z = [xs[0]];
for (var i = 1; i < xs.length; i++) {
z.push(x);
z.push(xs[i]);
}
return z;
}
last
Prelude: last
Source:
function last(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs[xs.length - 1];
case 'list':
if (xs.isEmpty()) {
return undefined;
}
for (var ts = xs.tail(); !ts.isEmpty();) {
xs = xs.tail();
ts = xs.tail();
}
return xs.head();
default:
error(TypeError);
}
}
length
Prelude: length
Source:
function length(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs.length;
case 'list':
var count = 0;
while (!xs.isEmpty()) {
count += 1;
xs = xs.tail();
}
return count;
case 'stream':
return Infinity;
case 'object':
return Object.keys(xs).length;
default:
error(TypeError);
}
}
listToMaybe
Source:
function listToMaybe(xs) {
if (is(List, xs)) {
return xs.isEmpty() ? null : xs.head();
}
throw new TypeError();
}
lookup
Prelude: lookup
Source:
function lookup(x, xs) {
if (isArray(xs)) {
for (var i = 0; i < xs.length; i++) {
if (xs[i] && eq(xs[i][0], x)) {
return xs[i][1];
}
}
}
return xs[x];
}
lt
<LT
Prelude: <
Source:
function lt(a, b) {
return compare(a, b) < 0;
}
lte
<=LTE
Prelude: <=
Source:
function lte(a, b) {
return compare(a, b) <= 0;
}
map
fmap
Prelude: fmap
Source:
function map(f, xs) {
var i, ys;
switch (typeOf(xs)) {
case 'array':
return mapArray(f, xs);
case 'string':
return arrayToString(mapArray(f, xs));
case 'list':
if (xs.isEmpty()) {
return xs;
}
/* falls through */
case 'stream':
return new List(lazy(function () {
return f(xs.head());
}), lazy(function () {
return map(f, xs.tail());
}));
case 'object':
ys = {};
var ks = Object.keys(xs);
for (var j = 0; j < ks.length; j += 1) {
ys[ks[j]] = f(xs[ks[j]], ks[j]);
}
return ys;
}
}
max
Prelude: max
Source:
function max(a, b) {
return compare(a, b) > 0 ? a : b;
}
maximum
Prelude: maximum
Source:
var maximum = /* this is a composed function */
maximumBy
Prelude: maximumBy
Source:
function maximumBy(f, xs) {
return foldl1(function (a, b) {
if (f(a, b) > 0) {
return a;
}
return b;
}, xs);
}
min
Prelude: min
Source:
function min(a, b) {
return compare(a, b) < 0 ? a : b;
}
minimum
Prelude: minimum
Source:
var minimum = /* this is a composed function */
minimumBy
Prelude: minimumBy
Source:
function minimumBy(f, xs) {
return foldl1(function (a, b) {
if (f(a, b) < 0) {
return a;
}
return b;
}, xs);
}
neq
/=!=<>NEQ
Prelude: /=
Source:
function neq(a, b) {
return !eq(a, b);
}
notElem
Prelude: notElem
Source:
function notElem(x, xs) {
for (var i = 0; i < xs.length; i++) {
if (eq(xs[i], x)) {
return false;
}
}
return true;
}
nub
Prelude: nub
Source:
function nub(xs) {
var set = new Set();
var zs = [];
for (var i = 0; i < xs.length; i++) {
if (!set.has(xs[i])) {
zs.push(xs[i]);
set.add(xs[i]);
}
}
return zs;
}
or
Prelude: or
Source:
var or = /* this is a composed function */
partition
Prelude: partition
Source:
function _partition(p, xs) {
var as = [];
var bs = [];
for (var i = 0; i < xs.length; i++) {
(p(xs[i]) ? as : bs).push(xs[i]);
}
if (isString(xs)) {
return tuple(arrayToString(as), arrayToString(bs));
}
return tuple(as, bs);
}
product
Prelude: product
Source:
var product = /* this is a composed function */
replicate
Prelude: replicate
Source:
function replicate(n, x) {
var xs = [];
for (var i = 0; i < n; i++) {
xs.push(x);
}
return xs;
}
reverse
Prelude: reverse
Source:
function reverse(xs) {
var zs = isString(xs) ? ''.split.call(xs, '') : [].slice.call(xs);
zs.reverse();
return isString(xs) ? zs.join('') : zs;
}
scanl
Prelude: scanl
Source:
function scanl(f, x, xs) {
var zs = [x];
for (var i = 0; i < xs.length; i++) {
x = f(x, xs[i]);
zs.push(x);
}
return zs;
}
scanl1
Prelude: scanl1
Source:
function scanl1(f, xs) {
var x = xs[0];
var zs = [x];
for (var i = 1; i < xs.length; i++) {
x = f(x, xs[i]);
zs.push(x);
}
return zs;
}
scanr
Prelude: scanr
Source:
function scanr(f, x, xs) {
var zs = [x];
for (var i = xs.length - 1; i >= 0; i--) {
x = f(xs[i], x);
zs.unshift(x);
}
return zs;
}
scanr1
Prelude: scanr1
Source:
function scanr1(f, xs) {
var x = xs[xs.length - 1];
var zs = [x];
for (var i = xs.length - 2; i >= 0; i--) {
x = f(xs[i], x);
zs.unshift(x);
}
return zs;
}
select
Source:
function select(path, object) {
return foldl(at, object, path.split(/\./));
}
sinh
Prelude: sinh
Source:
function sinh(x) {
return (Math.exp(x) - Math.exp(-x)) / 2;
}
sort
Prelude: sort
Source:
function sort(xs) {
if (xs.length <= 1) {
return xs;
}
var zs = isString(xs) ? ''.split.call(xs, '') : [].slice.call(xs);
if (isNumber(zs[0])) {
zs.sort(function (a, b) { return a - b; });
} else if (isString(zs[0])) {
zs.sort(function (a, b) { return a.localeCompare(b); });
} else {
zs.sort(compare);
}
return isString(xs) ? zs.join('') : zs;
}
sortBy
Prelude: sortBy
Source:
function sortBy(fn, xs) {
if (xs.length <= 1) {
return xs;
}
var yesItsAString = isString(xs);
var zs = yesItsAString ? ''.split.call(xs, '') : [].slice.call(xs);
zs.sort(fn);
return yesItsAString ? zs.join('') : zs;
}
span
Prelude: span
Source:
function span(p, xs) {
var i = 0;
while (i < xs.length && p(xs[i])) {
i++;
}
return tuple(xs.slice(0, i), xs.slice(i));
}
splitAt
Prelude: splitAt
Source:
function splitAt(n, xs) {
return tuple(take(n, xs), drop(n, xs));
}
tail
Prelude: tail
Source:
function tail(xs) {
switch (typeOf(xs)) {
case 'array':
return [].slice.call(xs, 1);
case 'string':
return "".slice.call(xs, 1);
case 'list':
case 'stream':
return xs.tail();
default:
error(TypeError);
}
}
tails
Prelude: tails
Source:
function tails(xs) {
var result, current, i;
if (isArray(xs)) {
result = [[]];
current = [];
for (i = xs.length - 1; i >= 0; i -= 1) {
current = [xs[i]].concat(current);
result.unshift(current);
}
return result;
}
// TODO the assumption is it's a string now
result = [''];
current = '';
for (i = xs.length - 1; i >= 0; i -= 1) {
current = xs[i] + current;
result.unshift(current);
}
return result;
}
take
Prelude: take
Source:
function take(n, xs) {
switch (typeOf(xs)) {
case 'string':
return "".slice.call(xs, 0, n);
case 'array':
return [].slice.call(xs, 0, n);
case 'list':
case 'stream':
return takeGenerator(n, xs);
default:
error(TypeError);
}
}
takeWhile
Prelude: takeWhile
Source:
function takeWhile(p, xs) {
var i = 0;
while (i < xs.length && p(xs[i])) {
i++;
}
return xs.slice(0, i);
}
transpose
Prelude: transpose
Source:
function transpose(xss) {
if (!isArray(xss)) {
var zss = {};
var ks = Object.keys(xss);
for (var k = 0; k < ks.length; k++) {
zss[xss[ks[k]]] = ks[k];
}
return zss;
}
var j = 0;
var zs = [];
var current;
do {
current = [];
for (var i = 0; i < xss.length; i++) {
if (xss[i][j] !== undefined) {
current.push(xss[i][j]);
}
}
j += 1;
} while (current.length > 0 && zs.push(current));
if (isString(xss[0])) {
zs = map(arrayToString, zs);
}
return zs;
}
union
Prelude: union
Source:
function union(xs, ys) {
var set = new Set();
var zs = [];
var i;
for (i = 0; i < xs.length; i++) {
zs.push(xs[i]);
set.add(xs[i]);
}
for (i = 0; i < ys.length; i++) {
if (!set.has(ys[i])) {
zs.push(ys[i]);
}
}
return zs;
}
Appendix
Coverage of Haskell Prelude
Prelude functions supported in Nodash
- !!
- $
- &&
- *
- **
- +
- ++
- ,
- -
- .
- /
- /=
- :
- <
- <=
- ==
- >
- >=
- ^
- ^^
- abs
- acos
- acosh
- all
- and
- any
- asin
- asinh
- atan
- atanh
- break
- ceiling
- compare
- concat
- concatMap
- const
- cos
- cosh
- curry
- cycle
- div
- divMod
- drop
- either
- elem
- even
- exp
- filter
- flip
- floor
- fmap
- foldl
- foldl1
- foldr
- foldr1
- fst
- gcd
- head
- id
- init
- iterate
- last
- lcm
- length
- lines
- log
- logBase
- lookup
- map
- max
- maximum
- maybe
- min
- minimum
- mod
- negate
- not
- notElem
- odd
- or
- product
- properFraction
- quot
- quotRem
- recip
- rem
- repeat
- replicate
- reverse
- round
- scanl
- scanl1
- scanr
- scanr1
- signum
- sin
- sinh
- snd
- span
- splitAt
- sqrt
- subtract
- sum
- tail
- take
- takeWhile
- tan
- tanh
- truncate
- uncurry
- unlines
- until
- unwords
- words
- zip
- zip3
- zipWith
- zipWith3
- ||
Prelude functions missing from Nodash
- $!
- =<<
- >>
- >>=
- FilePath
- IOError
- appendFile
- asTypeOf
- atan2
- catch
- decodeFloat
- dropWhie
- encodeFloat
- enumFrom
- enumFromThen
- enumFromThenTo
- enumFromTo
- error
- exponent
- fail
- floatDigits
- floatRadix
- floatRange
- fromEnum
- fromInteger
- fromIntegral
- fromRational
- getChar
- getContents
- getLine
- interact
- ioError
- isDenormalized
- isIEEE
- isInfinite
- isNaN
- isNegativeZero
- lex
- mapM
- mapM_
- maxBound
- minBound
- null
- otherwise
- pi
- pitStr
- pred
- print
- putChar
- putStrLn
- read
- readFile
- readIO
- readList
- readLn
- readParen
- reads
- readsPrec
- realToFrac
- return
- scaleFloat
- seq
- sequence
- sequence_
- show
- showChar
- showList
- showParen
- showString
- shows
- showsPrec
- significand
- succ
- toEnum
- toInteger
- toRational
- undefined
- unzip
- unzip3
- userError
- writeFile
Nodash-specific additions
- Either
- Left
- List
- Right
- Stream
- Thunk
- Tuple
- arrayToString
- async
- bool
- catMaybes
- chr
- classOf
- clone
- comparing
- compose2
- curried
- each
- emptyList
- fromLeft
- fromMaybe
- fromRight
- idf
- indexOf
- install
- invoke
- is
- isArguments
- isArray
- isAsciiLetter
- isBoolean
- isDate
- isEmpty
- isFunction
- isInteger
- isJust
- isLeft
- isLetter
- isLower
- isNothing
- isNull
- isNumber
- isNumeric
- isObject
- isRegExp
- isRight
- isString
- isUndefined
- isUpper
- keys
- lazy
- lefts
- listToArray
- listToMaybe
- listToString
- mapMaybe
- match
- maybeToList
- objectToArray
- on
- ord
- partitionEithers
- pipe
- range
- rangeStep
- register
- resolveThunk
- rights
- run
- select
- singleton
- tuple3
- tuple4
- tuplesToObject
- typeOf
- values
fst Prelude: fst
(a, b) → b
Extract the first component of a pair.
Tuples also have a fst()
method which does the same thing,
but this function is exposing that method as a function.
Haskell Definition:
fst (a, _) = a
Source:
function fst(t) {
return t.fst();
}
objectToArray
Object → [(String, Any)]
Turns an object into an associative list of tuples.
The objects keys are the first components of the tuples, the values the second components.
eq( objectToArray({ a: 17, b: 20 }), [ tuple('a', 17), tuple('b', 20) ]) === true
Source:
function objectToArray(obj) {
var arr = [];
each(function (val, key) {
arr.push(new Tuple(key, val));
}, obj);
return arr;
}
snd Prelude: snd
(a, b) → b
Extract the second component of a pair.
Tuples also have a fst()
method which does the same thing,
but this function is exposing that method as a function.
Haskell Definition:
snd (_, b) = b
Source:
function snd(t) {
return t.snd();
}
Tuple
new Tuple(first, second) :: a → b → (a, b)
Tuples are immutable pairs of a first and a second components.
Methods:
- .fst() → a
- Retrieves the first component of this tuple.
- .snd() → b
- Retrieves the second component of this tuple.
Example:
var t = new Tuple(4711, 8080);
console.log(t.fst()); // 4711
console.log(t.snd()); // 8080
fst
and snd
are functional forms of .fst()
and .snd()
.
tuple
is a convenience method for omitting new
:
var t = tuple(4711, 8080);
console.log(fst(t)); // 4711
console.log(snd(t)); // 8080
var extractFirsts = map(fst);
console.log(extractFirsts([
tuple(4711, 8080),
tuple(3000, 4444)
])); // [ 4711, 3000 ]
Haskell Definition:
data Tuple a b = Tuple { fst :: a, snd :: b }
Source:
function Tuple(fst, snd) {
if (!(this instanceof Tuple)) {
return new Tuple(fst, snd);
}
this.fst = idf(fst);
this.snd = idf(snd);
freeze(this);
}
tuple , Prelude: ,
Source:
function tuple(first, second) {
return new Tuple(first, second);
}
tuple3 ,,
Source:
function tuple3(first, second, third) {
return tuple(first, tuple(second, third));
}
tuple4 ,,,
Source:
function tuple4(first, second, third, fourth) {
return tuple3(first, second, tuple(third, fourth));
}
tuplesToObject
[(String, Any)] → Object
Turns an associative list of tuples into an object.
The first components of the tuples are the keys, the second components the corresponding values.
Example:
eq( tuplesToObject([ tuple('a', 2), tuple('b', 3) ]), { a: 2, b: 3 }) === true
Source:
function tuplesToObject(xs) {
var obj = {};
each(function (t) {
obj[t.fst()] = t.snd();
}, xs);
return obj;
}
classOf
Any → String
Determines the property of the internal
[[Class]]
attribute,
normalized to lower case.
Example:
classOf(new Date()) === 'date'
classOf(null) === 'null'
classOf([]) === 'array'
function f() {
return classOf(arguments)
}
f() === 'arguments'
Source:
function classOf(thing) {
var exactType = toString.call(thing);
return exactType.slice(8, exactType.length - 1).toLowerCase();
}
is
Source:
function is(type, thing) {
return thing instanceof type;
}
isArguments
Any → Boolean
Source:
function isArguments(thing) {
return toString.call(thing) === '[object Arguments]';
}
isArray
Any → Boolean
Determines whether something is an array or not.
This is exactly the same as Array.isArray
.
Example:
isArray([]) === true
isArray({}) === false
isArray(new Array(3)) === true
isArray(undefined) === false
isArray(3) === false
Source:
function isArray() { [native code] }
isBoolean
Any → Boolean
Returns true
if the argument is a boolean value, otherwise false
.
Example:
isBoolean(true) === true
isBoolean(false) === false
isBoolean({}) === false
isBoolean(undefined) === false
isBoolean(0) === false
isBoolean(1) === false
isBoolean("true") === false
Source:
function isBoolean(thing) {
return typeof thing === 'boolean';
}
isDate
Any → Boolean
Source:
function isDate(thing) {
return toString.call(thing) === '[object Date]';
}
isEmpty null_ Prelude: null
Any → Boolean
Source:
function isEmpty(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs.length === 0;
case 'list':
case 'stream':
return xs.isEmpty();
default:
for (var _ in xs) {
return false;
}
return true;
}
}
isFunction
Any → Boolean
Source:
function isFunction(thing) {
return typeof thing === 'function';
}
isInteger
Any → Boolean
Returns true
is the argument is an integral number.
Numbers in JavaScript are floating point values and there is no proper integer type. This function can be used to check whether a given number could be cast to an integer without truncating.
isInteger(7) === true
isInteger(7.0) === true
isInteger(7.3) === false
Source:
function isInteger(thing) {
return isNumber(thing) && !isNaN(thing) &&
thing - Math.floor(thing) === 0 &&
thing !== Infinity && thing !== -Infinity;
}
isNull
Any → Boolean
Source:
function isNull(thing) {
return toString.call(thing) === '[object Null]';
}
isNumber
Source:
function isNumber(thing) {
return typeof thing === 'number';
}
isObject
Source:
function isObject(thing) {
return typeof thing === 'object' &&
thing !== null && !Array.isArray(thing);
}
isRegExp
Any → Boolean
Returns true
is the argument is a regular expression object.
Example:
isRegExp(/a+/) === true
isRegExp("a+") === false
isRegExp(new RegExp("a+")) === true
Source:
function isRegExp(thing) {
return toString.call(thing) === '[object RegExp]';
}
isString
Source:
function isString(thing) {
return typeof thing === 'string' || toString.call(thing) === '[object String]';
}
isUndefined
Source:
function isUndefined(thing) {
return typeof thing === 'undefined';
}
typeOf
Something → String
Returns the type of the given thing as a String.
This differs from JavaScripts typeof
in the way that it
distinguishes null
, object
, and array
and identifies
NaN
as not-a-number
(Infinity
and -Infinity
are both
reported as number
). Also it knows some types native to
nodash, such as list
, stream
, and tuple
.
The possible return values are:
boolean
fortrue
andfalse
,number
for a number which is notNaN
,string
for a JavaScript string,function
for a JavaScript function,not-a-number
ifisNaN
would return true,null
fornull
,undefined
forundefined
,array
isArray.isArray
would return true,list
if it is a List,stream
if it is a Stream,tuple
if it is a Tuple,object
if it is an object but neithernull
nor anarray
or any of the previously mentioned object types (e.g.tuple
)
In ECMAScript 2015 (ES6) this function may also return symbol
for Symbols.
Source:
function typeOf(thing) {
var type = typeof thing;
switch (type) {
case 'number':
return isNaN(thing) ? 'not-a-number' : 'number';
case 'object':
var exactType = classOf(thing);
if (exactType === 'object' && thing.constructor && thing.constructor.__type) {
return thing.constructor.__type;
}
return exactType;
default:
return type;
}
}
(unclassified)
any
Prelude: any
Source:
function any(p, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
return true;
}
}
return false;
}
append
++
Prelude: ++
Source:
function append(xs, ys) {
switch (typeOf(xs)) {
case 'list':
return appendList(xs, ys);
case 'string':
return xs + ys;
case 'array':
return [].concat.call(xs, ys);
default:
error(TypeError);
}
}
at
!!AT
Prelude: !!
Source:
function at(xs, ix) {
if (xs === undefined) {
return xs;
}
return xs[ix];
}
break
break_
Prelude: break
Source:
function break(p, xs) {
var i = 0;
while (i < xs.length && !p(xs[i])) {
i++;
}
return tuple(xs.slice(0, i), xs.slice(i));
}
clone
Source:
function clone(thing) {
if (typeof thing === 'object') {
if (thing === null) {
return null;
}
return map(clone, thing);
}
return thing;
}
compare
Prelude: compare
Source:
function compare(a, b) {
switch (typeof a) {
case 'string':
return a.localeCompare(b);
case 'object':
if (isFunction(a.compareTo)) {
return a.compareTo(b);
} else if (isArray(a)) {
for (var i = 0; i < Math.min(a.length, b.length); i++) {
var r = compare(a[i], b[i]);
if (r !== 0) {
return r;
}
}
return 0;
}
return a.toString().localeCompare(b.toString());
case 'number':
return signum(a - b);
}
return undefined;
}
comparing
Source:
function comparing(f, a, b) {
return compare(f(a), f(b));
}
concat
Prelude: concat
Source:
function concat(xs) {
if (isString(xs[0])) {
return xs.join('');
}
var zs = [];
var ks = Object.keys(xs);
for (var i = 0; i < ks.length; i++) {
[].push.apply(zs, xs[ks[i]]);
}
return zs;
}
concatMap
Prelude: concatMap
Source:
var concatMap = /* this is a composed function */
cons
:
Prelude: :
Source:
function cons(x, xs) {
switch (typeOf(xs)) {
case 'array':
var zs = [].slice.call(xs);
zs.unshift(x);
return zs;
case 'string':
return x + xs;
case 'list':
return new List(x, xs);
case 'stream':
return new Stream(function () {
return tuple(x, xs);
});
default:
error(TypeError);
}
}
curried
Source:
function curried(fn) {
return funcs[fn.length](fn);
}
delete
delete_
Prelude: delete
Source:
function delete(x, xs) {
var i = xs.indexOf(x);
if (i >= 0) {
return append(xs.slice(0,i), xs.slice(i+1));
}
return xs;
}
deleteBy
Prelude: deleteBy
Source:
function deleteBy(p, x, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(x, xs[i])) {
return append(xs.slice(0,i), xs.slice(i+1));
}
}
return xs;
}
difference
\\
Prelude: \\
Source:
function difference(xs, ys) {
var set = new Set();
var i;
for (i = 0; i < ys.length; i++) {
set.add(ys[i]);
}
var zs = [];
for (i = 0; i < xs.length; i++) {
if (!set.has(xs[i])) {
zs.push(xs[i]);
}
}
return isString(xs) ? arrayToString(zs) : zs;
}
drop
Prelude: drop
Source:
function drop(n, xs) {
return xs.slice(n);
}
dropWhile
Prelude: dropWhile
Source:
function dropWhile(p, xs) {
var i = 0;
while (i < xs.length && p(xs[i])) {
i++;
}
return xs.slice(i);
}
either
Prelude: either
Source:
function either(afun, bfun, value) {
if (is(Left, value)) {
return afun(value.value());
} else if (is(Right, value)) {
return bfun(value.value());
} else {
fail();
}
}
elem
Prelude: elem
Source:
function elem(x, xs) {
for (var i = 0; i < xs.length; i++) {
if (eq(xs[i], x)) {
return true;
}
}
return false;
}
elemIndex
Prelude: elemIndex
Source:
function elemIndex(x, xs) {
return findIndex(eq(x), xs);
}
elemIndices
Prelude: elemIndices
Source:
function elemIndices(x, xs) {
return findIndices(eq(x), xs);
}
emptyList
Source:
function emptyList() {
return emptyList;
}
eq
==EQ
Prelude: ==
Source:
function eq(a, b) {
if (a === b) {
return true;
}
var ta = typeOf(a);
var tb = typeOf(b);
if (ta !== tb) {
return false;
}
switch (ta) {
case 'tuple':
return eq(a.fst(), b.fst()) && eq(a.snd(), b.snd());
case 'list':
return eq(a.head(), b.head()) && eq(a.tail(), b.tail());
case 'array':
case 'object':
if (a.constructor !== b.constructor) {
return false;
}
var k = union(Object.keys(a), Object.keys(b));
for (var i = 0; i < k.length; i++) {
if (!eq(a[k[i]], b[k[i]])) {
return false;
}
}
return true;
}
return false;
}
filter
Prelude: filter
Source:
function filter(p, xs) {
var ys;
switch (typeOf(xs)) {
case 'array':
case 'string':
ys = [];
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
ys.push(xs[i]);
}
}
return isString(xs) ? arrayToString(ys) : ys;
default:
ys = {};
var ks = Object.keys(xs);
for (var j = 0; j < ks.length; j++) {
if (p(xs[ks[j]])) {
ys[ks[j]] = xs[ks[j]];
}
}
return ys;
}
}
find
Prelude: find
Source:
function find(p, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
return xs[i];
}
}
return null;
}
findIndex
Prelude: findIndex
Source:
function findIndex(p, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
return i;
}
}
return null;
}
findIndices
Prelude: findIndices
Source:
function findIndices(p, xs) {
var zs = [];
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
zs.push(i);
}
}
return zs;
}
foldl1
foldl1'
Prelude: foldl1'
Source:
function foldl1(f, xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
var x = xs[0];
for (var i = 1; i < xs.length; i += 1) {
x = f(xs[i], x);
}
return x;
}
}
foldr1
Prelude: foldr1
Source:
function foldr1(f, xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
var x = xs[xs.length - 1];
for (var i = xs.length - 2; i >= 0; i -= 1) {
x = f(xs[i], x);
}
return x;
}
}
fromLeft
Source:
function fromLeft(thing) {
if (is(Left, thing)) {
return thing.value();
}
fail();
}
fromMaybe
Source:
function fromMaybe(def, maybe) {
if (isJust(maybe)) {
return maybe;
}
return def;
}
fromRight
Source:
function fromRight(thing) {
if (is(Right, thing)) {
return thing.value();
}
fail();
}
group
Prelude: group
Source:
var group = /* this is a composed function */
groupBy
Prelude: groupBy
Source:
function groupBy(p, xs) {
if (xs.length === 0) {
return [];
}
var zs = [];
var current = [xs[0]];
var last = xs[0];
for (var i = 1; i < xs.length; i++) {
if (p(xs[i], last)) {
current.push(xs[i]);
} else {
zs.push(current);
current = [xs[i]];
}
last = xs[i];
}
zs.push(current);
return isString(xs) ? map(arrayToString, zs) : zs;
}
gt
>GT
Prelude: >
Source:
function gt(a, b) {
return compare(a, b) > 0;
}
gte
>=GTE
Prelude: >=
Source:
function gte(a, b) {
return compare(a, b) >= 0;
}
head
Prelude: head
Source:
function head(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs[0];
case 'list':
case 'stream':
return xs.head();
default:
error(TypeError);
}
}
indexOf
Source:
function indexOf(word, string) {
'use strict';
var m = 0;
var i = 0;
var table = [];
var pos = 2;
var cnd = 0;
table[0] = -1;
table[1] = 0;
// build the table for KMP. This takes `O(word.length)` steps.
while (pos < word.length) {
if (word[pos - 1] == word[cnd]) {
cnd = cnd + 1;
table[pos] = cnd;
pos = pos + 1;
} else if (cnd > 0) {
cnd = table[cnd];
} else {
table[pos] = 0;
pos = pos + 1;
}
}
// scan the string. This takes `O(string.length)` steps.
while (m + i < string.length) {
if (word[i] == string[m + i]) {
if (i == word.length - 1) {
return m;
}
i = i + 1;
} else {
if (table[i] > -1) {
m = m + i - table[i];
i = table[i];
} else {
i = 0;
m = m + 1;
}
}
}
// Returns -1 if the subsequence was not found in the sequence.
return -1;
}
init
Prelude: init
Source:
function init(xs) {
if (isString(xs)) {
return xs.slice(0, xs.length - 1);
}
return [].slice.call(xs, 0, xs.length - 1);
}
inits
Prelude: inits
Source:
function inits(xs) {
var result, current, i, length;
if (isArray(xs)) {
result = [[]];
current = [];
length = xs.length;
for (i = 0; i < length; i += 1) {
current = current.concat(xs[i]);
result.push(current);
}
return result;
}
// TODO the assumption is it's a string now
result = [''];
current = '';
length = xs.length;
for (i = 0; i < length; i += 1) {
current += xs[i];
result.push(current);
}
return result;
}
insert
Prelude: insert
Source:
var insert = /* this is a composed function */
insertBy
Prelude: insertBy
Source:
function insertBy(f, x, xs) {
for (var i = 0; i < xs.length; i++) {
if (f(x, xs[i]) <= 0) {
return concat([xs.slice(0,i), x, xs.slice(i)]);
}
}
return append(xs, x);
}
intercalate
Prelude: intercalate
Source:
function intercalate(x, xs) {
return concat(intersperse(x, xs));
}
intersect
Prelude: intersect
Source:
function intersect(xs, ys) {
var set = new Set();
var zs = [];
var i;
for (i = 0; i < ys.length; i++) {
set.add(ys[i]);
}
for (i = 0; i < xs.length; i++) {
if (set.has(xs[i])) {
zs.push(xs[i]);
}
}
return zs;
}
intersperse
Prelude: intersperse
Source:
function intersperse(x, xs) {
if (xs.length === 0) {
return [];
}
var z = [xs[0]];
for (var i = 1; i < xs.length; i++) {
z.push(x);
z.push(xs[i]);
}
return z;
}
last
Prelude: last
Source:
function last(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs[xs.length - 1];
case 'list':
if (xs.isEmpty()) {
return undefined;
}
for (var ts = xs.tail(); !ts.isEmpty();) {
xs = xs.tail();
ts = xs.tail();
}
return xs.head();
default:
error(TypeError);
}
}
length
Prelude: length
Source:
function length(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs.length;
case 'list':
var count = 0;
while (!xs.isEmpty()) {
count += 1;
xs = xs.tail();
}
return count;
case 'stream':
return Infinity;
case 'object':
return Object.keys(xs).length;
default:
error(TypeError);
}
}
listToMaybe
Source:
function listToMaybe(xs) {
if (is(List, xs)) {
return xs.isEmpty() ? null : xs.head();
}
throw new TypeError();
}
lookup
Prelude: lookup
Source:
function lookup(x, xs) {
if (isArray(xs)) {
for (var i = 0; i < xs.length; i++) {
if (xs[i] && eq(xs[i][0], x)) {
return xs[i][1];
}
}
}
return xs[x];
}
lt
<LT
Prelude: <
Source:
function lt(a, b) {
return compare(a, b) < 0;
}
lte
<=LTE
Prelude: <=
Source:
function lte(a, b) {
return compare(a, b) <= 0;
}
map
fmap
Prelude: fmap
Source:
function map(f, xs) {
var i, ys;
switch (typeOf(xs)) {
case 'array':
return mapArray(f, xs);
case 'string':
return arrayToString(mapArray(f, xs));
case 'list':
if (xs.isEmpty()) {
return xs;
}
/* falls through */
case 'stream':
return new List(lazy(function () {
return f(xs.head());
}), lazy(function () {
return map(f, xs.tail());
}));
case 'object':
ys = {};
var ks = Object.keys(xs);
for (var j = 0; j < ks.length; j += 1) {
ys[ks[j]] = f(xs[ks[j]], ks[j]);
}
return ys;
}
}
max
Prelude: max
Source:
function max(a, b) {
return compare(a, b) > 0 ? a : b;
}
maximum
Prelude: maximum
Source:
var maximum = /* this is a composed function */
maximumBy
Prelude: maximumBy
Source:
function maximumBy(f, xs) {
return foldl1(function (a, b) {
if (f(a, b) > 0) {
return a;
}
return b;
}, xs);
}
min
Prelude: min
Source:
function min(a, b) {
return compare(a, b) < 0 ? a : b;
}
minimum
Prelude: minimum
Source:
var minimum = /* this is a composed function */
minimumBy
Prelude: minimumBy
Source:
function minimumBy(f, xs) {
return foldl1(function (a, b) {
if (f(a, b) < 0) {
return a;
}
return b;
}, xs);
}
neq
/=!=<>NEQ
Prelude: /=
Source:
function neq(a, b) {
return !eq(a, b);
}
notElem
Prelude: notElem
Source:
function notElem(x, xs) {
for (var i = 0; i < xs.length; i++) {
if (eq(xs[i], x)) {
return false;
}
}
return true;
}
nub
Prelude: nub
Source:
function nub(xs) {
var set = new Set();
var zs = [];
for (var i = 0; i < xs.length; i++) {
if (!set.has(xs[i])) {
zs.push(xs[i]);
set.add(xs[i]);
}
}
return zs;
}
or
Prelude: or
Source:
var or = /* this is a composed function */
partition
Prelude: partition
Source:
function _partition(p, xs) {
var as = [];
var bs = [];
for (var i = 0; i < xs.length; i++) {
(p(xs[i]) ? as : bs).push(xs[i]);
}
if (isString(xs)) {
return tuple(arrayToString(as), arrayToString(bs));
}
return tuple(as, bs);
}
product
Prelude: product
Source:
var product = /* this is a composed function */
replicate
Prelude: replicate
Source:
function replicate(n, x) {
var xs = [];
for (var i = 0; i < n; i++) {
xs.push(x);
}
return xs;
}
reverse
Prelude: reverse
Source:
function reverse(xs) {
var zs = isString(xs) ? ''.split.call(xs, '') : [].slice.call(xs);
zs.reverse();
return isString(xs) ? zs.join('') : zs;
}
scanl
Prelude: scanl
Source:
function scanl(f, x, xs) {
var zs = [x];
for (var i = 0; i < xs.length; i++) {
x = f(x, xs[i]);
zs.push(x);
}
return zs;
}
scanl1
Prelude: scanl1
Source:
function scanl1(f, xs) {
var x = xs[0];
var zs = [x];
for (var i = 1; i < xs.length; i++) {
x = f(x, xs[i]);
zs.push(x);
}
return zs;
}
scanr
Prelude: scanr
Source:
function scanr(f, x, xs) {
var zs = [x];
for (var i = xs.length - 1; i >= 0; i--) {
x = f(xs[i], x);
zs.unshift(x);
}
return zs;
}
scanr1
Prelude: scanr1
Source:
function scanr1(f, xs) {
var x = xs[xs.length - 1];
var zs = [x];
for (var i = xs.length - 2; i >= 0; i--) {
x = f(xs[i], x);
zs.unshift(x);
}
return zs;
}
select
Source:
function select(path, object) {
return foldl(at, object, path.split(/\./));
}
sinh
Prelude: sinh
Source:
function sinh(x) {
return (Math.exp(x) - Math.exp(-x)) / 2;
}
sort
Prelude: sort
Source:
function sort(xs) {
if (xs.length <= 1) {
return xs;
}
var zs = isString(xs) ? ''.split.call(xs, '') : [].slice.call(xs);
if (isNumber(zs[0])) {
zs.sort(function (a, b) { return a - b; });
} else if (isString(zs[0])) {
zs.sort(function (a, b) { return a.localeCompare(b); });
} else {
zs.sort(compare);
}
return isString(xs) ? zs.join('') : zs;
}
sortBy
Prelude: sortBy
Source:
function sortBy(fn, xs) {
if (xs.length <= 1) {
return xs;
}
var yesItsAString = isString(xs);
var zs = yesItsAString ? ''.split.call(xs, '') : [].slice.call(xs);
zs.sort(fn);
return yesItsAString ? zs.join('') : zs;
}
span
Prelude: span
Source:
function span(p, xs) {
var i = 0;
while (i < xs.length && p(xs[i])) {
i++;
}
return tuple(xs.slice(0, i), xs.slice(i));
}
splitAt
Prelude: splitAt
Source:
function splitAt(n, xs) {
return tuple(take(n, xs), drop(n, xs));
}
tail
Prelude: tail
Source:
function tail(xs) {
switch (typeOf(xs)) {
case 'array':
return [].slice.call(xs, 1);
case 'string':
return "".slice.call(xs, 1);
case 'list':
case 'stream':
return xs.tail();
default:
error(TypeError);
}
}
tails
Prelude: tails
Source:
function tails(xs) {
var result, current, i;
if (isArray(xs)) {
result = [[]];
current = [];
for (i = xs.length - 1; i >= 0; i -= 1) {
current = [xs[i]].concat(current);
result.unshift(current);
}
return result;
}
// TODO the assumption is it's a string now
result = [''];
current = '';
for (i = xs.length - 1; i >= 0; i -= 1) {
current = xs[i] + current;
result.unshift(current);
}
return result;
}
take
Prelude: take
Source:
function take(n, xs) {
switch (typeOf(xs)) {
case 'string':
return "".slice.call(xs, 0, n);
case 'array':
return [].slice.call(xs, 0, n);
case 'list':
case 'stream':
return takeGenerator(n, xs);
default:
error(TypeError);
}
}
takeWhile
Prelude: takeWhile
Source:
function takeWhile(p, xs) {
var i = 0;
while (i < xs.length && p(xs[i])) {
i++;
}
return xs.slice(0, i);
}
transpose
Prelude: transpose
Source:
function transpose(xss) {
if (!isArray(xss)) {
var zss = {};
var ks = Object.keys(xss);
for (var k = 0; k < ks.length; k++) {
zss[xss[ks[k]]] = ks[k];
}
return zss;
}
var j = 0;
var zs = [];
var current;
do {
current = [];
for (var i = 0; i < xss.length; i++) {
if (xss[i][j] !== undefined) {
current.push(xss[i][j]);
}
}
j += 1;
} while (current.length > 0 && zs.push(current));
if (isString(xss[0])) {
zs = map(arrayToString, zs);
}
return zs;
}
union
Prelude: union
Source:
function union(xs, ys) {
var set = new Set();
var zs = [];
var i;
for (i = 0; i < xs.length; i++) {
zs.push(xs[i]);
set.add(xs[i]);
}
for (i = 0; i < ys.length; i++) {
if (!set.has(ys[i])) {
zs.push(ys[i]);
}
}
return zs;
}
Appendix
Coverage of Haskell Prelude
Prelude functions supported in Nodash
- !!
- $
- &&
- *
- **
- +
- ++
- ,
- -
- .
- /
- /=
- :
- <
- <=
- ==
- >
- >=
- ^
- ^^
- abs
- acos
- acosh
- all
- and
- any
- asin
- asinh
- atan
- atanh
- break
- ceiling
- compare
- concat
- concatMap
- const
- cos
- cosh
- curry
- cycle
- div
- divMod
- drop
- either
- elem
- even
- exp
- filter
- flip
- floor
- fmap
- foldl
- foldl1
- foldr
- foldr1
- fst
- gcd
- head
- id
- init
- iterate
- last
- lcm
- length
- lines
- log
- logBase
- lookup
- map
- max
- maximum
- maybe
- min
- minimum
- mod
- negate
- not
- notElem
- odd
- or
- product
- properFraction
- quot
- quotRem
- recip
- rem
- repeat
- replicate
- reverse
- round
- scanl
- scanl1
- scanr
- scanr1
- signum
- sin
- sinh
- snd
- span
- splitAt
- sqrt
- subtract
- sum
- tail
- take
- takeWhile
- tan
- tanh
- truncate
- uncurry
- unlines
- until
- unwords
- words
- zip
- zip3
- zipWith
- zipWith3
- ||
Prelude functions missing from Nodash
- $!
- =<<
- >>
- >>=
- FilePath
- IOError
- appendFile
- asTypeOf
- atan2
- catch
- decodeFloat
- dropWhie
- encodeFloat
- enumFrom
- enumFromThen
- enumFromThenTo
- enumFromTo
- error
- exponent
- fail
- floatDigits
- floatRadix
- floatRange
- fromEnum
- fromInteger
- fromIntegral
- fromRational
- getChar
- getContents
- getLine
- interact
- ioError
- isDenormalized
- isIEEE
- isInfinite
- isNaN
- isNegativeZero
- lex
- mapM
- mapM_
- maxBound
- minBound
- null
- otherwise
- pi
- pitStr
- pred
- print
- putChar
- putStrLn
- read
- readFile
- readIO
- readList
- readLn
- readParen
- reads
- readsPrec
- realToFrac
- return
- scaleFloat
- seq
- sequence
- sequence_
- show
- showChar
- showList
- showParen
- showString
- shows
- showsPrec
- significand
- succ
- toEnum
- toInteger
- toRational
- undefined
- unzip
- unzip3
- userError
- writeFile
Nodash-specific additions
- Either
- Left
- List
- Right
- Stream
- Thunk
- Tuple
- arrayToString
- async
- bool
- catMaybes
- chr
- classOf
- clone
- comparing
- compose2
- curried
- each
- emptyList
- fromLeft
- fromMaybe
- fromRight
- idf
- indexOf
- install
- invoke
- is
- isArguments
- isArray
- isAsciiLetter
- isBoolean
- isDate
- isEmpty
- isFunction
- isInteger
- isJust
- isLeft
- isLetter
- isLower
- isNothing
- isNull
- isNumber
- isNumeric
- isObject
- isRegExp
- isRight
- isString
- isUndefined
- isUpper
- keys
- lazy
- lefts
- listToArray
- listToMaybe
- listToString
- mapMaybe
- match
- maybeToList
- objectToArray
- on
- ord
- partitionEithers
- pipe
- range
- rangeStep
- register
- resolveThunk
- rights
- run
- select
- singleton
- tuple3
- tuple4
- tuplesToObject
- typeOf
- values
any Prelude: any
Source:
function any(p, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
return true;
}
}
return false;
}
append ++ Prelude: ++
Source:
function append(xs, ys) {
switch (typeOf(xs)) {
case 'list':
return appendList(xs, ys);
case 'string':
return xs + ys;
case 'array':
return [].concat.call(xs, ys);
default:
error(TypeError);
}
}
at !!AT Prelude: !!
Source:
function at(xs, ix) {
if (xs === undefined) {
return xs;
}
return xs[ix];
}
break break_ Prelude: break
Source:
function break(p, xs) {
var i = 0;
while (i < xs.length && !p(xs[i])) {
i++;
}
return tuple(xs.slice(0, i), xs.slice(i));
}
clone
Source:
function clone(thing) {
if (typeof thing === 'object') {
if (thing === null) {
return null;
}
return map(clone, thing);
}
return thing;
}
compare Prelude: compare
Source:
function compare(a, b) {
switch (typeof a) {
case 'string':
return a.localeCompare(b);
case 'object':
if (isFunction(a.compareTo)) {
return a.compareTo(b);
} else if (isArray(a)) {
for (var i = 0; i < Math.min(a.length, b.length); i++) {
var r = compare(a[i], b[i]);
if (r !== 0) {
return r;
}
}
return 0;
}
return a.toString().localeCompare(b.toString());
case 'number':
return signum(a - b);
}
return undefined;
}
comparing
Source:
function comparing(f, a, b) {
return compare(f(a), f(b));
}
concat Prelude: concat
Source:
function concat(xs) {
if (isString(xs[0])) {
return xs.join('');
}
var zs = [];
var ks = Object.keys(xs);
for (var i = 0; i < ks.length; i++) {
[].push.apply(zs, xs[ks[i]]);
}
return zs;
}
concatMap Prelude: concatMap
Source:
var concatMap = /* this is a composed function */
cons : Prelude: :
Source:
function cons(x, xs) {
switch (typeOf(xs)) {
case 'array':
var zs = [].slice.call(xs);
zs.unshift(x);
return zs;
case 'string':
return x + xs;
case 'list':
return new List(x, xs);
case 'stream':
return new Stream(function () {
return tuple(x, xs);
});
default:
error(TypeError);
}
}
curried
Source:
function curried(fn) {
return funcs[fn.length](fn);
}
delete delete_ Prelude: delete
Source:
function delete(x, xs) {
var i = xs.indexOf(x);
if (i >= 0) {
return append(xs.slice(0,i), xs.slice(i+1));
}
return xs;
}
deleteBy Prelude: deleteBy
Source:
function deleteBy(p, x, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(x, xs[i])) {
return append(xs.slice(0,i), xs.slice(i+1));
}
}
return xs;
}
difference \\ Prelude: \\
Source:
function difference(xs, ys) {
var set = new Set();
var i;
for (i = 0; i < ys.length; i++) {
set.add(ys[i]);
}
var zs = [];
for (i = 0; i < xs.length; i++) {
if (!set.has(xs[i])) {
zs.push(xs[i]);
}
}
return isString(xs) ? arrayToString(zs) : zs;
}
drop Prelude: drop
Source:
function drop(n, xs) {
return xs.slice(n);
}
dropWhile Prelude: dropWhile
Source:
function dropWhile(p, xs) {
var i = 0;
while (i < xs.length && p(xs[i])) {
i++;
}
return xs.slice(i);
}
either Prelude: either
Source:
function either(afun, bfun, value) {
if (is(Left, value)) {
return afun(value.value());
} else if (is(Right, value)) {
return bfun(value.value());
} else {
fail();
}
}
elem Prelude: elem
Source:
function elem(x, xs) {
for (var i = 0; i < xs.length; i++) {
if (eq(xs[i], x)) {
return true;
}
}
return false;
}
elemIndex Prelude: elemIndex
Source:
function elemIndex(x, xs) {
return findIndex(eq(x), xs);
}
elemIndices Prelude: elemIndices
Source:
function elemIndices(x, xs) {
return findIndices(eq(x), xs);
}
emptyList
Source:
function emptyList() {
return emptyList;
}
eq ==EQ Prelude: ==
Source:
function eq(a, b) {
if (a === b) {
return true;
}
var ta = typeOf(a);
var tb = typeOf(b);
if (ta !== tb) {
return false;
}
switch (ta) {
case 'tuple':
return eq(a.fst(), b.fst()) && eq(a.snd(), b.snd());
case 'list':
return eq(a.head(), b.head()) && eq(a.tail(), b.tail());
case 'array':
case 'object':
if (a.constructor !== b.constructor) {
return false;
}
var k = union(Object.keys(a), Object.keys(b));
for (var i = 0; i < k.length; i++) {
if (!eq(a[k[i]], b[k[i]])) {
return false;
}
}
return true;
}
return false;
}
filter Prelude: filter
Source:
function filter(p, xs) {
var ys;
switch (typeOf(xs)) {
case 'array':
case 'string':
ys = [];
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
ys.push(xs[i]);
}
}
return isString(xs) ? arrayToString(ys) : ys;
default:
ys = {};
var ks = Object.keys(xs);
for (var j = 0; j < ks.length; j++) {
if (p(xs[ks[j]])) {
ys[ks[j]] = xs[ks[j]];
}
}
return ys;
}
}
find Prelude: find
Source:
function find(p, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
return xs[i];
}
}
return null;
}
findIndex Prelude: findIndex
Source:
function findIndex(p, xs) {
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
return i;
}
}
return null;
}
findIndices Prelude: findIndices
Source:
function findIndices(p, xs) {
var zs = [];
for (var i = 0; i < xs.length; i++) {
if (p(xs[i])) {
zs.push(i);
}
}
return zs;
}
foldl1 foldl1' Prelude: foldl1'
Source:
function foldl1(f, xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
var x = xs[0];
for (var i = 1; i < xs.length; i += 1) {
x = f(xs[i], x);
}
return x;
}
}
foldr1 Prelude: foldr1
Source:
function foldr1(f, xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
var x = xs[xs.length - 1];
for (var i = xs.length - 2; i >= 0; i -= 1) {
x = f(xs[i], x);
}
return x;
}
}
fromLeft
Source:
function fromLeft(thing) {
if (is(Left, thing)) {
return thing.value();
}
fail();
}
fromMaybe
Source:
function fromMaybe(def, maybe) {
if (isJust(maybe)) {
return maybe;
}
return def;
}
fromRight
Source:
function fromRight(thing) {
if (is(Right, thing)) {
return thing.value();
}
fail();
}
group Prelude: group
Source:
var group = /* this is a composed function */
groupBy Prelude: groupBy
Source:
function groupBy(p, xs) {
if (xs.length === 0) {
return [];
}
var zs = [];
var current = [xs[0]];
var last = xs[0];
for (var i = 1; i < xs.length; i++) {
if (p(xs[i], last)) {
current.push(xs[i]);
} else {
zs.push(current);
current = [xs[i]];
}
last = xs[i];
}
zs.push(current);
return isString(xs) ? map(arrayToString, zs) : zs;
}
gt >GT Prelude: >
Source:
function gt(a, b) {
return compare(a, b) > 0;
}
gte >=GTE Prelude: >=
Source:
function gte(a, b) {
return compare(a, b) >= 0;
}
head Prelude: head
Source:
function head(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs[0];
case 'list':
case 'stream':
return xs.head();
default:
error(TypeError);
}
}
indexOf
Source:
function indexOf(word, string) {
'use strict';
var m = 0;
var i = 0;
var table = [];
var pos = 2;
var cnd = 0;
table[0] = -1;
table[1] = 0;
// build the table for KMP. This takes `O(word.length)` steps.
while (pos < word.length) {
if (word[pos - 1] == word[cnd]) {
cnd = cnd + 1;
table[pos] = cnd;
pos = pos + 1;
} else if (cnd > 0) {
cnd = table[cnd];
} else {
table[pos] = 0;
pos = pos + 1;
}
}
// scan the string. This takes `O(string.length)` steps.
while (m + i < string.length) {
if (word[i] == string[m + i]) {
if (i == word.length - 1) {
return m;
}
i = i + 1;
} else {
if (table[i] > -1) {
m = m + i - table[i];
i = table[i];
} else {
i = 0;
m = m + 1;
}
}
}
// Returns -1 if the subsequence was not found in the sequence.
return -1;
}
init Prelude: init
Source:
function init(xs) {
if (isString(xs)) {
return xs.slice(0, xs.length - 1);
}
return [].slice.call(xs, 0, xs.length - 1);
}
inits Prelude: inits
Source:
function inits(xs) {
var result, current, i, length;
if (isArray(xs)) {
result = [[]];
current = [];
length = xs.length;
for (i = 0; i < length; i += 1) {
current = current.concat(xs[i]);
result.push(current);
}
return result;
}
// TODO the assumption is it's a string now
result = [''];
current = '';
length = xs.length;
for (i = 0; i < length; i += 1) {
current += xs[i];
result.push(current);
}
return result;
}
insert Prelude: insert
Source:
var insert = /* this is a composed function */
insertBy Prelude: insertBy
Source:
function insertBy(f, x, xs) {
for (var i = 0; i < xs.length; i++) {
if (f(x, xs[i]) <= 0) {
return concat([xs.slice(0,i), x, xs.slice(i)]);
}
}
return append(xs, x);
}
intercalate Prelude: intercalate
Source:
function intercalate(x, xs) {
return concat(intersperse(x, xs));
}
intersect Prelude: intersect
Source:
function intersect(xs, ys) {
var set = new Set();
var zs = [];
var i;
for (i = 0; i < ys.length; i++) {
set.add(ys[i]);
}
for (i = 0; i < xs.length; i++) {
if (set.has(xs[i])) {
zs.push(xs[i]);
}
}
return zs;
}
intersperse Prelude: intersperse
Source:
function intersperse(x, xs) {
if (xs.length === 0) {
return [];
}
var z = [xs[0]];
for (var i = 1; i < xs.length; i++) {
z.push(x);
z.push(xs[i]);
}
return z;
}
last Prelude: last
Source:
function last(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs[xs.length - 1];
case 'list':
if (xs.isEmpty()) {
return undefined;
}
for (var ts = xs.tail(); !ts.isEmpty();) {
xs = xs.tail();
ts = xs.tail();
}
return xs.head();
default:
error(TypeError);
}
}
length Prelude: length
Source:
function length(xs) {
switch (typeOf(xs)) {
case 'array':
case 'string':
return xs.length;
case 'list':
var count = 0;
while (!xs.isEmpty()) {
count += 1;
xs = xs.tail();
}
return count;
case 'stream':
return Infinity;
case 'object':
return Object.keys(xs).length;
default:
error(TypeError);
}
}
listToMaybe
Source:
function listToMaybe(xs) {
if (is(List, xs)) {
return xs.isEmpty() ? null : xs.head();
}
throw new TypeError();
}
lookup Prelude: lookup
Source:
function lookup(x, xs) {
if (isArray(xs)) {
for (var i = 0; i < xs.length; i++) {
if (xs[i] && eq(xs[i][0], x)) {
return xs[i][1];
}
}
}
return xs[x];
}
lt <LT Prelude: <
Source:
function lt(a, b) {
return compare(a, b) < 0;
}
lte <=LTE Prelude: <=
Source:
function lte(a, b) {
return compare(a, b) <= 0;
}
map fmap Prelude: fmap
Source:
function map(f, xs) {
var i, ys;
switch (typeOf(xs)) {
case 'array':
return mapArray(f, xs);
case 'string':
return arrayToString(mapArray(f, xs));
case 'list':
if (xs.isEmpty()) {
return xs;
}
/* falls through */
case 'stream':
return new List(lazy(function () {
return f(xs.head());
}), lazy(function () {
return map(f, xs.tail());
}));
case 'object':
ys = {};
var ks = Object.keys(xs);
for (var j = 0; j < ks.length; j += 1) {
ys[ks[j]] = f(xs[ks[j]], ks[j]);
}
return ys;
}
}
max Prelude: max
Source:
function max(a, b) {
return compare(a, b) > 0 ? a : b;
}
maximum Prelude: maximum
Source:
var maximum = /* this is a composed function */
maximumBy Prelude: maximumBy
Source:
function maximumBy(f, xs) {
return foldl1(function (a, b) {
if (f(a, b) > 0) {
return a;
}
return b;
}, xs);
}
min Prelude: min
Source:
function min(a, b) {
return compare(a, b) < 0 ? a : b;
}
minimum Prelude: minimum
Source:
var minimum = /* this is a composed function */
minimumBy Prelude: minimumBy
Source:
function minimumBy(f, xs) {
return foldl1(function (a, b) {
if (f(a, b) < 0) {
return a;
}
return b;
}, xs);
}
neq /=!=<>NEQ Prelude: /=
Source:
function neq(a, b) {
return !eq(a, b);
}
notElem Prelude: notElem
Source:
function notElem(x, xs) {
for (var i = 0; i < xs.length; i++) {
if (eq(xs[i], x)) {
return false;
}
}
return true;
}
nub Prelude: nub
Source:
function nub(xs) {
var set = new Set();
var zs = [];
for (var i = 0; i < xs.length; i++) {
if (!set.has(xs[i])) {
zs.push(xs[i]);
set.add(xs[i]);
}
}
return zs;
}
or Prelude: or
Source:
var or = /* this is a composed function */
partition Prelude: partition
Source:
function _partition(p, xs) {
var as = [];
var bs = [];
for (var i = 0; i < xs.length; i++) {
(p(xs[i]) ? as : bs).push(xs[i]);
}
if (isString(xs)) {
return tuple(arrayToString(as), arrayToString(bs));
}
return tuple(as, bs);
}
product Prelude: product
Source:
var product = /* this is a composed function */
replicate Prelude: replicate
Source:
function replicate(n, x) {
var xs = [];
for (var i = 0; i < n; i++) {
xs.push(x);
}
return xs;
}
reverse Prelude: reverse
Source:
function reverse(xs) {
var zs = isString(xs) ? ''.split.call(xs, '') : [].slice.call(xs);
zs.reverse();
return isString(xs) ? zs.join('') : zs;
}
scanl Prelude: scanl
Source:
function scanl(f, x, xs) {
var zs = [x];
for (var i = 0; i < xs.length; i++) {
x = f(x, xs[i]);
zs.push(x);
}
return zs;
}
scanl1 Prelude: scanl1
Source:
function scanl1(f, xs) {
var x = xs[0];
var zs = [x];
for (var i = 1; i < xs.length; i++) {
x = f(x, xs[i]);
zs.push(x);
}
return zs;
}
scanr Prelude: scanr
Source:
function scanr(f, x, xs) {
var zs = [x];
for (var i = xs.length - 1; i >= 0; i--) {
x = f(xs[i], x);
zs.unshift(x);
}
return zs;
}
scanr1 Prelude: scanr1
Source:
function scanr1(f, xs) {
var x = xs[xs.length - 1];
var zs = [x];
for (var i = xs.length - 2; i >= 0; i--) {
x = f(xs[i], x);
zs.unshift(x);
}
return zs;
}
select
Source:
function select(path, object) {
return foldl(at, object, path.split(/\./));
}
sinh Prelude: sinh
Source:
function sinh(x) {
return (Math.exp(x) - Math.exp(-x)) / 2;
}
sort Prelude: sort
Source:
function sort(xs) {
if (xs.length <= 1) {
return xs;
}
var zs = isString(xs) ? ''.split.call(xs, '') : [].slice.call(xs);
if (isNumber(zs[0])) {
zs.sort(function (a, b) { return a - b; });
} else if (isString(zs[0])) {
zs.sort(function (a, b) { return a.localeCompare(b); });
} else {
zs.sort(compare);
}
return isString(xs) ? zs.join('') : zs;
}
sortBy Prelude: sortBy
Source:
function sortBy(fn, xs) {
if (xs.length <= 1) {
return xs;
}
var yesItsAString = isString(xs);
var zs = yesItsAString ? ''.split.call(xs, '') : [].slice.call(xs);
zs.sort(fn);
return yesItsAString ? zs.join('') : zs;
}
span Prelude: span
Source:
function span(p, xs) {
var i = 0;
while (i < xs.length && p(xs[i])) {
i++;
}
return tuple(xs.slice(0, i), xs.slice(i));
}
splitAt Prelude: splitAt
Source:
function splitAt(n, xs) {
return tuple(take(n, xs), drop(n, xs));
}
tail Prelude: tail
Source:
function tail(xs) {
switch (typeOf(xs)) {
case 'array':
return [].slice.call(xs, 1);
case 'string':
return "".slice.call(xs, 1);
case 'list':
case 'stream':
return xs.tail();
default:
error(TypeError);
}
}
tails Prelude: tails
Source:
function tails(xs) {
var result, current, i;
if (isArray(xs)) {
result = [[]];
current = [];
for (i = xs.length - 1; i >= 0; i -= 1) {
current = [xs[i]].concat(current);
result.unshift(current);
}
return result;
}
// TODO the assumption is it's a string now
result = [''];
current = '';
for (i = xs.length - 1; i >= 0; i -= 1) {
current = xs[i] + current;
result.unshift(current);
}
return result;
}
take Prelude: take
Source:
function take(n, xs) {
switch (typeOf(xs)) {
case 'string':
return "".slice.call(xs, 0, n);
case 'array':
return [].slice.call(xs, 0, n);
case 'list':
case 'stream':
return takeGenerator(n, xs);
default:
error(TypeError);
}
}
takeWhile Prelude: takeWhile
Source:
function takeWhile(p, xs) {
var i = 0;
while (i < xs.length && p(xs[i])) {
i++;
}
return xs.slice(0, i);
}
transpose Prelude: transpose
Source:
function transpose(xss) {
if (!isArray(xss)) {
var zss = {};
var ks = Object.keys(xss);
for (var k = 0; k < ks.length; k++) {
zss[xss[ks[k]]] = ks[k];
}
return zss;
}
var j = 0;
var zs = [];
var current;
do {
current = [];
for (var i = 0; i < xss.length; i++) {
if (xss[i][j] !== undefined) {
current.push(xss[i][j]);
}
}
j += 1;
} while (current.length > 0 && zs.push(current));
if (isString(xss[0])) {
zs = map(arrayToString, zs);
}
return zs;
}
union Prelude: union
Source:
function union(xs, ys) {
var set = new Set();
var zs = [];
var i;
for (i = 0; i < xs.length; i++) {
zs.push(xs[i]);
set.add(xs[i]);
}
for (i = 0; i < ys.length; i++) {
if (!set.has(ys[i])) {
zs.push(ys[i]);
}
}
return zs;
}