All new
alle new
This commit is contained in:
1 parent
da64472251
commit
5b20adee48
1605 files changed
+396517
-1674
No files matched your search
+1
@@ -0,0 +1 @@
|
||||
node_modules
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
Copyright (c) 2013, Michael Williamson
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
# options for node.js
|
||||
|
||||
An implementation of the option type, sometimes known as the maybe type.
|
||||
|
||||
An instance of an option type is an optional value. Either it's `none`, or an
|
||||
instance of `Some`:
|
||||
|
||||
```javascript
|
||||
var option = require("option");
|
||||
|
||||
var some = option.some("Bob");
|
||||
var none = option.none;
|
||||
```
|
||||
|
||||
A function that returns an optional string isn't that different from a function
|
||||
that returns a string or `null`. The advantage over null is that options
|
||||
provide a number of functions that help with manipulating optional values.
|
||||
|
||||
```javascript
|
||||
function greet(user) {
|
||||
return "Hello " + user.name().valueOrElse("Anonymous");
|
||||
}
|
||||
```
|
||||
|
||||
## Methods
|
||||
|
||||
### isNone() and isSome()
|
||||
|
||||
* `some(value).isNone()` returns `false`
|
||||
* `some(value).isSome()` returns `true`
|
||||
* `none.isNone()` returns `true`
|
||||
* `none.isSome()` returns `false`
|
||||
|
||||
### value()
|
||||
|
||||
* `some(value).value()` returns `value`
|
||||
* `none.value()` throws an error
|
||||
|
||||
### map(*func*)
|
||||
|
||||
* `some(value).map(func)` returns `some(func(value))`
|
||||
* `none.map(func)` returns `none`
|
||||
|
||||
### flatMap(*func*)
|
||||
|
||||
Conventionally used when `func` returns another option.
|
||||
|
||||
* `some(value).flatMap(func)` returns `func(value)`
|
||||
* `none.flatMap(func)` returns `none`
|
||||
|
||||
### filter(*predicate*)
|
||||
|
||||
* `some(value).filter(predicate)` returns:
|
||||
* `some(value)` if `predicate(value) === true`
|
||||
* `none` if `predicate(value) === false`
|
||||
* `none.filter(predicate)` returns `none`
|
||||
|
||||
### toArray()
|
||||
|
||||
* `some(value).toArray()` returns `[some]`
|
||||
* `none.toArray()` returns `[]`
|
||||
|
||||
### orElse(*other*)
|
||||
|
||||
If `other` is a function (`other` conventionally returning another option):
|
||||
|
||||
* `some(value).orElse(other)` returns `some(value)`
|
||||
* `none.orElse(other)` returns `other()`
|
||||
|
||||
If `other` is not a function (`other` conventionally being another option):
|
||||
|
||||
* `some(value).orElse(other)` returns `some(value)`
|
||||
* `none.orElse(other)` returns `other`
|
||||
|
||||
### valueOrElse(*other*)
|
||||
|
||||
If `other` is a function:
|
||||
|
||||
* `some(value).valueOrElse(other)` returns `value`
|
||||
* `none.valueOrElse(other)` returns `other()`
|
||||
|
||||
If `other` is not a function:
|
||||
|
||||
* `some(value).valueOrElse(other)` returns `value`
|
||||
* `none.valueOrElse(other)` returns `other`
|
||||
|
||||
## Functions
|
||||
|
||||
### option.isOption(*value*)
|
||||
|
||||
* `option.isOption(value)` returns `true` if `value` is `option.none` or `option.some(x)`.
|
||||
|
||||
### option.fromNullable(*value*)
|
||||
|
||||
* If `value` is `null` or `undefined`, `option.fromNullable(value)` returns `option.none`.
|
||||
* Otherwise, returns `option.some(value)`.
|
||||
For instance, `option.fromNullable(5)` returns `option.some(5)`.
|
||||
|
||||
## Installation
|
||||
|
||||
npm install option
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
exports.none = Object.create({
|
||||
value: function() {
|
||||
throw new Error('Called value on none');
|
||||
},
|
||||
isNone: function() {
|
||||
return true;
|
||||
},
|
||||
isSome: function() {
|
||||
return false;
|
||||
},
|
||||
map: function() {
|
||||
return exports.none;
|
||||
},
|
||||
flatMap: function() {
|
||||
return exports.none;
|
||||
},
|
||||
filter: function() {
|
||||
return exports.none;
|
||||
},
|
||||
toArray: function() {
|
||||
return [];
|
||||
},
|
||||
orElse: callOrReturn,
|
||||
valueOrElse: callOrReturn
|
||||
});
|
||||
|
||||
function callOrReturn(value) {
|
||||
if (typeof(value) == "function") {
|
||||
return value();
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
exports.some = function(value) {
|
||||
return new Some(value);
|
||||
};
|
||||
|
||||
var Some = function(value) {
|
||||
this._value = value;
|
||||
};
|
||||
|
||||
Some.prototype.value = function() {
|
||||
return this._value;
|
||||
};
|
||||
|
||||
Some.prototype.isNone = function() {
|
||||
return false;
|
||||
};
|
||||
|
||||
Some.prototype.isSome = function() {
|
||||
return true;
|
||||
};
|
||||
|
||||
Some.prototype.map = function(func) {
|
||||
return new Some(func(this._value));
|
||||
};
|
||||
|
||||
Some.prototype.flatMap = function(func) {
|
||||
return func(this._value);
|
||||
};
|
||||
|
||||
Some.prototype.filter = function(predicate) {
|
||||
return predicate(this._value) ? this : exports.none;
|
||||
};
|
||||
|
||||
Some.prototype.toArray = function() {
|
||||
return [this._value];
|
||||
};
|
||||
|
||||
Some.prototype.orElse = function(value) {
|
||||
return this;
|
||||
};
|
||||
|
||||
Some.prototype.valueOrElse = function(value) {
|
||||
return this._value;
|
||||
};
|
||||
|
||||
exports.isOption = function(value) {
|
||||
return value === exports.none || value instanceof Some;
|
||||
};
|
||||
|
||||
exports.fromNullable = function(value) {
|
||||
if (value == null) {
|
||||
return exports.none;
|
||||
}
|
||||
return new Some(value);
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "option",
|
||||
"version": "0.2.4",
|
||||
"author": "Michael Williamson <mike@zwobble.org>",
|
||||
"description": "The option type, also known as the maybe type, for JavaScript",
|
||||
"license": "BSD-2-Clause",
|
||||
"scripts": {
|
||||
"test": "nodeunit test"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mwilliamson/node-options.git"
|
||||
},
|
||||
"dependencies": {
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodeunit": "latest"
|
||||
},
|
||||
"keywords": [
|
||||
"option",
|
||||
"maybe"
|
||||
]
|
||||
}
|
||||
+174
@@ -0,0 +1,174 @@
|
||||
var options = require("..");
|
||||
|
||||
exports.noneIsAnOption = function(test) {
|
||||
test.equal(true, options.isOption(options.none));
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports.someIsAnOption = function(test) {
|
||||
test.equal(true, options.isOption(options.some(4)));
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports.nullIsNotAnOption = function(test) {
|
||||
test.equal(false, options.isOption(null));
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports.stringIsNotAnOption = function(test) {
|
||||
test.equal(false, options.isOption("surrender"));
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports["none.isNone() returns true"] = function(test) {
|
||||
test.equal(true, options.none.isNone());
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports["none.isSome() returns false"] = function(test) {
|
||||
test.equal(false, options.none.isSome());
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports["some(_).isNone() returns false"] = function(test) {
|
||||
test.equal(false, options.some(1).isNone());
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports["some(_).isSome() returns true"] = function(test) {
|
||||
test.equal(true, options.some(1).isSome());
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports.fromNullableConvertsNullToNone = function(test) {
|
||||
test.deepEqual(options.none, options.fromNullable(null));
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports.fromNullableConvertsUndefinedToNone = function(test) {
|
||||
test.deepEqual(options.none, options.fromNullable(undefined));
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports.fromNullableConvertsNumberToSome = function(test) {
|
||||
test.deepEqual(options.some(5), options.fromNullable(5));
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports.mappingOverNoneHasNoEffect = function(test) {
|
||||
test.equal(options.none, options.none.map(function() { return true }));
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports.mappingOverSomeAppliesFunctionToValue = function(test) {
|
||||
test.deepEqual(options.some(4), options.some(2).map(function(value) {
|
||||
return value * value;
|
||||
}));
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports["none.flatMap(_) returns none"] = function(test) {
|
||||
test.deepEqual(options.none, options.none.flatMap(function(value) {
|
||||
return options.some("apple");
|
||||
}));
|
||||
test.done();
|
||||
};
|
||||
|
||||
|
||||
exports["when func(value) is none, then some(value).flatMap(func) returns none"] = function(test) {
|
||||
test.deepEqual(options.none, options.some(2).flatMap(function(value) {
|
||||
return options.none;
|
||||
}));
|
||||
test.done();
|
||||
};
|
||||
|
||||
|
||||
exports["when func(value) is some(result), then some(value).flatMap(func) returns some(result)"] = function(test) {
|
||||
test.deepEqual(options.some(4), options.some(2).flatMap(function(value) {
|
||||
return options.some(value * value);
|
||||
}));
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports.noneToArrayIsEmptyArray = function(test) {
|
||||
test.deepEqual([], options.none.toArray());
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports.someToArrayIsSingleElementArray = function(test) {
|
||||
test.deepEqual(["apple"], options.some("apple").toArray());
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports.noneValueOrElseCallsPassedValueIfItsAFunction = function(test) {
|
||||
test.deepEqual(4, options.none.valueOrElse(function() { return 4; }));
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports.noneValueOrElseReturnsArgumentIfItsNotAFunction = function(test) {
|
||||
test.deepEqual(4, options.none.valueOrElse(4));
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports.someValueOrElseReturnsWrappedValue = function(test) {
|
||||
test.deepEqual(1, options.some(1).valueOrElse(function() { return 4; }));
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports.noneOrElseReturnsArgumentIfItsNotAFunction = function(test) {
|
||||
test.deepEqual(options.some(4), options.none.orElse(options.some(4)));
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports.noneOrElseCallsArgumentIfItsAFunction = function(test) {
|
||||
test.deepEqual(options.some(4), options.none.orElse(function() { return options.some(4); }));
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports.someOrElseReturnsTheCurrentOption = function(test) {
|
||||
test.deepEqual(options.some(1), options.some(1).orElse(4));
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports.callingValueOnNoneRaisesError = function(test) {
|
||||
test.throws(function(){
|
||||
options.none.value();
|
||||
}, /Called value on none/);
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports.callingValueOnSomeReturnsValue = function(test) {
|
||||
test.deepEqual(4, options.some(4).value());
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports["none.filter returns none"] = function(test) {
|
||||
function equals3(x) {
|
||||
return x === 3;
|
||||
}
|
||||
|
||||
test.deepEqual(options.none.filter(equals3), options.none);
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports["when predicate(value) is true, some(value).filter(predicate) returns some(value)"] = function(test) {
|
||||
var some3 = options.some(3);
|
||||
|
||||
function equals3(x) {
|
||||
return x === 3;
|
||||
}
|
||||
|
||||
test.deepEqual(some3.filter(equals3), some3);
|
||||
test.done();
|
||||
};
|
||||
|
||||
exports["when predicate(value) is false, some(value).filter(predicate) returns none"] = function(test) {
|
||||
var some11 = options.some(11);
|
||||
|
||||
function equals3(x) {
|
||||
return x === 3;
|
||||
}
|
||||
|
||||
test.deepEqual(some11.filter(equals3), options.none);
|
||||
test.done();
|
||||
};
|
||||
Reference in new issue
Block a user