├── examples ├── blah.txt ├── gadsby.txt ├── 1.js ├── 2.js ├── 5.js ├── 3.js ├── 4.js ├── 6.js ├── 7.js └── holy_smokes.js ├── examples after ├── blah.txt ├── gadsby.txt ├── 1.js ├── 2.js ├── 5.js ├── 3.js ├── 4.js ├── 6.js ├── 7.js └── holy_smokes.js ├── support ├── lambdajs │ ├── test │ │ ├── spec │ │ │ ├── SpecHelper.js │ │ │ ├── numbers_spec.js │ │ │ ├── regex_spec.js │ │ │ ├── objects_spec.js │ │ │ ├── lambdajs_spec.js │ │ │ ├── utils_spec.js │ │ │ ├── strings_spec.js │ │ │ └── arrays_spec.js │ │ ├── helpers │ │ │ └── SpecHelper.js │ │ ├── lib │ │ │ └── jasmine-1.2.0 │ │ │ │ ├── MIT.LICENSE │ │ │ │ ├── jasmine.css │ │ │ │ └── jasmine-html.js │ │ └── SpecRunner.html │ ├── README.md │ ├── docs │ │ └── docs_files │ │ │ ├── prettify.css │ │ │ ├── style.css │ │ │ ├── functional-js │ │ │ └── github-btn.html │ ├── utils.js │ └── lambda.js ├── node-promise │ ├── fs-promise.js │ ├── package.json │ ├── README.md │ └── promise.js ├── promise.js └── arrow.js ├── vendor ├── typeclasses │ ├── README.md │ ├── index.js │ ├── support │ │ └── types.js │ ├── applicative.js │ ├── functor.js │ ├── monoid.js │ ├── monad.js │ └── amd │ │ └── index.js ├── PreludeJS │ ├── README.md │ ├── package.json │ ├── prelude.js │ └── specs │ │ └── prelude_spec.coffee └── FunctionalJS │ ├── README.md │ ├── package.json │ ├── specs │ └── functional.spec.coffee │ └── functional.js └── README.md /examples/blah.txt: -------------------------------------------------------------------------------- 1 | blah.txt -------------------------------------------------------------------------------- /examples after/blah.txt: -------------------------------------------------------------------------------- 1 | blah.txt -------------------------------------------------------------------------------- /support/lambdajs/test/spec/SpecHelper.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vendor/typeclasses/README.md: -------------------------------------------------------------------------------- 1 | typeclasses 2 | =========== 3 | 4 | Fun with typeclasses! -------------------------------------------------------------------------------- /vendor/PreludeJS/README.md: -------------------------------------------------------------------------------- 1 | PreludeJS 2 | ========= 3 | 4 | A collection of functions often used with the functional paradigm -------------------------------------------------------------------------------- /support/lambdajs/test/helpers/SpecHelper.js: -------------------------------------------------------------------------------- 1 | if(typeof require == "object") { 2 | console.log("DO IT!") 3 | require('../lambda') 4 | } -------------------------------------------------------------------------------- /vendor/FunctionalJS/README.md: -------------------------------------------------------------------------------- 1 | FunctionalJS 2 | ============ 3 | 4 | beefed up version of osteeles' library: http://osteele.com/sources/javascript/functional/ -------------------------------------------------------------------------------- /vendor/typeclasses/index.js: -------------------------------------------------------------------------------- 1 | require('./support/types'); 2 | require('./functor'); 3 | require('./applicative'); 4 | require('./monoid'); 5 | require('./monad'); 6 | require('./promise'); 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Patterns talk. 2 | 3 | Run this this stuff with node: 4 | 5 | $> node examples/1.js 6 | 7 | *Some of these are out of date* 8 | Pointfree fantasy has changed `flatMap` to `chain` and `fmap` to `map` 9 | -------------------------------------------------------------------------------- /examples/gadsby.txt: -------------------------------------------------------------------------------- 1 | If youth, throughout all history, had a champion to stand up for it; to show a doubting world that a child can think; and, possibly, do it practically; you wouldn't constantly run across folks today who claim that "a child don't know anything." A child's brain starts functioning at birth; and has, amongst its many infant convolutions, thousands of dormant atoms, into which God has put a mystic possibility for noticing an adults act, and figuring out its purport. -------------------------------------------------------------------------------- /support/lambdajs/README.md: -------------------------------------------------------------------------------- 1 | LambdaJS 2 | ======== 3 | The full ECMAScript API done a functional way. 4 | 5 | RULES: 6 | 1. The data comes last. E.g: str.method(arg) -> method(arg, str) 7 | 2. Everything is curried 8 | 3. Functions with optional arguments are split into two functions. One with _ at the end that takes the options. E.g: indexOf(x,str) & indexOf_(x,y,str) 9 | 4. Every function is pure 10 | 11 | Thanks so much to @casperin for doing a ton of the work on this! -------------------------------------------------------------------------------- /examples after/gadsby.txt: -------------------------------------------------------------------------------- 1 | If youth, throughout all history, had a champion to stand up for it; to show a doubting world that a child can think; and, possibly, do it practically; you wouldn't constantly run across folks today who claim that "a child don't know anything." A child's brain starts functioning at birth; and has, amongst its many infant convolutions, thousands of dormant atoms, into which God has put a mystic possibility for noticing an adults act, and figuring out its purport. -------------------------------------------------------------------------------- /support/node-promise/fs-promise.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Node fs module that returns promises 3 | */ 4 | 5 | var fs = require("fs"), 6 | convertNodeAsyncFunction = require("./promise").convertNodeAsyncFunction; 7 | 8 | // convert all the non-sync functions 9 | for (var i in fs) { 10 | if (!(i.match(/Sync$/))) { 11 | exports[i] = convertNodeAsyncFunction(fs[i]); 12 | } 13 | } 14 | 15 | // convert the functions that don't have a declared callback 16 | exports.writeFile = convertNodeAsyncFunction(fs.writeFile, true); 17 | exports.readFile = convertNodeAsyncFunction(fs.readFile, true); -------------------------------------------------------------------------------- /examples/1.js: -------------------------------------------------------------------------------- 1 | require('../support/lambdajs/utils').expose(global); 2 | require('../support/lambdajs/lambda').expose(); 3 | require('pointfree-fantasy').expose(global); 4 | require('lenses').expose(global); 5 | 6 | var markdown = require('markdown').parse; 7 | 8 | 9 | 10 | var comment = {id: 2, body: "this is a *great* post!", viewed: false}; 11 | 12 | var showOnScreen = log; 13 | 14 | var prog = compose(showOnScreen, markdown, pluck('body')); 15 | 16 | prog(comment); 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /support/lambdajs/test/spec/numbers_spec.js: -------------------------------------------------------------------------------- 1 | describe("Numbers", function() { 2 | beforeEach(LambdaJS.expose); 3 | 4 | it("toExponential", function() { 5 | expect(toExponential(3, 5.56789)).toEqual("5.568e+0") 6 | expect(toExponential(3)(5.56789)).toEqual("5.568e+0") 7 | }); 8 | 9 | it("toFixed", function() { 10 | expect(toFixed(2)(5.56789)).toEqual('5.57') 11 | }); 12 | 13 | it("toPrecision", function() { 14 | expect(toPrecision(2, 13.3714)).toEqual("13") 15 | expect(toPrecision(2)(13.3714)).toEqual("13") 16 | }); 17 | 18 | it("toString", function() { 19 | expect(toString(2)).toEqual("2") 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /examples after/1.js: -------------------------------------------------------------------------------- 1 | require('../support/lambdajs/utils').expose(global); 2 | require('../support/lambdajs/lambda').expose(); 3 | require('pointfree-fantasy').expose(global); 4 | require('lenses').expose(global); 5 | 6 | var markdown = require('markdown').parse; 7 | 8 | var L = makeLenses(['body', 'viewed']); 9 | 10 | var comment = {id: 2, body: "this is a *great* post!", viewed: false}; 11 | 12 | var showOnScreen = log; 13 | 14 | var prog = compose(showOnScreen, set(L.viewed, true), over(L.body, markdown)); 15 | 16 | prog(comment); 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /support/lambdajs/test/spec/regex_spec.js: -------------------------------------------------------------------------------- 1 | describe("Regex", function() { 2 | beforeEach(LambdaJS.expose); 3 | 4 | it("exec", function() { 5 | var str="Hello world!"; 6 | var patt=/Hello/; 7 | var patt2=/W3Schools/; 8 | expect(exec(patt, str)[0]).toEqual("Hello"); 9 | expect(exec(patt)(str)[0]).toEqual("Hello"); 10 | expect(exec(patt2, str)).toEqual(null); 11 | }); 12 | 13 | it("test", function() { 14 | var str="Hello world!"; 15 | var patt=/Hello/; 16 | var patt2=/W3Schools/; 17 | expect(test(patt, str)).toEqual(true); 18 | expect(test(patt)(str)).toEqual(true); 19 | expect(test(patt2, str)).toEqual(false); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /support/lambdajs/docs/docs_files/prettify.css: -------------------------------------------------------------------------------- 1 | .pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} -------------------------------------------------------------------------------- /vendor/PreludeJS/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "preludejs", 3 | "description": "A collection of functions often used with the functional paradigm", 4 | "version": "0.1.0", 5 | "author": "loop/recur ", 6 | "maintainers": [ 7 | "Brian Lonsdorf ", 8 | "Ryan Charette ", 9 | "Eric Schmitt " 10 | ], 11 | "repository": { 12 | "type": "git", 13 | "url": "http://github.com/loop-recur/PreludeJS.git" 14 | }, 15 | "devDependencies": { 16 | "jasmine-node": "*" 17 | }, 18 | "engines": { 19 | "node": "*" 20 | }, 21 | "scripts": { 22 | "test": "jasmine-node --coffee specs" 23 | }, 24 | "main": "./prelude.js" 25 | } 26 | -------------------------------------------------------------------------------- /vendor/FunctionalJS/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "functionaljs", 3 | "description": "beefed up version of osteeles' library: http://osteele.com/sources/javascript/functional/", 4 | "version": "0.1.0", 5 | "author": "loop/recur ", 6 | "maintainers": [ 7 | "Brian Lonsdorf ", 8 | "Ryan Charette ", 9 | "Eric Schmitt " 10 | ], 11 | "repository": { 12 | "type": "git", 13 | "url": "http://github.com/loop-recur/FunctionalJS.git" 14 | }, 15 | "devDependencies": { 16 | "jasmine-node": "*" 17 | }, 18 | "engines": { 19 | "node": "*" 20 | }, 21 | "scripts": { 22 | "test": "jasmine-node --coffee specs" 23 | }, 24 | "main": "./functional.js" 25 | } 26 | -------------------------------------------------------------------------------- /support/promise.js: -------------------------------------------------------------------------------- 1 | var Promise = require('./node-promise/promise').Promise; 2 | 3 | var p = new Promise(); 4 | 5 | p.constructor.prototype.map = function(f) { 6 | var promise = new Promise(); 7 | this.then(function(response){ 8 | promise.resolve(f(response)); 9 | }); 10 | return promise; 11 | } 12 | 13 | p.constructor.prototype.ap = function(p2) { 14 | var promise = new Promise(); 15 | var p1 = this; 16 | 17 | p1.then(function(f){ 18 | p2.then(function(response){ 19 | promise.resolve(f(response)); 20 | }) 21 | }); 22 | return promise; 23 | } 24 | 25 | p.constructor.prototype.chain = function(f) { 26 | var prom = this; 27 | return prom.then(function(response){ 28 | return f(response); 29 | }); 30 | }; 31 | 32 | module.exports = Promise; 33 | -------------------------------------------------------------------------------- /examples/2.js: -------------------------------------------------------------------------------- 1 | require('../support/lambdajs/utils').expose(global); 2 | require('../support/lambdajs/lambda').expose(); 3 | require('pointfree-fantasy').expose(global); 4 | require('lenses').expose(global); 5 | 6 | var Maybe = require('pointfree-fantasy/instances/maybe'); 7 | var Either = require('pointfree-fantasy/instances/either'); 8 | var Promise = require('../support/promise'); 9 | var fs = require('../support/node-promise/fs-promise'); 10 | var readFile = function(path) { return fs.readFile(path, 'utf-8') }; 11 | 12 | 13 | 14 | 15 | var prog = compose(pluck('length'), match(/\w+/g)); 16 | 17 | var result = prog('i got some words'); 18 | 19 | log(result); 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /examples/5.js: -------------------------------------------------------------------------------- 1 | require('../support/lambdajs/utils').expose(global); 2 | require('../support/lambdajs/lambda').expose(); 3 | require('pointfree-fantasy').expose(global); 4 | require('lenses').expose(global); 5 | 6 | var Promise = require('../support/promise'); 7 | var Sum = require('pointfree-fantasy/instances/sum').Sum; 8 | var _ = require('lodash'); 9 | var fs = require('../support/node-promise/fs-promise'); 10 | var asterisk = require('../support/arrow').asterisk; 11 | var readFile = function(path) { return fs.readFile(path, 'utf-8') }; 12 | 13 | 14 | 15 | 16 | var p1 = readFile('gadsby.txt'); 17 | var p2 = readFile('blah.txt'); 18 | 19 | var result = ? 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /examples/3.js: -------------------------------------------------------------------------------- 1 | require('../support/lambdajs/utils').expose(global); 2 | require('../support/lambdajs/lambda').expose(); 3 | require('pointfree-fantasy').expose(global); 4 | require('lenses').expose(global); 5 | var _ = require('lodash') 6 | 7 | var Maybe = require('pointfree-fantasy/instances/maybe'); 8 | var flatMap = _.curry(function(f, x) { return compose(mjoin, fmap(f))(x); }); 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | var showLength = compose(concat('The length is: '), pluck('length')); 33 | 34 | var getWords = compose(Maybe, match(/\w+/g)); 35 | 36 | var prog = compose(fmap(showLength), getWords); 37 | 38 | var result = prog('blah blah'); 39 | 40 | log(result); 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /support/lambdajs/test/spec/objects_spec.js: -------------------------------------------------------------------------------- 1 | describe("Object", function() { 2 | var obj = {a:1, b:2}; 3 | beforeEach(LambdaJS.expose); 4 | 5 | it("toLocaleString", function() { 6 | expect(toLocaleString(obj)).toEqual("[object Object]"); 7 | }); 8 | 9 | it("hasOwnProperty", function() { 10 | expect(hasOwnProperty('a', obj)).toBeTruthy() 11 | expect(hasOwnProperty('blah', obj)).toBeFalsy() 12 | }); 13 | 14 | it("isPrototypeOf", function() { 15 | var Fee = function(){} 16 | 17 | var Fi = function() {} 18 | Fi.prototype = new Fee(); 19 | 20 | var Fo = function() {} 21 | Fo.prototype = new Fi(); 22 | 23 | var Fum = function() {} 24 | Fum.prototype = new Fo(); 25 | 26 | var fum = new Fum(); 27 | var fo = new Fo(); 28 | expect(isPrototypeOf(fum, Fi)).toBeTruthy() 29 | expect(isPrototypeOf(fo, Fum)).toBeFalsy() 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /examples after/2.js: -------------------------------------------------------------------------------- 1 | require('../support/lambdajs/utils').expose(global); 2 | require('../support/lambdajs/lambda').expose(); 3 | require('pointfree-fantasy').expose(global); 4 | require('lenses').expose(global); 5 | 6 | var Maybe = require('pointfree-fantasy/instances/maybe'); 7 | var Either = require('pointfree-fantasy/instances/either'); 8 | var Promise = require('../support/promise'); 9 | var fs = require('../support/node-promise/fs-promise'); 10 | var readFile = function(path) { return fs.readFile(path, 'utf-8') }; 11 | 12 | 13 | 14 | var showLength = compose(concat('The length is: '), pluck('length')); 15 | 16 | var getWords = compose(Maybe, match(/\w+/g)); 17 | 18 | var prog = compose(fmap(showLength), getWords); 19 | 20 | var result = prog('i got some words'); 21 | 22 | log(result); 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /examples after/5.js: -------------------------------------------------------------------------------- 1 | require('../support/lambdajs/utils').expose(global); 2 | require('../support/lambdajs/lambda').expose(); 3 | require('pointfree-fantasy').expose(global); 4 | require('lenses').expose(global); 5 | 6 | var Promise = require('../support/promise'); 7 | var Sum = require('pointfree-fantasy/instances/sum').Sum; 8 | var _ = require('lodash'); 9 | var fs = require('../support/node-promise/fs-promise'); 10 | var asterisk = require('../support/arrow').asterisk; 11 | var readFile = function(path) { return fs.readFile(path, 'utf-8') }; 12 | 13 | var totalLength = compose(Sum, pluck('length')); 14 | 15 | var tally = _.curry(function(f1, f2) { 16 | compose(log, mconcat, asterisk(totalLength, totalLength))([f1, f2]) 17 | }); 18 | 19 | liftA2(tally, readFile('gadsby.txt'), readFile('blah.txt')); 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /examples/4.js: -------------------------------------------------------------------------------- 1 | require('../support/lambdajs/utils').expose(global); 2 | require('../support/lambdajs/lambda').expose(); 3 | require('pointfree-fantasy').expose(global); 4 | require('lenses').expose(global); 5 | 6 | var markdown = require('markdown').parse; 7 | var _ = require('lodash'); 8 | var Maybe = require('pointfree-fantasy/instances/maybe'); 9 | var Either = require('pointfree-fantasy/instances/either'); 10 | var Promise = require('../support/promise'); 11 | var fs = require('../support/node-promise/fs-promise'); 12 | var ampersand = require('../support/arrow').ampersand; 13 | var readFile = function(path) { return fs.readFile(path, 'utf-8') }; 14 | 15 | 16 | 17 | 18 | 19 | 20 | var makeUser = function(first, last) { return first +" "+last + ' created!' }; 21 | 22 | var result = makeUser('Sal', 'Woodsman'); 23 | log(result); 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /examples after/3.js: -------------------------------------------------------------------------------- 1 | require('../support/lambdajs/utils').expose(global); 2 | require('../support/lambdajs/lambda').expose(); 3 | require('pointfree-fantasy').expose(global); 4 | require('lenses').expose(global); 5 | var _ = require('lodash'); 6 | 7 | var Maybe = require('pointfree-fantasy/instances/maybe'); 8 | var flatMap = _.curry(function(f, x) { return compose(mjoin, fmap(f))(x); }); 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | var showLength = compose(concat('The length is: '), pluck('length')); 33 | 34 | var getWords = compose(Maybe, match(/\w+/g)); 35 | 36 | var getText = compose(Maybe, pluck('text')); 37 | 38 | var prog = compose(fmap(showLength), flatMap(getWords), flatMap(getText), Maybe); 39 | 40 | var result = prog({text: 'blah blah'}); 41 | 42 | log(result); 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /vendor/typeclasses/support/types.js: -------------------------------------------------------------------------------- 1 | define([], function() { 2 | Constructor = function(f) { 3 | var x = function(){ 4 | if(!(this instanceof x)){ 5 | var inst = new x(); 6 | f.apply(inst, arguments); 7 | return inst; 8 | } 9 | f.apply(this, arguments); 10 | }; 11 | 12 | return x; 13 | } 14 | 15 | makeType = function(f) { 16 | f = f || function(v){ this.val = v; } 17 | return Constructor(f); 18 | } 19 | 20 | // Some default types 21 | UI = makeType(); 22 | PromiseWrapper = makeType(); 23 | 24 | Identity = makeType(); 25 | 26 | Maybe = makeType(); 27 | 28 | // _Either is a temporary hack until we can keep a consistent prototype during autoCurry 29 | _Either = Constructor(function(left, right){ 30 | this.left = left; 31 | this.right = right; 32 | }); 33 | 34 | Either = function(left, right){ 35 | return _Either(left, right); 36 | }.autoCurry(); 37 | 38 | return makeType; 39 | }) 40 | -------------------------------------------------------------------------------- /vendor/typeclasses/applicative.js: -------------------------------------------------------------------------------- 1 | define(['functor'], function() { 2 | Applicative = function(type, defs) { 3 | type.prototype.pure = defs.pure; 4 | type.prototype.ap = defs.ap.autoCurry(); 5 | } 6 | 7 | ap = function(a1, a2) { 8 | return a1.ap(a2); 9 | }.autoCurry(); 10 | 11 | pure = function(f) { 12 | f.ap = fmap(f); 13 | return f; 14 | } 15 | 16 | liftA2 = function(f, a1, a2) { 17 | return pure(f).ap(a1).ap(a2); 18 | }.autoCurry(); 19 | 20 | liftA3 = function(f, a1, a2, a3) { 21 | return pure(f).ap(a1).ap(a2).ap(a3); 22 | }.autoCurry(); 23 | 24 | Applicative(Function, { 25 | pure: K, 26 | ap: function(g) { 27 | var f = this; 28 | return function(x) { 29 | return f(x, g(x)); 30 | }; 31 | } 32 | }); 33 | 34 | // Applicative(Array, { 35 | // pure: Array, // needs to be infinite to be correct ziplist 36 | // ap: function(a2) { 37 | // // ziplist implementation 38 | // return map(function(f,i){ return f(a2[i]); }, this); 39 | // } 40 | // }); 41 | }); 42 | -------------------------------------------------------------------------------- /support/arrow.js: -------------------------------------------------------------------------------- 1 | var curry = require('lodash.curry'); 2 | 3 | // Helpers 4 | var K = function(x) { return function(y) { return x} }; 5 | var I = function(x) { return x }; 6 | 7 | 8 | // Defines the function instance for arrow rather than the full typeclass 9 | var arr = I 10 | 11 | , compose = curry(function(f, g, x) { 12 | return g(f(x)); 13 | }) 14 | 15 | , asterisk = curry(function(f, g) { 16 | return function(tuple) { 17 | return [f(tuple[0]), g(tuple[1])] 18 | } 19 | }) 20 | 21 | , ampersand = curry(function(f, g) { 22 | return function(x) { 23 | return asterisk(f, g)([x, x]); 24 | }; 25 | }) 26 | 27 | , first = function(f) { 28 | return asterisk(f, I); 29 | } 30 | 31 | , second = function(f) { 32 | return asterisk(I, f); 33 | } 34 | ; 35 | 36 | var Arrow = { arr: arr 37 | , asterisk: asterisk 38 | , ampersand: ampersand 39 | , first: first 40 | , second: second 41 | , compose: compose 42 | } 43 | 44 | module.exports = Arrow; 45 | 46 | -------------------------------------------------------------------------------- /vendor/typeclasses/functor.js: -------------------------------------------------------------------------------- 1 | define(['types'], function() { 2 | Functor = function(type, defs) { 3 | type.prototype.fmap = defs.fmap; 4 | } 5 | 6 | fmap = function(f, obj) { 7 | return obj.fmap(f); 8 | }.autoCurry(); 9 | 10 | // Some default instances: 11 | 12 | // Functor(Array, { 13 | // fmap: function(f){ 14 | // return this.map(function(x){ 15 | // return f(x); 16 | // }); 17 | // } // expand map function with lambda since map passes index in which messes with curried functions on applicatives 18 | // }); 19 | 20 | Functor(Function, { 21 | fmap: function(f){ return compose(f, this); } 22 | }); 23 | 24 | Functor(Identity, { 25 | fmap: function(f){ return Identity(f(this.val)); } 26 | }); 27 | 28 | Functor(Maybe, { 29 | fmap: function(f) { 30 | if(!this.val) return this; 31 | return Maybe(f(this.val)); 32 | } 33 | }); 34 | 35 | Functor(_Either, { 36 | fmap: function(f) { 37 | if(!this.right) return _Either(f(this.left), this.right); 38 | return _Either(this.left, f(this.right)); 39 | } 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /examples after/4.js: -------------------------------------------------------------------------------- 1 | require('../support/lambdajs/utils').expose(global); 2 | require('../support/lambdajs/lambda').expose(); 3 | require('pointfree-fantasy').expose(global); 4 | require('lenses').expose(global); 5 | 6 | var markdown = require('markdown').parse; 7 | var _ = require('lodash') 8 | var Maybe = require('pointfree-fantasy/instances/maybe'); 9 | var Either = require('pointfree-fantasy/instances/either'); 10 | var Promise = require('../support/promise'); 11 | var fs = require('../support/node-promise/fs-promise'); 12 | var ampersand = require('../support/arrow').ampersand; 13 | var readFile = function(path) { return fs.readFile(path, 'utf-8') }; 14 | 15 | 16 | 17 | 18 | 19 | 20 | var makeUser = _.curry(function(first, last) { return first +" "+last + ' created!' }); 21 | 22 | var create = function(first, last) { 23 | return liftA2(makeUser, Either('enter a first name', first), Either('enter a last name', last)) 24 | }; 25 | 26 | var result = create('Sal', 'Woodsman'); 27 | log(result); 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /support/lambdajs/test/lib/jasmine-1.2.0/MIT.LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008-2011 Pivotal Labs 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /examples/6.js: -------------------------------------------------------------------------------- 1 | require('../support/lambdajs/utils').expose(global); 2 | require('../support/lambdajs/lambda').expose(); 3 | require('pointfree-fantasy').expose(global); 4 | require('lenses').expose(global); 5 | 6 | var Maybe = require('pointfree-fantasy/instances/maybe'); 7 | var Promise = require('../support/promise'); 8 | var fs = require('../support/node-promise/fs-promise'); 9 | var readFile = function(path) { return fs.readFile(path, 'utf-8') }; 10 | 11 | function askUser(prompt) { 12 | var promise = new Promise(); 13 | process.stdin.resume(); 14 | process.stdout.write(prompt+'\n'); 15 | process.stdin.once("data", function (data) { 16 | promise.resolve(data.toString().trim()); 17 | }); 18 | return promise; 19 | } 20 | 21 | 22 | 23 | 24 | var showLength = compose(concat('The length is: '), pluck('length')); 25 | 26 | var getWords = compose(Maybe, match(/\w+/g)); 27 | 28 | var showWordLength = compose(fmap(showLength), getWords); 29 | 30 | var prog = compose(fmap(showWordLength), readFile); 31 | 32 | var result = prog('what file?'); 33 | 34 | fmap(log, result); 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /examples after/6.js: -------------------------------------------------------------------------------- 1 | require('../support/lambdajs/utils').expose(global); 2 | require('../support/lambdajs/lambda').expose(); 3 | require('pointfree-fantasy').expose(global); 4 | require('lenses').expose(global); 5 | 6 | var Maybe = require('pointfree-fantasy/instances/maybe'); 7 | var Promise = require('../support/promise'); 8 | var fs = require('../support/node-promise/fs-promise'); 9 | var readFile = function(path) { return fs.readFile(path, 'utf-8') }; 10 | 11 | function askUser(prompt) { 12 | var promise = new Promise(); 13 | process.stdin.resume(); 14 | process.stdout.write(prompt+'\n'); 15 | process.stdin.once("data", function (data) { 16 | promise.resolve(data.toString().trim()); 17 | }); 18 | return promise; 19 | } 20 | 21 | 22 | 23 | 24 | var showLength = compose(concat('The length is: '), pluck('length')) 25 | 26 | var getWords = compose(Maybe, match(/\w+/g)); 27 | 28 | var showWordLength = compose(fmap(showLength), getWords); 29 | 30 | var prog = compose(fmap(showWordLength), mjoin, fmap(readFile), askUser); 31 | 32 | var result = prog('what file?'); 33 | 34 | fmap(log, result); 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /support/lambdajs/test/spec/lambdajs_spec.js: -------------------------------------------------------------------------------- 1 | describe("LambdaJS", function() { 2 | 3 | it("does not globally expose functions automatically", function() { 4 | expect(window.concat).toBeUndefined(); 5 | }); 6 | 7 | describe("expose", function() { 8 | var cleanup = function() { 9 | for (f in LambdaJS) { 10 | if (LambdaJS.hasOwnProperty(f)) { 11 | delete window[f]; 12 | } 13 | } 14 | } 15 | ; 16 | 17 | beforeEach(LambdaJS.expose); 18 | afterEach(cleanup); 19 | 20 | it("exposes all functions to the global namespace", function() { 21 | expect(LambdaJS).toBeDefined(); 22 | expect(window.concat).toBeDefined(); 23 | }); 24 | 25 | it("omits designated functions from exposure", function() { 26 | expect(window.expose).toBeUndefined(); 27 | }); 28 | }); 29 | 30 | describe("LambdaJS", function() { 31 | it("concat", function() { 32 | expect(LambdaJS.concat([1], [2, 3], [4,5])).toEqual([1, 2, 3, 4, 5]); 33 | expect(LambdaJS.concat([1])([2, 3], [4,5])).toEqual([1, 2, 3, 4, 5]); 34 | expect(LambdaJS.concat("hello", " ", "world")).toEqual("hello world"); 35 | expect(LambdaJS.concat("hello")(" ", "world")).toEqual("hello world"); 36 | }); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /examples/7.js: -------------------------------------------------------------------------------- 1 | require('../support/lambdajs/utils').expose(global); 2 | require('../support/lambdajs/lambda').expose(); 3 | require('pointfree-fantasy').expose(global); 4 | require('lenses').expose(global); 5 | 6 | var markdown = require('markdown').parse; 7 | var _ = require('lodash'); 8 | var Maybe = require('pointfree-fantasy/instances/maybe'); 9 | var Either = require('pointfree-fantasy/instances/either'); 10 | var Promise = require('../support/promise'); 11 | var fs = require('../support/node-promise/fs-promise'); 12 | var ampersand = require('../support/arrow').ampersand; 13 | var readFile = function(path) { return fs.readFile(path, 'utf-8') }; 14 | 15 | function askUser(prompt) { 16 | var promise = new Promise(); 17 | process.stdin.resume(); 18 | process.stdout.write(prompt+'\n'); 19 | process.stdin.once("data", function (data) { 20 | promise.resolve(data.toString().trim()); 21 | }); 22 | return promise; 23 | } 24 | 25 | 26 | 27 | 28 | 29 | 30 | var getResults = _.curry(function(text, input) { 31 | var result = Math.abs(Number(input) - text.length); 32 | return "You were "+result+' off'; 33 | }); 34 | 35 | var guessLength = ? 36 | 37 | fmap(log, guessLength()); 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /examples after/7.js: -------------------------------------------------------------------------------- 1 | require('../support/lambdajs/utils').expose(global); 2 | require('../support/lambdajs/lambda').expose(); 3 | require('pointfree-fantasy').expose(global); 4 | require('lenses').expose(global); 5 | 6 | var markdown = require('markdown').parse; 7 | var _ = require('lodash') 8 | var Maybe = require('pointfree-fantasy/instances/maybe'); 9 | var Either = require('pointfree-fantasy/instances/either'); 10 | var Promise = require('../support/promise'); 11 | var fs = require('../support/node-promise/fs-promise'); 12 | var ampersand = require('../support/arrow').ampersand; 13 | var readFile = function(path) { return fs.readFile(path, 'utf-8') }; 14 | 15 | function askUser(prompt) { 16 | var promise = new Promise(); 17 | process.stdin.resume(); 18 | process.stdout.write(prompt+'\n'); 19 | process.stdin.once("data", function (data) { 20 | promise.resolve(data.toString().trim()); 21 | }); 22 | return promise; 23 | } 24 | 25 | 26 | 27 | 28 | 29 | 30 | var getResults = _.curry(function(text, input) { 31 | var result = Math.abs(Number(input) - text.length); 32 | return 'You were '+result+' off'; 33 | }); 34 | 35 | var guessLength = function() { 36 | return liftA2(getResults, readFile('gadsby.txt'), askUser("What's the length?")) 37 | }; 38 | 39 | fmap(log, guessLength()); 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /vendor/typeclasses/monoid.js: -------------------------------------------------------------------------------- 1 | define(['types'], function() { 2 | mappend = function(x, y) { 3 | return x.mappend(x, y); 4 | } 5 | 6 | mconcat = function() { 7 | var xs = Array.prototype.slice.call(arguments); 8 | if(xs.length == 1) xs = xs[0]; //skip having to call apply 9 | var f = xs[0].mappend; 10 | var e = xs[0].mempty(); 11 | return xs.reduce(f, e); 12 | } 13 | 14 | Monoid = function(type, defs) { 15 | type.prototype.mempty = defs.mempty; 16 | type.prototype.mappend = defs.mappend.autoCurry(); 17 | } 18 | 19 | // Monoid(Object, { 20 | // mempty: function(){ return Object({}) }, 21 | // mappend: function(x,y){ 22 | // return Object(unionWith(mappend, x, y)); 23 | // } 24 | // }); 25 | 26 | Monoid(Number, { 27 | mempty: K(0), 28 | mappend: function(x,y) { return x + y; } 29 | }); 30 | 31 | // Monoid(Array, { 32 | // mempty: K([]), 33 | // mappend: concat 34 | // }); 35 | 36 | Monoid(String, { 37 | mempty: K(""), 38 | mappend: function(x,y) { return x + y; } 39 | }); 40 | 41 | Monoid(Boolean, { 42 | mempty: K(false), 43 | mappend: function(x,y){ return (x || y); } 44 | }); 45 | 46 | Monoid(Function, { 47 | mempty: K(K({mappend: function(f, g) { return mappend(g.mempty(), g);} })), 48 | mappend: function(f,g){ 49 | return function() { 50 | return mappend(f.apply(this, arguments), 51 | g.apply(this, arguments)); 52 | } 53 | } 54 | }); 55 | }); -------------------------------------------------------------------------------- /examples/holy_smokes.js: -------------------------------------------------------------------------------- 1 | require('../support/lambdajs/utils').expose(global); 2 | require('../support/lambdajs/lambda').expose(); 3 | require('pointfree-fantasy').expose(global); 4 | require('lenses').expose(global); 5 | 6 | var curry = require('lodash.curry'); 7 | var Maybe = require('pointfree-fantasy/instances/maybe'); 8 | var Promise = require('../support/promise'); 9 | var flatMap = curry(function(f, x) { return compose(mjoin, fmap(f))(x); }); 10 | 11 | 12 | var safeGet = curry(function(name, obj) { return compose(Maybe, pluck(name))(obj); }) 13 | 14 | var Db = { 15 | getUser: function(id) { 16 | var p = new Promise(); 17 | setTimeout(function() { p.resolve(Maybe(users[id])); }, 10); 18 | return p; 19 | } 20 | } 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | var users = [ {name: 'Kate', addresses:[{street: {number: 22, name: 'Walnut St.'}}]} 32 | , {name: "Ajit", addresses:[{street: {number: 52, name: 'Crane Ave.'}}]} 33 | ]; 34 | 35 | 36 | var L = makeLenses(['addresses']); 37 | 38 | var dbResp = compose(mapped, mapped); 39 | 40 | var usersAddresses = compose(dbResp, L.addresses); 41 | 42 | var firstStreetsName = compose(flatMap(safeGet('name')), flatMap(safeGet('street')), safeGet(0)) 43 | 44 | var upperLog = compose(log, toUpperCase) 45 | 46 | var upperCaseTheStreet = compose(fmap(upperLog), firstStreetsName) 47 | 48 | var prog = compose( over(usersAddresses, upperCaseTheStreet) 49 | , Db.getUser 50 | , pluck('id') 51 | ) 52 | 53 | prog({id: 0}); 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /examples after/holy_smokes.js: -------------------------------------------------------------------------------- 1 | require('../support/lambdajs/utils').expose(global); 2 | require('../support/lambdajs/lambda').expose(); 3 | require('pointfree-fantasy').expose(global); 4 | require('lenses').expose(global); 5 | 6 | var curry = require('lodash.curry'); 7 | var Maybe = require('pointfree-fantasy/instances/maybe'); 8 | var Promise = require('../support/promise'); 9 | var flatMap = curry(function(f, x) { return compose(mjoin, fmap(f))(x); }); 10 | 11 | 12 | var safeGet = curry(function(name, obj) { return compose(Maybe, pluck(name))(obj); }); 13 | 14 | var Db = { 15 | getUser: function(id) { 16 | var p = new Promise(); 17 | setTimeout(function() { p.resolve(Maybe(users[id])); }, 10); 18 | return p; 19 | } 20 | }; 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | var users = [ {name: 'Kate', addresses:[{street: {number: 22, name: 'Walnut St.'}}]} 32 | , {name: "Ajit", addresses:[{street: {number: 52, name: 'Crane Ave.'}}]} 33 | ]; 34 | 35 | 36 | var L = makeLenses(['addresses']); 37 | 38 | var dbResp = compose(mapped, mapped); 39 | 40 | var usersAddresses = compose(dbResp, L.addresses); 41 | 42 | var firstStreetsName = compose(flatMap(safeGet('name')), flatMap(safeGet('street')), safeGet(0)); 43 | 44 | var upperLog = compose(log, toUpperCase); 45 | 46 | var upperCaseTheStreet = compose(fmap(upperLog), firstStreetsName); 47 | 48 | var prog = compose( over(usersAddresses, upperCaseTheStreet) 49 | , Db.getUser 50 | , pluck('id') 51 | ); 52 | 53 | prog({id: 0}); 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /support/lambdajs/docs/docs_files/style.css: -------------------------------------------------------------------------------- 1 | body{ 2 | font: 14px/1.4 Myriad Pro, Arial, Sans-serif; 3 | } 4 | 5 | a { 6 | color: #80f; 7 | text-decoration: none; 8 | } 9 | a:hover { 10 | text-decoration: underline; 11 | } 12 | mark { background: #ffa; margin-left: 5px; } 13 | .sidebar { 14 | position: fixed; 15 | top: 0; 16 | left: 0; 17 | bottom: 0; 18 | width: 209px; 19 | padding: 10px 20px; 20 | background: #f5f5f5; 21 | border-right: 1px solid #e5e5e5; 22 | overflow: auto; 23 | } 24 | 25 | .sidebar nav { 26 | display: none; 27 | border-bottom: 1px solid #e5e5e5; 28 | color: #aaa; 29 | } 30 | 31 | .sidebar nav span:hover { 32 | cursor: pointer; 33 | background: #ffc; 34 | } 35 | .sidebar .current { 36 | color: black; 37 | font-weight: 800 38 | } 39 | 40 | .sidebar ul { 41 | list-style: none; 42 | padding: 0; 43 | } 44 | 45 | .container { 46 | margin-left: 270px; 47 | } 48 | 49 | pre, code { 50 | font-family: monaco; 51 | font-size: 12px; 52 | line-height: 1.4; 53 | } 54 | 55 | /* prettify */ 56 | section .com { color: #93a1a1; } 57 | section .lit { color: #195f91; } 58 | section .pun, .opn, .clo { color: #93a1a1; } 59 | section .fun { color: #dc322f; } 60 | section .str, .atv { color: #D14; } 61 | section .kwd, .prettyprint .tag { color: #1e347b; } 62 | section .typ, .atn, .dec, .var { color: teal; } 63 | section .pln { color: #48484c; } 64 | 65 | section pre.prettyprint { 66 | padding: 8px; 67 | background-color: #f5f5f5; 68 | border: none; 69 | } 70 | 71 | section { 72 | } 73 | 74 | section h2 { 75 | margin: 3em 0 0; 76 | } 77 | 78 | h2 small { 79 | font-size: 14px; 80 | font-weight: 400; 81 | margin-left: 5px; 82 | } 83 | h2 small a { color: #aaa; text-decoration: underline; } 84 | h2 small a:hover { color: #80f; } 85 | 86 | code.sig { color: #aaa } 87 | -------------------------------------------------------------------------------- /support/lambdajs/test/SpecRunner.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | Jasmine Spec Runner 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /support/lambdajs/utils.js: -------------------------------------------------------------------------------- 1 | var curry = require('lodash.curry'); 2 | var _FPUtils = {}; 3 | 4 | var _compose = curry(function(f,g,x) { return f(g(x)) }); 5 | 6 | // f . g . h == compose(f, g, h) 7 | var toAssociativeCommaInfix = function(fn) { 8 | return function() { 9 | var fns = [].slice.call(arguments) 10 | return function() { 11 | return _FPUtils.groupsOf(2, fns).reverse().map(function(g) { 12 | return (g.length > 1) ? fn.apply(this,g) : g[0]; 13 | }).reduce(function(x, f) { 14 | return [f.apply(f,x)]; 15 | }, arguments)[0]; 16 | }; 17 | }; 18 | }; 19 | 20 | _FPUtils.compose = toAssociativeCommaInfix(_compose); 21 | 22 | _FPUtils.groupsOf = curry(function(n, xs) { 23 | if(!xs.length) return []; 24 | return [xs.slice(0, n)].concat(_FPUtils.groupsOf(n, xs.slice(n, xs.length))); 25 | }) 26 | 27 | _FPUtils.pluck = curry(function( param, obj ){ 28 | return obj[param]; 29 | }) 30 | 31 | _FPUtils.first = _FPUtils.pluck(0) 32 | 33 | _FPUtils.last = function(xs) { 34 | return xs[xs.length -1]; 35 | } 36 | 37 | _FPUtils.invoke = function(methodName/*, arguments*/) { 38 | var args = Array.slice(arguments, 1); 39 | return function(object) { 40 | return object[methodName].apply(object, Array.slice(arguments, 1).concat(args)); 41 | } 42 | } 43 | 44 | _FPUtils.flip = function( fn ){ 45 | return curry(function(){ 46 | var args = Array.slice(arguments, 0).reverse(); 47 | return fn.apply( null, args ); 48 | }, fn.arity || fn.length); 49 | } 50 | 51 | _FPUtils.multiply = curry(function( x, y ) { 52 | return x * y; 53 | }) 54 | 55 | _FPUtils.div = curry(function( x, y ) { 56 | return x / y; 57 | }) 58 | 59 | _FPUtils.add = curry(function( x, y ) { 60 | return x + y; 61 | }) 62 | 63 | _FPUtils.subtract = curry(function( x, y ) { 64 | return x - y; 65 | }) 66 | 67 | _FPUtils.mod = curry(function(x,y) { 68 | return x % y; 69 | }) 70 | 71 | _FPUtils.gt = curry(function( x, y ) { 72 | return x > y; 73 | }) 74 | 75 | _FPUtils.gte = curry(function( x, y ) { 76 | return x >= y; 77 | }) 78 | 79 | _FPUtils.lt = curry(function( x, y ) { 80 | return x < y; 81 | }) 82 | 83 | _FPUtils.lte = curry(function( x, y ) { 84 | return x <= y; 85 | }) 86 | 87 | _FPUtils.equal = curry(function( x, y ) { 88 | return x === y; 89 | }) 90 | 91 | _FPUtils.eq = curry(function( x, y ) { 92 | return x == y; 93 | }) 94 | 95 | _FPUtils.sequence = function() { 96 | var fns = [].slice.call(arguments); 97 | return function(x) { 98 | return fns.map(function(f) { return f(x); }); 99 | }; 100 | }; 101 | 102 | _FPUtils.S = curry(function(f, g) { 103 | return function() { 104 | return f.apply(this, [g.apply(this, arguments)].concat(Array.slice(arguments, 0))); 105 | } 106 | }) 107 | 108 | _FPUtils.K = function(x){ return function(){ return x; }; } 109 | 110 | _FPUtils.I = function(x){ return x; } 111 | 112 | _FPUtils.log = function(x){ console.log(x); return x; } 113 | 114 | _FPUtils.expose = function(env) { 115 | var f; 116 | for (f in _FPUtils) { 117 | if (f !== 'expose' && _FPUtils.hasOwnProperty(f)) { 118 | env[f] = _FPUtils[f]; 119 | } 120 | } 121 | return _FPUtils; 122 | } 123 | 124 | module.exports = _FPUtils; 125 | 126 | if(typeof window == "object") { 127 | FPUtils = _FPUtils; 128 | } 129 | -------------------------------------------------------------------------------- /vendor/typeclasses/monad.js: -------------------------------------------------------------------------------- 1 | define(['functor'], function() { 2 | Monad = function(type, defs) { 3 | var mbindViaJoin = function(f, mv) { 4 | return mjoin(mv.fmap(f)); 5 | }.autoCurry(); 6 | 7 | var joinViaMbind = function(mmv) { return mmv.mbind(id); } 8 | 9 | type.prototype.mresult = defs.mresult; 10 | type.prototype.mbind = (defs.mbind && defs.mbind.autoCurry()) || mbindViaJoin; 11 | type.prototype.mjoin = defs.mjoin || joinViaMbind; 12 | } 13 | 14 | mjoin = function(mmv) { 15 | return mmv.mjoin(); 16 | } 17 | 18 | mbind = function(mv, f) { 19 | f.mresult = mv.mresult; 20 | return mv.mbind(f, mv); 21 | }.autoCurry(); 22 | 23 | ap = function(mf, m) { 24 | return mbind(mf, function(f){ 25 | return mbind(m, function(x) { 26 | return m.mresult.call(this, f(x)); 27 | }) 28 | }) 29 | }.autoCurry(); 30 | 31 | // takes variable args like compose does though. 32 | //+ _mcompose :: (b -> m c) -> (a -> m b) -> (a -> m c) 33 | mcompose = function(){ 34 | var fns= map(Function.toFunction,arguments), 35 | arglen=fns.length; 36 | return function() { 37 | var restlen = arglen-1; 38 | arguments = [fns[arglen-1].apply(this, arguments)]; 39 | for(var i=restlen;--i>=0;) { 40 | console.log(arguments[0]); 41 | arguments = [arguments[0].mbind(fns[i], arguments[0])]; 42 | } 43 | return arguments[0]; 44 | } 45 | } 46 | 47 | 48 | // liftM2 and on, but needs to work with ap. 49 | _liftApplicative = function(f) { 50 | return function() { 51 | var args = Array.prototype.slice.apply(arguments) 52 | , arg_length = args.length 53 | , result = args[0].mresult.call(this, f) 54 | , current_arg_idx = 0; 55 | 56 | while(current_arg_idx < arg_length) { 57 | result = ap(result, args[current_arg_idx]); 58 | current_arg_idx++; 59 | } 60 | 61 | return result; 62 | } 63 | } 64 | 65 | _liftFunctor = function(f) { 66 | return function(m) { 67 | return mbind(m, function(x){ 68 | return m.mresult.call(this, f(x)); 69 | }); 70 | } 71 | } 72 | 73 | liftM = function(f) { 74 | f = f.toFunction(); 75 | return f.curried ? _liftApplicative(f) : _liftFunctor(f); 76 | } 77 | 78 | 79 | // Built ins 80 | 81 | Monad(Identity, { 82 | mjoin: function() { 83 | return this.val; 84 | }, 85 | mresult: function(x){ return Identity(x); } 86 | }); 87 | 88 | // Monad(Array, { 89 | // mresult: Array, 90 | // mbind: function(f) { 91 | // return flatten(this.map(f)); 92 | // } 93 | // }); 94 | 95 | Monad(Maybe, { 96 | mjoin: function() { 97 | return this.val ? this.val : Maybe(undefined); 98 | }, 99 | mresult: function(x){ return Maybe(x); } 100 | }); 101 | 102 | Monad(_Either, { 103 | mjoin: function() { 104 | return this.right ? this.right : this.left; 105 | }, 106 | mresult: function(x){ return Either(this.left, x); } 107 | }); 108 | 109 | State = Constructor(function(runState){ 110 | this.runState = runState; 111 | }) 112 | 113 | Monad(State, { 114 | mresult: function(x){ 115 | return State(function(s){ return [x, s]}); 116 | }, 117 | mbind: function(f) { 118 | var that = this; 119 | return State(function(s){ 120 | var result = that.runState(s) 121 | , g = f(result[0]); 122 | return g.runState(result[1]); 123 | }); 124 | } 125 | }); 126 | }); 127 | -------------------------------------------------------------------------------- /support/lambdajs/test/spec/utils_spec.js: -------------------------------------------------------------------------------- 1 | describe("Utils", function() { 2 | beforeEach(LambdaJS.expose); 3 | 4 | it("compose", function() { 5 | var oneAndDouble = compose(multiply(2), add(1)); 6 | expect(oneAndDouble(1)).toEqual(4); 7 | }); 8 | 9 | xit("compose (binary functions) *coming soon", function() { 10 | var doubleMap = compose(map, map); 11 | expect(doubleMap(toUpperCase, [["a"]])).toEqual([["A"]]); 12 | }); 13 | 14 | it("compose (several functions)", function() { 15 | var doubleMap = compose(toUpperCase, charAt(1), dot(0)); 16 | expect(doubleMap(["abc"])).toEqual("B"); 17 | }); 18 | 19 | it("compose (binary then unary function)", function() { 20 | var mapThenReverse = compose(reverse, map(toUpperCase)); 21 | expect(mapThenReverse(["a", "b", "c"])).toEqual(["C", "B", "A"]); 22 | }); 23 | 24 | it("partial", function() { 25 | var twoTimesFive = multiply.partial(2, 5); 26 | expect(twoTimesFive()).toEqual(10); 27 | }); 28 | 29 | it("parallel", function() { 30 | var finished = false; 31 | var f = function(y){ 32 | expect(y).toEqual(2); 33 | expect(g).toHaveBeenCalledWith(2); 34 | finished = true; 35 | } 36 | var g = jasmine.createSpy(); 37 | var doubleAndAdd = parallel(f, g); 38 | waitsFor(function(){return finished}); 39 | doubleAndAdd(2); 40 | }); 41 | 42 | it("S", function() { 43 | var addTwoMultiplyI = S(multiply, add(2)); 44 | expect(addTwoMultiplyI(3)).toEqual(15); 45 | }); 46 | 47 | it("K", function() { 48 | var two = K(2); 49 | expect(two()).toEqual(2); 50 | }); 51 | 52 | it("I", function() { 53 | expect(I(2)).toEqual(2); 54 | }); 55 | 56 | it("mod", function() { 57 | expect(mod(5, 2)).toEqual(1); 58 | expect(mod(6)(2)).toEqual(0); 59 | }); 60 | 61 | it("gt", function() { 62 | expect(gt(2, 3)).toEqual(false); 63 | expect(gt(3, 3)).toEqual(false); 64 | expect(gt(5, 3)).toEqual(true); 65 | expect(gt(5)(3)).toEqual(true); 66 | }); 67 | 68 | it("gte", function() { 69 | expect(gte(2, 3)).toEqual(false); 70 | expect(gte(3, 3)).toEqual(true); 71 | expect(gte(5, 3)).toEqual(true); 72 | expect(gte(5)(3)).toEqual(true); 73 | }); 74 | 75 | it("lt", function() { 76 | expect(lt(2, 3)).toEqual(true); 77 | expect(lt(3, 3)).toEqual(false); 78 | expect(lt(5, 3)).toEqual(false); 79 | expect(lt(5)(3)).toEqual(false); 80 | }); 81 | 82 | it("lte", function() { 83 | expect(lte(2, 3)).toEqual(true); 84 | expect(lte(3, 3)).toEqual(true); 85 | expect(lte(5, 3)).toEqual(false); 86 | expect(lte(5)(3)).toEqual(false); 87 | }); 88 | 89 | it("equal", function() { 90 | expect(equal(2, 3)).toEqual(false); 91 | expect(equal(3, 3)).toEqual(true); 92 | expect(equal(3)(3)).toEqual(true); 93 | expect(equal("3")(3)).toEqual(false); 94 | }); 95 | 96 | it("eq", function() { 97 | expect(eq(2, 3)).toEqual(false); 98 | expect(eq(3, 3)).toEqual(true); 99 | expect(eq(3)(3)).toEqual(true); 100 | expect(eq("3")(3)).toEqual(true); 101 | }); 102 | 103 | it("add", function() { 104 | expect(add(2, 3)).toEqual(5); 105 | expect(add(2)(3)).toEqual(5); 106 | }); 107 | 108 | it("div", function() { 109 | expect(div(4, 2)).toEqual(2); 110 | expect(div(4)(2)).toEqual(2); 111 | }); 112 | 113 | it("multiply", function() { 114 | expect(multiply(4, 2)).toEqual(8); 115 | expect(multiply(4)(2)).toEqual(8); 116 | }); 117 | 118 | it("subtract", function() { 119 | expect(subtract(5, 2)).toEqual(3); 120 | expect(subtract(5)(2)).toEqual(3); 121 | }); 122 | }); 123 | -------------------------------------------------------------------------------- /support/lambdajs/test/spec/strings_spec.js: -------------------------------------------------------------------------------- 1 | if(typeof require == "function") { 2 | require('../../utils'); 3 | require('../../lambda').expose(); 4 | } 5 | 6 | describe("Strings", function() { 7 | 8 | it("charAt", function() { 9 | expect(charAt(1, "hey")).toEqual('e'); 10 | expect(charAt(1)("hey")).toEqual('e'); 11 | }); 12 | 13 | it("charCodeAt", function() { 14 | expect(charCodeAt(1, "hey")).toEqual(101); 15 | expect(charCodeAt(1)("hey")).toEqual(101); 16 | }); 17 | 18 | it("concat", function() { 19 | expect(concat("rock ", "n' ", "roll")).toEqual("rock n' roll"); 20 | expect(concat("rock ")("n' ", "roll")).toEqual("rock n' roll"); 21 | }); 22 | 23 | it("indexOf", function() { 24 | var str="Hello world, welcome to the universe."; 25 | expect(indexOf("welcome", str)).toEqual(13); 26 | expect(indexOf("welcome")(str)).toEqual(13); 27 | }); 28 | 29 | it("indexOf_", function() { 30 | var str="Hello world, welcome to the welcomed universe."; 31 | expect(indexOf_("welcome", 14, str)).toEqual(28); 32 | expect(indexOf_("welcome")(14)(str)).toEqual(28); 33 | }); 34 | 35 | it("lastIndexOf", function() { 36 | var str="Hello planet earth, you are a great planet."; 37 | expect(lastIndexOf("planet", str)).toEqual(36); 38 | expect(lastIndexOf("planet")(str)).toEqual(36); 39 | }); 40 | 41 | it("match", function() { 42 | var str="The rain in SPAIN stays mainly in the plain"; 43 | expect(match(/ain/g, str)).toEqual(['ain','ain','ain']); 44 | expect(match(/ain/g)(str)).toEqual(['ain','ain','ain']); 45 | }); 46 | 47 | it("replace", function() { 48 | var str="Visit Microsoft!"; 49 | expect(replace("Microsoft","W3Schools", str)).toEqual('Visit W3Schools!'); 50 | expect(replace("Microsoft")("W3Schools")(str)).toEqual('Visit W3Schools!'); 51 | }); 52 | 53 | it("search", function() { 54 | var str="Visit W3Schools!"; 55 | expect(search("W3Schools", str)).toEqual(6); 56 | expect(search("W3Schools")(str)).toEqual(6); 57 | }); 58 | 59 | it("slice", function() { 60 | var str="Hello world!"; 61 | expect(slice(1, str)).toEqual('ello world!'); 62 | expect(slice(1)(str)).toEqual('ello world!'); 63 | }); 64 | 65 | it("slice_", function() { 66 | var str="Hello world!"; 67 | expect(slice_(1, 5, str)).toEqual('ello'); 68 | expect(slice_(1)(5)(str)).toEqual('ello'); 69 | }); 70 | 71 | it("split", function() { 72 | var str="How are you doing today?"; 73 | expect(split(" ", str)).toEqual(['How','are','you','doing','today?']); 74 | expect(split(" ")(str)).toEqual(['How','are','you','doing','today?']); 75 | }); 76 | 77 | it("split_", function() { 78 | var str="How are you doing today?"; 79 | expect(split_(" ", 2, str)).toEqual(['How','are']); 80 | expect(split_(" ")(2)(str)).toEqual(['How','are']); 81 | }); 82 | 83 | it("substring", function() { 84 | var str="Hello world!"; 85 | expect(substring(3, str)).toEqual('lo world!'); 86 | expect(substring(3)(str)).toEqual('lo world!'); 87 | }); 88 | 89 | it("substring_", function() { 90 | var str="Hello world!"; 91 | expect(substring_(3, 5, str)).toEqual('lo'); 92 | expect(substring_(3)(5)(str)).toEqual('lo'); 93 | }); 94 | 95 | it("toLocaleLowerCase", function() { 96 | expect(toLocaleLowerCase("ALPHABET")).toEqual('alphabet'); 97 | }); 98 | 99 | it("toLowerCase", function() { 100 | expect(toLowerCase("Hello world!")).toEqual('hello world!'); 101 | }); 102 | 103 | it("toLocaleUpperCase", function() { 104 | expect(toLocaleUpperCase("alphabet")).toEqual('ALPHABET'); 105 | }); 106 | 107 | it("toUpperCase", function() { 108 | var str="Hello world!"; 109 | expect(toUpperCase("Hello world!")).toEqual('HELLO WORLD!'); 110 | }); 111 | 112 | it("trim", function() { 113 | var str="Hello world!"; 114 | expect(trim(" Hello world! ")).toEqual('Hello world!'); 115 | }); 116 | }); 117 | -------------------------------------------------------------------------------- /support/lambdajs/docs/docs_files/functional-js: -------------------------------------------------------------------------------- 1 | callback({ 2 | "meta": { 3 | "X-RateLimit-Limit": "60", 4 | "X-RateLimit-Remaining": "59", 5 | "X-RateLimit-Reset": "1373675094", 6 | "X-GitHub-Media-Type": "github.beta; format=json", 7 | "status": 200 8 | }, 9 | "data": { 10 | "id": 10583697, 11 | "name": "functional-js", 12 | "full_name": "casperin/functional-js", 13 | "owner": { 14 | "login": "casperin", 15 | "id": 99103, 16 | "avatar_url": "https://secure.gravatar.com/avatar/8011f2f608a7456af69f5a440d68b167?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png", 17 | "gravatar_id": "8011f2f608a7456af69f5a440d68b167", 18 | "url": "https://api.github.com/users/casperin", 19 | "html_url": "https://github.com/casperin", 20 | "followers_url": "https://api.github.com/users/casperin/followers", 21 | "following_url": "https://api.github.com/users/casperin/following{/other_user}", 22 | "gists_url": "https://api.github.com/users/casperin/gists{/gist_id}", 23 | "starred_url": "https://api.github.com/users/casperin/starred{/owner}{/repo}", 24 | "subscriptions_url": "https://api.github.com/users/casperin/subscriptions", 25 | "organizations_url": "https://api.github.com/users/casperin/orgs", 26 | "repos_url": "https://api.github.com/users/casperin/repos", 27 | "events_url": "https://api.github.com/users/casperin/events{/privacy}", 28 | "received_events_url": "https://api.github.com/users/casperin/received_events", 29 | "type": "User" 30 | }, 31 | "private": false, 32 | "html_url": "https://github.com/casperin/functional-js", 33 | "description": "", 34 | "fork": false, 35 | "url": "https://api.github.com/repos/casperin/functional-js", 36 | "forks_url": "https://api.github.com/repos/casperin/functional-js/forks", 37 | "keys_url": "https://api.github.com/repos/casperin/functional-js/keys{/key_id}", 38 | "collaborators_url": "https://api.github.com/repos/casperin/functional-js/collaborators{/collaborator}", 39 | "teams_url": "https://api.github.com/repos/casperin/functional-js/teams", 40 | "hooks_url": "https://api.github.com/repos/casperin/functional-js/hooks", 41 | "issue_events_url": "https://api.github.com/repos/casperin/functional-js/issues/events{/number}", 42 | "events_url": "https://api.github.com/repos/casperin/functional-js/events", 43 | "assignees_url": "https://api.github.com/repos/casperin/functional-js/assignees{/user}", 44 | "branches_url": "https://api.github.com/repos/casperin/functional-js/branches{/branch}", 45 | "tags_url": "https://api.github.com/repos/casperin/functional-js/tags", 46 | "blobs_url": "https://api.github.com/repos/casperin/functional-js/git/blobs{/sha}", 47 | "git_tags_url": "https://api.github.com/repos/casperin/functional-js/git/tags{/sha}", 48 | "git_refs_url": "https://api.github.com/repos/casperin/functional-js/git/refs{/sha}", 49 | "trees_url": "https://api.github.com/repos/casperin/functional-js/git/trees{/sha}", 50 | "statuses_url": "https://api.github.com/repos/casperin/functional-js/statuses/{sha}", 51 | "languages_url": "https://api.github.com/repos/casperin/functional-js/languages", 52 | "stargazers_url": "https://api.github.com/repos/casperin/functional-js/stargazers", 53 | "contributors_url": "https://api.github.com/repos/casperin/functional-js/contributors", 54 | "subscribers_url": "https://api.github.com/repos/casperin/functional-js/subscribers", 55 | "subscription_url": "https://api.github.com/repos/casperin/functional-js/subscription", 56 | "commits_url": "https://api.github.com/repos/casperin/functional-js/commits{/sha}", 57 | "git_commits_url": "https://api.github.com/repos/casperin/functional-js/git/commits{/sha}", 58 | "comments_url": "https://api.github.com/repos/casperin/functional-js/comments{/number}", 59 | "issue_comment_url": "https://api.github.com/repos/casperin/functional-js/issues/comments/{number}", 60 | "contents_url": "https://api.github.com/repos/casperin/functional-js/contents/{+path}", 61 | "compare_url": "https://api.github.com/repos/casperin/functional-js/compare/{base}...{head}", 62 | "merges_url": "https://api.github.com/repos/casperin/functional-js/merges", 63 | "archive_url": "https://api.github.com/repos/casperin/functional-js/{archive_format}{/ref}", 64 | "downloads_url": "https://api.github.com/repos/casperin/functional-js/downloads", 65 | "issues_url": "https://api.github.com/repos/casperin/functional-js/issues{/number}", 66 | "pulls_url": "https://api.github.com/repos/casperin/functional-js/pulls{/number}", 67 | "milestones_url": "https://api.github.com/repos/casperin/functional-js/milestones{/number}", 68 | "notifications_url": "https://api.github.com/repos/casperin/functional-js/notifications{?since,all,participating}", 69 | "labels_url": "https://api.github.com/repos/casperin/functional-js/labels{/name}", 70 | "created_at": "2013-06-09T13:42:33Z", 71 | "updated_at": "2013-06-19T06:50:53Z", 72 | "pushed_at": "2013-06-19T06:50:53Z", 73 | "git_url": "git://github.com/casperin/functional-js.git", 74 | "ssh_url": "git@github.com:casperin/functional-js.git", 75 | "clone_url": "https://github.com/casperin/functional-js.git", 76 | "svn_url": "https://github.com/casperin/functional-js", 77 | "homepage": null, 78 | "size": 488, 79 | "watchers_count": 0, 80 | "language": "JavaScript", 81 | "has_issues": true, 82 | "has_downloads": true, 83 | "has_wiki": true, 84 | "forks_count": 0, 85 | "mirror_url": null, 86 | "open_issues_count": 0, 87 | "forks": 0, 88 | "open_issues": 0, 89 | "watchers": 0, 90 | "master_branch": "master", 91 | "default_branch": "master", 92 | "network_count": 0 93 | } 94 | }) 95 | -------------------------------------------------------------------------------- /support/lambdajs/test/spec/arrays_spec.js: -------------------------------------------------------------------------------- 1 | describe("Arrays", function() { 2 | it("concat", function() { 3 | var hege = ["Cecilie", "Lone"]; 4 | var stale = ["Emil", "Tobias", "Linus"]; 5 | var kai = ["Robin"]; 6 | expect(concat(hege,stale,kai)).toEqual(['Cecilie','Lone','Emil','Tobias','Linus','Robin']) 7 | expect(concat(hege)(stale,kai)).toEqual(['Cecilie','Lone','Emil','Tobias','Linus','Robin']) 8 | }); 9 | 10 | it("every", function() { 11 | var isBigEnough = lte(10); 12 | expect(every(isBigEnough, [12, 5, 8, 130, 44])).toBeFalsy(); 13 | expect(every(isBigEnough, [12, 54, 18, 130, 44])).toBeTruthy(); 14 | }); 15 | 16 | it("filter", function() { 17 | var isEven = function(n) { return !(n % 2); } 18 | expect(filter(isEven, [1,2,3,4])).toEqual([2,4]); 19 | expect(filter(isEven)([1,2,3,4])).toEqual([2,4]); 20 | }); 21 | 22 | it("forEach", function() { 23 | var x = 1; 24 | var addToX = function(y){ x += y } 25 | forEach(addToX, [2, 5]); 26 | expect(x).toEqual(8) 27 | }); 28 | 29 | it("indexOf", function() { 30 | var fruits = ["Banana", "Orange", "Apple", "Mango"]; 31 | expect(indexOf("Apple", fruits)).toEqual(2); 32 | expect(indexOf("Apple")(fruits)).toEqual(2); 33 | }); 34 | 35 | it("indexOf_", function() { 36 | var fruits = ["Banana", "Orange", "Apple", "Mango", "Apple"]; 37 | expect(indexOf_("Apple", 3, fruits)).toEqual(4); 38 | expect(indexOf_("Apple", 3)(fruits)).toEqual(4); 39 | }); 40 | 41 | it("join", function() { 42 | var fruits = ["Banana", "Orange", "Apple", "Mango"]; 43 | expect(join(' ', fruits)).toEqual("Banana Orange Apple Mango"); 44 | expect(join(' ')(fruits)).toEqual("Banana Orange Apple Mango"); 45 | }); 46 | 47 | it("lastIndexOf", function() { 48 | var fruits = ["Banana", "Orange", "Apple", "Mango"]; 49 | expect(lastIndexOf('Apple', fruits)).toEqual(2); 50 | expect(lastIndexOf('Apple')(fruits)).toEqual(2); 51 | }); 52 | 53 | it("map", function() { 54 | var addOne = add(1); 55 | expect(map(addOne, [1,2,3,4])).toEqual([2, 3, 4, 5]); 56 | expect(map(addOne)([1,2,3,4])).toEqual([2, 3, 4, 5]); 57 | }); 58 | 59 | it("pop", function() { 60 | var fruits = ["Banana", "Orange", "Apple", "Mango"]; 61 | expect(pop(fruits)).toEqual(["Banana", "Orange", "Apple"]); 62 | expect(fruits).toEqual(["Banana", "Orange", "Apple", "Mango"]); 63 | }); 64 | 65 | it("push", function() { 66 | var fruits = ["Banana", "Orange", "Apple", "Mango"]; 67 | expect(push("Kiwi", fruits)).toEqual(["Banana", "Orange", "Apple", "Mango", "Kiwi"]); 68 | expect(push("Kiwi")(fruits)).toEqual(["Banana", "Orange", "Apple", "Mango", "Kiwi"]); 69 | expect(fruits).toEqual(["Banana", "Orange", "Apple", "Mango"]); 70 | }); 71 | 72 | it("reduce", function() { 73 | var sum = function(sum, num) { return sum + num; }; 74 | expect(reduce(sum, 0, [1,2,3,4])).toEqual(10); 75 | expect(reduce(sum)(0)([1,2,3,4])).toEqual(10); 76 | expect(reduce(sum, 0)([1,2,3,4])).toEqual(10); 77 | }); 78 | 79 | it("reduceRight", function() { 80 | var words = ['foo', 'bar', 'baz']; 81 | expect(reduceRight(add, '', words)).toEqual('bazbarfoo'); 82 | expect(reduceRight(add)('', words)).toEqual('bazbarfoo'); 83 | expect(reduceRight(add)('')(words)).toEqual('bazbarfoo'); 84 | expect(reduceRight(add, '')(words)).toEqual('bazbarfoo'); 85 | }); 86 | 87 | it("reverse", function() { 88 | var fruits = ["Banana", "Orange", "Apple", "Mango"]; 89 | expect(reverse(fruits)).toEqual(["Mango", "Apple", "Orange", "Banana"]); 90 | expect(fruits).toEqual(["Banana", "Orange", "Apple", "Mango"]); 91 | }); 92 | 93 | it("shift", function() { 94 | var fruits = ["Banana", "Orange", "Apple", "Mango"]; 95 | expect(shift(fruits)).toEqual(["Orange", "Apple", "Mango"]); 96 | expect(fruits).toEqual(["Banana", "Orange", "Apple", "Mango"]); 97 | }); 98 | 99 | it("slice", function() { 100 | var fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"]; 101 | expect(slice(1,fruits)).toEqual(["Orange", "Lemon", "Apple", "Mango"]); 102 | expect(slice(2)(fruits)).toEqual(["Lemon", "Apple", "Mango"]); 103 | }); 104 | 105 | it("slice_", function() { 106 | var fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"]; 107 | expect(slice_(1,3,fruits)).toEqual(["Orange", "Lemon"]); 108 | expect(slice_(1)(3)(fruits)).toEqual(["Orange", "Lemon"]); 109 | }); 110 | 111 | it("some", function() { 112 | var isBigEnough = lte(10); 113 | expect(some(isBigEnough, [2, 5, 8, 1, 4])).toBeFalsy() 114 | expect(some(isBigEnough, [12, 5, 8, 1, 4])).toBeTruthy() 115 | }); 116 | 117 | it("sort", function() { 118 | var fruits = ["Banana", "Orange", "Apple", "Mango"]; 119 | expect(sort(fruits)).toEqual(["Apple", "Banana", "Mango", "Orange"]); 120 | expect(fruits).toEqual(["Banana", "Orange", "Apple", "Mango"]); 121 | }); 122 | 123 | it("splice", function() { 124 | var fruits = ["Banana", "Orange", "Apple", "Mango"]; 125 | expect(splice(2, 1, fruits)).toEqual(["Banana", "Orange", "Mango"]); 126 | expect(splice(2)(1)(fruits)).toEqual(["Banana", "Orange", "Mango"]); 127 | expect(fruits).toEqual(["Banana", "Orange", "Apple", "Mango"]); 128 | }); 129 | 130 | it("toString", function() { 131 | var fruits = ["Banana", "Orange", "Apple", "Mango"]; 132 | expect(toString(fruits)).toEqual("Banana,Orange,Apple,Mango"); 133 | }); 134 | 135 | it("toLocaleString", function() { 136 | var fruits = ["Banana", "Orange", "Apple", "Mango"]; 137 | expect(toLocaleString(fruits)).toEqual("Banana,Orange,Apple,Mango"); 138 | }); 139 | 140 | it("unshift", function() { 141 | var fruits = ["Banana", "Orange", "Apple", "Mango"]; 142 | expect(unshift("Lemon", fruits)).toEqual(["Lemon", "Banana", "Orange", "Apple", "Mango"]); 143 | expect(fruits).toEqual(["Banana", "Orange", "Apple", "Mango"]); 144 | }); 145 | }); 146 | -------------------------------------------------------------------------------- /support/lambdajs/test/lib/jasmine-1.2.0/jasmine.css: -------------------------------------------------------------------------------- 1 | body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; } 2 | 3 | #HTMLReporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; } 4 | #HTMLReporter a { text-decoration: none; } 5 | #HTMLReporter a:hover { text-decoration: underline; } 6 | #HTMLReporter p, #HTMLReporter h1, #HTMLReporter h2, #HTMLReporter h3, #HTMLReporter h4, #HTMLReporter h5, #HTMLReporter h6 { margin: 0; line-height: 14px; } 7 | #HTMLReporter .banner, #HTMLReporter .symbolSummary, #HTMLReporter .summary, #HTMLReporter .resultMessage, #HTMLReporter .specDetail .description, #HTMLReporter .alert .bar, #HTMLReporter .stackTrace { padding-left: 9px; padding-right: 9px; } 8 | #HTMLReporter #jasmine_content { position: fixed; right: 100%; } 9 | #HTMLReporter .version { color: #aaaaaa; } 10 | #HTMLReporter .banner { margin-top: 14px; } 11 | #HTMLReporter .duration { color: #aaaaaa; float: right; } 12 | #HTMLReporter .symbolSummary { overflow: hidden; *zoom: 1; margin: 14px 0; } 13 | #HTMLReporter .symbolSummary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; } 14 | #HTMLReporter .symbolSummary li.passed { font-size: 14px; } 15 | #HTMLReporter .symbolSummary li.passed:before { color: #5e7d00; content: "\02022"; } 16 | #HTMLReporter .symbolSummary li.failed { line-height: 9px; } 17 | #HTMLReporter .symbolSummary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; } 18 | #HTMLReporter .symbolSummary li.skipped { font-size: 14px; } 19 | #HTMLReporter .symbolSummary li.skipped:before { color: #bababa; content: "\02022"; } 20 | #HTMLReporter .symbolSummary li.pending { line-height: 11px; } 21 | #HTMLReporter .symbolSummary li.pending:before { color: #aaaaaa; content: "-"; } 22 | #HTMLReporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; } 23 | #HTMLReporter .runningAlert { background-color: #666666; } 24 | #HTMLReporter .skippedAlert { background-color: #aaaaaa; } 25 | #HTMLReporter .skippedAlert:first-child { background-color: #333333; } 26 | #HTMLReporter .skippedAlert:hover { text-decoration: none; color: white; text-decoration: underline; } 27 | #HTMLReporter .passingAlert { background-color: #a6b779; } 28 | #HTMLReporter .passingAlert:first-child { background-color: #5e7d00; } 29 | #HTMLReporter .failingAlert { background-color: #cf867e; } 30 | #HTMLReporter .failingAlert:first-child { background-color: #b03911; } 31 | #HTMLReporter .results { margin-top: 14px; } 32 | #HTMLReporter #details { display: none; } 33 | #HTMLReporter .resultsMenu, #HTMLReporter .resultsMenu a { background-color: #fff; color: #333333; } 34 | #HTMLReporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; } 35 | #HTMLReporter.showDetails .summaryMenuItem:hover { text-decoration: underline; } 36 | #HTMLReporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; } 37 | #HTMLReporter.showDetails .summary { display: none; } 38 | #HTMLReporter.showDetails #details { display: block; } 39 | #HTMLReporter .summaryMenuItem { font-weight: bold; text-decoration: underline; } 40 | #HTMLReporter .summary { margin-top: 14px; } 41 | #HTMLReporter .summary .suite .suite, #HTMLReporter .summary .specSummary { margin-left: 14px; } 42 | #HTMLReporter .summary .specSummary.passed a { color: #5e7d00; } 43 | #HTMLReporter .summary .specSummary.failed a { color: #b03911; } 44 | #HTMLReporter .description + .suite { margin-top: 0; } 45 | #HTMLReporter .suite { margin-top: 14px; } 46 | #HTMLReporter .suite a { color: #333333; } 47 | #HTMLReporter #details .specDetail { margin-bottom: 28px; } 48 | #HTMLReporter #details .specDetail .description { display: block; color: white; background-color: #b03911; } 49 | #HTMLReporter .resultMessage { padding-top: 14px; color: #333333; } 50 | #HTMLReporter .resultMessage span.result { display: block; } 51 | #HTMLReporter .stackTrace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; } 52 | 53 | #TrivialReporter { padding: 8px 13px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow-y: scroll; background-color: white; font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; /*.resultMessage {*/ /*white-space: pre;*/ /*}*/ } 54 | #TrivialReporter a:visited, #TrivialReporter a { color: #303; } 55 | #TrivialReporter a:hover, #TrivialReporter a:active { color: blue; } 56 | #TrivialReporter .run_spec { float: right; padding-right: 5px; font-size: .8em; text-decoration: none; } 57 | #TrivialReporter .banner { color: #303; background-color: #fef; padding: 5px; } 58 | #TrivialReporter .logo { float: left; font-size: 1.1em; padding-left: 5px; } 59 | #TrivialReporter .logo .version { font-size: .6em; padding-left: 1em; } 60 | #TrivialReporter .runner.running { background-color: yellow; } 61 | #TrivialReporter .options { text-align: right; font-size: .8em; } 62 | #TrivialReporter .suite { border: 1px outset gray; margin: 5px 0; padding-left: 1em; } 63 | #TrivialReporter .suite .suite { margin: 5px; } 64 | #TrivialReporter .suite.passed { background-color: #dfd; } 65 | #TrivialReporter .suite.failed { background-color: #fdd; } 66 | #TrivialReporter .spec { margin: 5px; padding-left: 1em; clear: both; } 67 | #TrivialReporter .spec.failed, #TrivialReporter .spec.passed, #TrivialReporter .spec.skipped { padding-bottom: 5px; border: 1px solid gray; } 68 | #TrivialReporter .spec.failed { background-color: #fbb; border-color: red; } 69 | #TrivialReporter .spec.passed { background-color: #bfb; border-color: green; } 70 | #TrivialReporter .spec.skipped { background-color: #bbb; } 71 | #TrivialReporter .messages { border-left: 1px dashed gray; padding-left: 1em; padding-right: 1em; } 72 | #TrivialReporter .passed { background-color: #cfc; display: none; } 73 | #TrivialReporter .failed { background-color: #fbb; } 74 | #TrivialReporter .skipped { color: #777; background-color: #eee; display: none; } 75 | #TrivialReporter .resultMessage span.result { display: block; line-height: 2em; color: black; } 76 | #TrivialReporter .resultMessage .mismatch { color: black; } 77 | #TrivialReporter .stackTrace { white-space: pre; font-size: .8em; margin-left: 10px; max-height: 5em; overflow: auto; border: 1px inset red; padding: 1em; background: #eef; } 78 | #TrivialReporter .finished-at { padding-left: 1em; font-size: .6em; } 79 | #TrivialReporter.show-passed .passed, #TrivialReporter.show-skipped .skipped { display: block; } 80 | #TrivialReporter #jasmine_content { position: fixed; right: 100%; } 81 | #TrivialReporter .runner { border: 1px solid gray; display: block; margin: 5px 0; padding: 2px 0 2px 10px; } 82 | -------------------------------------------------------------------------------- /support/node-promise/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-promise", 3 | "description": "Kris Zyp's implementation of promises with added features, maintained as an npm package.", 4 | "version": "0.5.5", 5 | "homepage": "https://github.com/MaxMotovilov/node-promise", 6 | "files": [ 7 | "package.json", 8 | "promise.js", 9 | "fs-promise.js" 10 | ], 11 | "main": "promise.js", 12 | "repository": { 13 | "type": "git", 14 | "url": "https://MaxMotovilov@github.com/MaxMotovilov/node-promise.git" 15 | }, 16 | "readme": "MIT License.\n\nThe node-promise project provides a complete promise implementation. Promises provide a clean separation\nof concerns between asynchronous behavior and the interface so asynchronous\nfunctions can be called without callbacks, and callback interaction can be \ndone on the generic promise interface. The node-promise package provides just a promise implementation, however, https://github.com/kriszyp/promised-io is recommended for more complete promise-based IO functionality. The promised-io includes the promise implementation from node-promise, as well as wrappers around Node's filesystem and other system I/O APIs for consistent promise-based interaction.\n\nThe node-promise module features a promise implementation with:\n\n* Chainable promises\n* Promises throw errors if an error handler is not provided\n* CommonJS promise proposal [1] compliant\n* Immutable once fulfilled to reduce possible side-effects\n* Promises can be used securely (as separate resolver/promise pairs in\nocap situations)\n* Backwards compatibility where possible (addCallback, addErrback,\nemitSuccess, and emitError should still behave as expected)\n\nUtility functions, including:\n\n* when() - Normalization of sync (normal values) and async (promises)\n* all() - Create a promise that accumulate multiple concurrent promises (failed promises resolve to Error objects)\n* allOrNone() - Ditto, but the first promise to fail causes the composition to fail as well\n* first() - Find the first promise to be fulfilled in a group of promises\n* seq() - Sequentially execute a set of promise returning functions\n* delay() - Returns a promise that is fulfilled after a given amount of time\n* execute() - Executes a function that takes a callback and returns a\npromise (thank you Benjamin Thomas for providing this)\n\nMuch of this is adapted from Tyler Close's ref_send and Kris Kowal's work on promises. \n\nSome quick examples from test-promise.js (again, it is recommended that you use http://github.com/kriszyp/promised-io for file and other I/O interaction):\n util = require('util');\n var fs = require('./fs-promise');\n\n // open a file and read it\n fs.open(\"fs-promise.js\", process.O_RDONLY).then(function(fd){\n return fs.read(fd, 4096);\n }).then(function(args){\n util.puts(args[0]); // print the contents of the file\n });\n\n // does the same thing\n fs.readFile(\"fs-promise.js\").addCallback(util.puts);\n\nA default Promise constructor can be used to create a self-resolving deferred/promise:\n\n var Promise = require(\"promise\").Promise;\n var promise = new Promise();\n asyncOperation(function(){\n Promise.resolve(\"succesful result\");\n });\n promise -> given to the consumer\n \nA consumer can use the promise:\n\n promise.then(function(result){\n ... when the action is complete this is executed ...\n },\n function(error){\n ... executed when the promise fails\n });\n\nAlternately, a provider can create a deferred and resolve it when it completes an action. \nThe deferred object a promise object that provides a separation of consumer and producer to protect\npromises from being fulfilled by untrusted code.\n\n var defer = require(\"promise\").defer;\n var deferred = defer();\n asyncOperation(function(){\n deferred.resolve(\"succesful result\");\n });\n deferred.promise -> given to the consumer\n \nAnother way that a consumer can use promises:\n\n var when = require(\"promise\").when;\n when(promise,function(result){\n ... when the action is complete this is executed ...\n },\n function(error){\n ... executed when the promise fails\n });\n\nMore examples:\n\n function printFirstAndList(itemsDeferred){\n findFirst(itemsDeferred).then(util.puts);\n findLast(itemsDeferred).then(util.puts);\n }\n function findFirst(itemsDeferred){\n return itemsDeferred.then(function(items){\n return items[0];\n });\n }\n function findLast(itemsDeferred){\n return itemsDeferred.then(function(items){\n return items[items.length];\n });\n }\n\nAnd now you can do:\n\n printFirstAndLast(someAsyncFunction());\n\n\nThe workhorse function of this library is the \"when\" function, which provides a means for normalizing interaction with values and functions that may be a normal synchronous value, or may be a promise (asynchronously fulfilled). The when() function takes a value that may be a promise or a normal value for the first function, and when the value is ready executes the function provided as the second argument (immediately in the case of a non-promise normal value). The value returned from when() is the result of the execution of the provided function, and returns a promise if provided a promise or synchronously returns a normal value if provided a non-promise value. This makes it easy to \"chain\" computations together. This allows us to write code that is agnostic to sync/async interfaces:\n\n var when = require(\"promise\").when;\n function printFirstAndLast(items){\n // print the first and last item\n when(findFirst(items), util.puts);\n when(findLast(items), util.puts);\n }\n function findFirst(items){\n // return the first item\n return when(items, function(items){\n return items[0];\n });\n }\n function findLast(items){\n // return the last item\n return when(items, function(items){\n return items[items.length - 1];\n });\n }\n\nNow we can do:\n\n > printFirstAndLast([1,2,3,4,5]);\n 1\n 5\n\nAnd we can also provide asynchronous promise:\n\n var promise = new process.Promise();\n > printFirstAndLast(promise);\n\n(nothing printed yet)\n\n > promise.emitSuccess([2,4,6,8,10]);\n 2\n 10\n\n\nThe \"all\" function is intended to provide a means for waiting for the completion of an array of promises. The \"all\" function should be passed an array of promises, and it returns an promise that is fulfilled once all the promises in the array are fulfilled. The returned promise's resolved value will be an array with the resolved values of all of the promises in the passed in array.\n\nThe \"first\" function is intended to provide a means for waiting for the completion of the first promise in an array of promises to be fulfilled. The \"first\" function should be passed an array of promises, and it returns an promise that is fulfilled once the first promise in the array is fulfilled. The returned promise's resolved value will be the resolved value of the first fulfilled promise.\n\n", 17 | "_id": "node-promise@0.5.5", 18 | "dist": { 19 | "shasum": "02d8a08c64561e6a8d211fd045b4f438303937f9" 20 | }, 21 | "_from": "node-promise" 22 | } 23 | -------------------------------------------------------------------------------- /support/node-promise/README.md: -------------------------------------------------------------------------------- 1 | MIT License. 2 | 3 | The node-promise project provides a complete promise implementation. Promises provide a clean separation 4 | of concerns between asynchronous behavior and the interface so asynchronous 5 | functions can be called without callbacks, and callback interaction can be 6 | done on the generic promise interface. The node-promise package provides just a promise implementation, however, https://github.com/kriszyp/promised-io is recommended for more complete promise-based IO functionality. The promised-io includes the promise implementation from node-promise, as well as wrappers around Node's filesystem and other system I/O APIs for consistent promise-based interaction. 7 | 8 | The node-promise module features a promise implementation with: 9 | 10 | * Chainable promises 11 | * Promises throw errors if an error handler is not provided 12 | * CommonJS promise proposal [1] compliant 13 | * Immutable once fulfilled to reduce possible side-effects 14 | * Promises can be used securely (as separate resolver/promise pairs in 15 | ocap situations) 16 | * Backwards compatibility where possible (addCallback, addErrback, 17 | emitSuccess, and emitError should still behave as expected) 18 | 19 | Utility functions, including: 20 | 21 | * when() - Normalization of sync (normal values) and async (promises) 22 | * all() - Create a promise that accumulate multiple concurrent promises (failed promises resolve to Error objects) 23 | * allOrNone() - Ditto, but the first promise to fail causes the composition to fail as well 24 | * first() - Find the first promise to be fulfilled in a group of promises 25 | * seq() - Sequentially execute a set of promise returning functions 26 | * delay() - Returns a promise that is fulfilled after a given amount of time 27 | * execute() - Executes a function that takes a callback and returns a 28 | promise (thank you Benjamin Thomas for providing this) 29 | 30 | Much of this is adapted from Tyler Close's ref_send and Kris Kowal's work on promises. 31 | 32 | Some quick examples from test-promise.js (again, it is recommended that you use http://github.com/kriszyp/promised-io for file and other I/O interaction): 33 | util = require('util'); 34 | var fs = require('./fs-promise'); 35 | 36 | // open a file and read it 37 | fs.open("fs-promise.js", process.O_RDONLY).then(function(fd){ 38 | return fs.read(fd, 4096); 39 | }).then(function(args){ 40 | util.puts(args[0]); // print the contents of the file 41 | }); 42 | 43 | // does the same thing 44 | fs.readFile("fs-promise.js").addCallback(util.puts); 45 | 46 | A default Promise constructor can be used to create a self-resolving deferred/promise: 47 | 48 | var Promise = require("promise").Promise; 49 | var promise = new Promise(); 50 | asyncOperation(function(){ 51 | Promise.resolve("succesful result"); 52 | }); 53 | promise -> given to the consumer 54 | 55 | A consumer can use the promise: 56 | 57 | promise.then(function(result){ 58 | ... when the action is complete this is executed ... 59 | }, 60 | function(error){ 61 | ... executed when the promise fails 62 | }); 63 | 64 | Alternately, a provider can create a deferred and resolve it when it completes an action. 65 | The deferred object a promise object that provides a separation of consumer and producer to protect 66 | promises from being fulfilled by untrusted code. 67 | 68 | var defer = require("promise").defer; 69 | var deferred = defer(); 70 | asyncOperation(function(){ 71 | deferred.resolve("succesful result"); 72 | }); 73 | deferred.promise -> given to the consumer 74 | 75 | Another way that a consumer can use promises: 76 | 77 | var when = require("promise").when; 78 | when(promise,function(result){ 79 | ... when the action is complete this is executed ... 80 | }, 81 | function(error){ 82 | ... executed when the promise fails 83 | }); 84 | 85 | More examples: 86 | 87 | function printFirstAndList(itemsDeferred){ 88 | findFirst(itemsDeferred).then(util.puts); 89 | findLast(itemsDeferred).then(util.puts); 90 | } 91 | function findFirst(itemsDeferred){ 92 | return itemsDeferred.then(function(items){ 93 | return items[0]; 94 | }); 95 | } 96 | function findLast(itemsDeferred){ 97 | return itemsDeferred.then(function(items){ 98 | return items[items.length]; 99 | }); 100 | } 101 | 102 | And now you can do: 103 | 104 | printFirstAndLast(someAsyncFunction()); 105 | 106 | 107 | The workhorse function of this library is the "when" function, which provides a means for normalizing interaction with values and functions that may be a normal synchronous value, or may be a promise (asynchronously fulfilled). The when() function takes a value that may be a promise or a normal value for the first function, and when the value is ready executes the function provided as the second argument (immediately in the case of a non-promise normal value). The value returned from when() is the result of the execution of the provided function, and returns a promise if provided a promise or synchronously returns a normal value if provided a non-promise value. This makes it easy to "chain" computations together. This allows us to write code that is agnostic to sync/async interfaces: 108 | 109 | var when = require("promise").when; 110 | function printFirstAndLast(items){ 111 | // print the first and last item 112 | when(findFirst(items), util.puts); 113 | when(findLast(items), util.puts); 114 | } 115 | function findFirst(items){ 116 | // return the first item 117 | return when(items, function(items){ 118 | return items[0]; 119 | }); 120 | } 121 | function findLast(items){ 122 | // return the last item 123 | return when(items, function(items){ 124 | return items[items.length - 1]; 125 | }); 126 | } 127 | 128 | Now we can do: 129 | 130 | > printFirstAndLast([1,2,3,4,5]); 131 | 1 132 | 5 133 | 134 | And we can also provide asynchronous promise: 135 | 136 | var promise = new process.Promise(); 137 | > printFirstAndLast(promise); 138 | 139 | (nothing printed yet) 140 | 141 | > promise.emitSuccess([2,4,6,8,10]); 142 | 2 143 | 10 144 | 145 | 146 | The "all" function is intended to provide a means for waiting for the completion of an array of promises. The "all" function should be passed an array of promises, and it returns an promise that is fulfilled once all the promises in the array are fulfilled. The returned promise's resolved value will be an array with the resolved values of all of the promises in the passed in array. 147 | 148 | The "first" function is intended to provide a means for waiting for the completion of the first promise in an array of promises to be fulfilled. The "first" function should be passed an array of promises, and it returns an promise that is fulfilled once the first promise in the array is fulfilled. The returned promise's resolved value will be the resolved value of the first fulfilled promise. 149 | 150 | -------------------------------------------------------------------------------- /vendor/FunctionalJS/specs/functional.spec.coffee: -------------------------------------------------------------------------------- 1 | functional = require('../functional') 2 | functional.expose() 3 | 4 | describe("functional", -> 5 | sum = (x, y) -> x + y 6 | addOne = (x) -> x + 1 7 | times2 = (x) -> x * 2 8 | subtract = (x, y) -> x - y 9 | 10 | it("should load properly using different module schemes", -> 11 | expect(functional).not.toBeUndefined() 12 | expect(typeof functional.compose).toEqual('function') 13 | ) 14 | 15 | describe("expose", -> 16 | it("can attach functions to the global namespace", -> 17 | expect(typeof functional.expose).toEqual('function') 18 | expect(typeof compose).toEqual('function') 19 | ) 20 | ) 21 | 22 | describe("autoCurry", -> 23 | it("is added to the Function prototype", -> 24 | expect(typeof Function.prototype.autoCurry).toEqual('function') 25 | ) 26 | 27 | it("enables a function to be partially applied", -> 28 | add = (a, b, c) -> a + b + c 29 | implicit = add.autoCurry() 30 | explicit = add.autoCurry(3) 31 | expect(implicit(1)(1)(1)).toEqual(3) 32 | expect(explicit(1)(1)(1)).toEqual(3) 33 | expect(implicit(1, 1)(1)).toEqual(3) 34 | expect(explicit(1, 1)(1)).toEqual(3) 35 | expect(implicit(1)(1, 1)).toEqual(3) 36 | expect(explicit(1)(1, 1)).toEqual(3) 37 | expect(implicit(1, 1, 1)).toEqual(3) 38 | expect(explicit(1, 1, 1)).toEqual(3) 39 | ) 40 | ) 41 | 42 | describe("map", -> 43 | it("returns the correct result when iterating over an array", -> 44 | expect(map(addOne, [1, 2, 3])).toEqual([2, 3, 4]) 45 | ) 46 | 47 | it("partially applies arguments", -> 48 | expect(map(addOne)([1, 2, 3])).toEqual([2, 3, 4]) 49 | ) 50 | ) 51 | 52 | describe("compose", -> 53 | it("composes functions, and applies functions right to left", -> 54 | expect(compose(addOne, times2)(3)).toEqual(7) 55 | expect(compose(addOne, times2, sum)(1, 2)).toEqual(7) 56 | ) 57 | ) 58 | 59 | describe("sequence", -> 60 | it("composes functions, and applies functions left to right", -> 61 | expect(sequence(times2, addOne)(3)).toEqual(7) 62 | expect(sequence(sum, times2, addOne)(1, 2)).toEqual(7) 63 | ) 64 | ) 65 | 66 | describe("memoize", -> 67 | fib = (n) -> if n < 2 then n else fib(n - 1) + fib(n - 2) 68 | fastFib = memoize(fib) 69 | 70 | it("returns a memoized function that produces identical results", -> 71 | expect(fib(10)).toEqual(55) 72 | expect(fastFib(10)).toEqual(55) 73 | ) 74 | ) 75 | 76 | describe("reduce", -> 77 | it("can sum up an array", -> 78 | expect(reduce(sum, 0, [1, 2, 3])).toEqual(6) 79 | ) 80 | it("can partially apply arguments", -> 81 | expect(reduce(sum)(0, [1, 2, 3])).toEqual(6) 82 | expect(reduce(sum, 0)([1, 2, 3])).toEqual(6) 83 | ) 84 | 85 | it("is aliased as 'foldl'", -> 86 | expect(foldl(sum, 0, [1, 2, 3])).toEqual(6) 87 | expect(foldl(sum)(0, [1, 2, 3])).toEqual(6) 88 | expect(foldl(sum, 0)([1, 2, 3])).toEqual(6) 89 | ) 90 | ) 91 | 92 | describe("select", -> 93 | isEven = (x) -> x % 2 == 0 94 | 95 | it("filters an array based on a criteria (function)", -> 96 | expect(select(isEven, [1, 2, 3, 4, 5, 6])).toEqual([2, 4, 6]) 97 | ) 98 | 99 | it("can be partially applied", -> 100 | expect(select(isEven)([1, 2, 3, 4, 5, 6])).toEqual([2, 4, 6]) 101 | ) 102 | 103 | it("is aliased as 'filter'", -> 104 | expect(filter(isEven, [1, 2, 3, 4, 5, 6])).toEqual([2, 4, 6]) 105 | expect(filter(isEven)([1, 2, 3, 4, 5, 6])).toEqual([2, 4, 6]) 106 | ) 107 | ) 108 | 109 | describe("guard", -> 110 | truthy = -> true 111 | falsy = -> false 112 | 113 | it("guards a function, acts like an if/else statement", -> 114 | expect(guard(truthy, addOne, times2)(3)).toEqual(4) 115 | expect(guard(falsy, addOne, times2)(3)).toEqual(6) 116 | expect(guard(id, addOne, times2)(3)).toEqual(4) 117 | expect(guard(id, addOne, times2)(0)).toEqual(0) 118 | ) 119 | ) 120 | 121 | describe("flip", -> 122 | it("returns a function with the first two arguments flipped", -> 123 | expect(subtract(1, 2)).toEqual(-1) 124 | expect(flip(subtract)(1, 2)).toEqual(1) 125 | ) 126 | ) 127 | 128 | describe("foldr", -> 129 | it("can sum up an array", -> 130 | expect(foldr(sum, 0, [1, 2, 3])).toEqual(6) 131 | ) 132 | it("can partially apply arguments", -> 133 | expect(foldr(sum)(0, [1, 2, 3])).toEqual(6) 134 | expect(foldr(sum, 0)([1, 2, 3])).toEqual(6) 135 | ) 136 | ) 137 | 138 | describe("and", -> 139 | it("returns a function that returns 'true' when all arguments applied to function's arguments return true", -> 140 | expect(andd('>1', '>2')(3)).toEqual(true) 141 | expect(andd('>1', '>2')(2)).toEqual(false) 142 | expect(andd('>1', 'error()')(1)).toEqual(false) 143 | ) 144 | ) 145 | 146 | describe("or", -> 147 | it("returns a function that returns 'true' when one of the arguments applied to the function's arguments returns true", -> 148 | expect(orr('>1', '>2')(2)).toEqual(true) 149 | expect(orr('>1', '>2')(0)).toEqual(false) 150 | expect(orr('>1', 'error()')(2)).toEqual(true) 151 | ) 152 | ) 153 | 154 | describe("some", -> 155 | xs = [1, 2, 3] 156 | it("returns true when the function returns true for some element in the sequence", -> 157 | expect(some('>2', xs)).toEqual(true) 158 | expect(some('>10', xs)).toEqual(false) 159 | ) 160 | 161 | it("can be partially applied", -> 162 | expect(some('>2')(xs)).toEqual(true) 163 | expect(some('>10')(xs)).toEqual(false) 164 | ) 165 | ) 166 | 167 | describe("every", -> 168 | xs = [1, 2, 3] 169 | it("returns true when the function returns true for every element in the sequence", -> 170 | expect(every('<2', xs)).toEqual(false) 171 | expect(every('<10', xs)).toEqual(true) 172 | ) 173 | 174 | it("can be partially applied", -> 175 | expect(every('<2')(xs)).toEqual(false) 176 | expect(every('<10')(xs)).toEqual(true) 177 | ) 178 | ) 179 | 180 | describe("not", -> 181 | it("returns a function that returns true when the function/argument returns false", -> 182 | expect(nott('<2')(3)).toEqual(true) 183 | expect(nott('<2')(1)).toEqual(false) 184 | ) 185 | ) 186 | 187 | describe("equal", -> 188 | it("Returns a function that returns true when this function's arguments applied to that function's are always the same", -> 189 | expect(equal()()).toEqual(true) 190 | expect(equal(K(1))()).toEqual(true) 191 | expect(equal(K(1), K(1))()).toEqual(true) 192 | expect(equal(K(1), K(2))()).toEqual(false) 193 | expect(equal(K(1), K(2), 'error()')()).toEqual(false) 194 | ) 195 | ) 196 | 197 | describe("lambda", -> 198 | it("Returns its argument coerced to a function", -> 199 | expect(lambda('+1')(2)).toEqual(3) 200 | expect(lambda(addOne)(2)).toEqual(3) 201 | ) 202 | ) 203 | 204 | describe("invoke", -> 205 | obj = { addOne: addOne } 206 | it("Returns a function that takes an object and applies the object's method name to the arguments", -> 207 | expect(invoke('addOne')(obj, 2)).toEqual(3) 208 | ) 209 | ) 210 | 211 | describe("pluck", -> 212 | it("Returns a function that takes an object and returns the value of its 'name' property", -> 213 | expect(pluck('age')({ age: 23 })).toEqual(23) 214 | ) 215 | ) 216 | 217 | describe("until", -> 218 | it("Returns a function that applies first, an argument, then each retur value to a function until a condition is met", -> 219 | expect(untill('>10', '2*')(1)).toEqual(16) 220 | ) 221 | ) 222 | 223 | describe("zip", -> 224 | it("Returns an array of arrays, grouping together the values at each index of multiple arrays", -> 225 | expect(zip([1, 2, 3], [4, 5, 6], [7, 8, 9])).toEqual( 226 | [ [1, 4, 7], [2, 5, 8], [3, 6, 9] ] 227 | ) 228 | ) 229 | ) 230 | 231 | describe("I", -> 232 | it("is the identity function, returning whatever argument is passed in", -> 233 | expect(I(1)).toEqual(1); 234 | expect(I('sweet')).toEqual('sweet') 235 | ) 236 | 237 | it("has an alias of 'id'", -> 238 | expect(id(1)).toEqual(1) 239 | expect(id('sweet')).toEqual('sweet') 240 | ) 241 | ) 242 | 243 | describe("K", -> 244 | it("Returns a constant function that returns whatever argument is passed in", -> 245 | expect(K(1)(2)).toEqual(1) 246 | expect(K('sweet')('foo')).toEqual('sweet') 247 | ) 248 | 249 | it("has an alias of 'constfn'", -> 250 | expect(constfn(1)(2)).toEqual(1) 251 | expect(constfn('sweet')('foo')).toEqual('sweet') 252 | ) 253 | ) 254 | 255 | describe("S", -> 256 | it("Returns the composition of two functions, applying the first function to the result of the second, AND the original arguments", -> 257 | expect(S('+', '_ a b -> a*b')(2,3,4)).toEqual(14) 258 | ) 259 | ) 260 | 261 | ) 262 | -------------------------------------------------------------------------------- /support/lambdajs/lambda.js: -------------------------------------------------------------------------------- 1 | ;(function(root) { 2 | var curry = require('lodash.curry'); 3 | 4 | /** Detect free variables */ 5 | var freeGlobal = {} 6 | if(typeof window == "object") freeGlobal.window = window; 7 | var freeExports = typeof exports == 'object' && exports; 8 | var freeModule = typeof module == 'object' && module && 9 | module.exports == freeExports && module; 10 | var freeGlobal = typeof global == 'object' && global; 11 | if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) { 12 | root = freeGlobal; 13 | } 14 | 15 | // All methods from 16 | // * Arrays 17 | // * Numbers 18 | // * Objects 19 | // * Regexp 20 | // * Strings 21 | // * Date (coming soon) 22 | 23 | 24 | // RULES: 25 | // 1. The data comes last. E.g: str.method(arg) -> method(arg, str) 26 | // 2. Everything is curried 27 | // 3. Functions with optional arguments are split into two functions. One with _ at the end that takes the options. E.g: indexOf(x,str) & indexOf_(x,y,str) 28 | // 4. Everything is pure in that it doesn't mutate arguments 29 | 30 | LambdaJS = {}; 31 | Strings = {}; 32 | Arrays = {}; 33 | Objects = {}; 34 | Regexps = {}; 35 | Numbers = {}; 36 | 37 | 38 | 39 | // STRINGS 40 | // ========================= 41 | 42 | //+ charAt :: Int -> String -> String 43 | Strings.charAt = curry(function charAt( i, s ){ 44 | return s.charAt(i); 45 | }); 46 | 47 | //+ charCodeAt :: Int -> String -> Int 48 | Strings.charCodeAt = curry(function charCodeAt( i, s ){ 49 | return s.charCodeAt( i ); 50 | }); 51 | 52 | //+ concat :: String... -> String 53 | Strings.concat = curry(function concat(x) { 54 | return x.concat.apply("", arguments); 55 | }, 2); 56 | 57 | //+ indexOf :: a -> String -> Int 58 | Strings.indexOf = curry(function indexOf( value, a ){ 59 | return a.indexOf( value ); 60 | }); 61 | 62 | //+ indexOf_ :: a -> Int -> String -> Int 63 | Strings.indexOf_ = curry(function indexOf_( value, len, a ){ 64 | return a.indexOf( value, len ); 65 | }); 66 | 67 | //+ lastIndexOf :: a -> [a] -> Int 68 | Strings.lastIndexOf = curry(function lastIndexOf( value, a ){ 69 | return a.lastIndexOf( value ); 70 | }); 71 | 72 | //+ match :: Regexp|String -> String -> [String] 73 | Strings.match = curry(function match( regexp, s ){ 74 | return s.match( regexp ); 75 | }); 76 | 77 | //+ replace :: Regexp|String -> String -> String -> String 78 | Strings.replace = curry(function replace( a, b, s ){ 79 | return s.replace( a, b ); 80 | }); 81 | 82 | //+ search :: Regexp|String -> String -> Int 83 | Strings.search = curry(function search( regexp, s ){ 84 | return s.search( regexp ); 85 | }); 86 | 87 | //+ split :: String -> String -> [String] 88 | Strings.split = curry(function split( separator, s ){ 89 | return s.split( separator ); 90 | }); 91 | 92 | //+ split_ :: String -> Int -> String -> [String] 93 | Strings.split_ = curry(function split_( separator, len, s ){ 94 | return s.split( separator, len ); 95 | }); 96 | 97 | //+ substring :: Int -> String -> String 98 | Strings.substring = curry(function substring( start, s ){ 99 | return s.substring( start ); 100 | }); 101 | 102 | //+ substring_ :: Int -> Int -> String -> String 103 | Strings.substring_ = curry(function substring_( start, end, s ){ 104 | return s.substring( start, end ); 105 | }); 106 | 107 | //+ toLocaleLowerCase :: String -> String 108 | Strings.toLocaleLowerCase = function toLocaleLowerCase( s ){ 109 | return s.toLocaleLowerCase(); 110 | } 111 | 112 | //+ toLocaleUpperCase :: String -> String 113 | Strings.toLocaleUpperCase = function toLocaleUpperCase( s ){ 114 | return s.toLocaleUpperCase(); 115 | } 116 | 117 | //+ toLocaleString :: String -> String 118 | Strings.toLocaleString = function toLocaleString( a ){ 119 | return a.toLocaleString(); 120 | } 121 | 122 | //+ toLowerCase :: String -> String 123 | Strings.toLowerCase = function toLowerCase( s ){ 124 | return s.toLowerCase(); 125 | } 126 | 127 | //+ toUpperCase :: String -> String 128 | Strings.toUpperCase = function toUpperCase( s ){ 129 | return s.toUpperCase(); 130 | } 131 | 132 | //+ trim :: String -> String 133 | Strings.trim = function trim( s ){ 134 | return s.trim(); 135 | } 136 | 137 | 138 | // Arrays 139 | // ========================= 140 | 141 | //+ concat :: [a]... -> [a] 142 | Arrays.concat = curry(function concat(a) { 143 | return a.concat.apply([], arguments); 144 | }, 2); 145 | 146 | //+ every :: (a -> Boolean) -> [a] -> Boolean 147 | Arrays.every = curry(function every( fn, xs ) { 148 | return xs.every(fn); 149 | }); 150 | 151 | //+ filter :: (a -> Boolean) -> [a] -> [a] 152 | Arrays.filter = curry(function filter(fn, xs) { 153 | return xs.filter(fn); 154 | }); 155 | 156 | //+ forEach :: (a -> undefined) -> [a] -> [a] 157 | Arrays.forEach = curry(function forEach( fn, xs ) { 158 | xs.forEach(fn); 159 | return xs; 160 | }); 161 | 162 | //+ indexOf :: a -> [a] -> Int 163 | Arrays.indexOf = curry(function indexOf( value, a ){ 164 | return a.indexOf( value ); 165 | }); 166 | 167 | //+ indexOf_ :: a -> Int -> [a] -> Int 168 | Arrays.indexOf_ = curry(function indexOf_( value, len, a ){ 169 | return a.indexOf( value, len ); 170 | }); 171 | 172 | //+ join :: String -> [a] -> String 173 | Arrays.join = curry(function join( separator, arr ){ 174 | return arr.join( separator ); 175 | }); 176 | 177 | //+ lastIndexOf :: a -> [a] -> Int 178 | Arrays.lastIndexOf = curry(function lastIndexOf( value, a ){ 179 | return a.lastIndexOf( value ); 180 | }); 181 | 182 | //+ map :: (a -> b) -> [a] -> [b] 183 | Arrays.map = curry(function map(fn, xs) { 184 | return xs.map(fn); 185 | }); 186 | 187 | //+ pop :: [a] -> [a] 188 | Arrays.pop = function pop( a ){ 189 | return a.slice(0,-1); 190 | } 191 | 192 | //+ push :: a -> [a] -> [a] 193 | Arrays.push = curry(function push( value, a ){ 194 | // cloning the array 195 | var b = a.slice(0); 196 | b.push( value ); 197 | return b; 198 | }); 199 | 200 | //+ reduce :: (b -> a -> b) -> b -> [a] -> b 201 | Arrays.reduce = curry(function reduce(fn, acc, xs) { 202 | return xs.reduce(fn, acc); 203 | }); 204 | 205 | //+ reduceRight :: (b -> a -> b) -> b -> [a] -> b 206 | Arrays.reduceRight = curry(function reduceRight(fn, acc, xs) { 207 | return xs.reduceRight(fn, acc); 208 | }); 209 | 210 | //+ reverse :: [a] -> [a] 211 | Arrays.reverse = function reverse( a ){ 212 | return a.slice(0).reverse(); 213 | } 214 | 215 | //+ shift :: [a] -> [a] 216 | Arrays.shift = function shift( arr ){ 217 | return arr.slice(1); 218 | } 219 | 220 | //+ some :: (a -> Boolean) -> [a] -> Boolean 221 | Arrays.some = curry(function some( fn, xs ) { 222 | return xs.some(fn); 223 | }); 224 | 225 | //+ sort :: [a] -> [a] 226 | Arrays.sort = function sort( a ){ 227 | return a.slice(0).sort(); 228 | } 229 | 230 | //+ splice :: Int -> Int -> [a] -> [a] 231 | Arrays.splice = curry(function splice( index, count, a ){ 232 | var b = a.slice(0); 233 | b.splice( index, count ); 234 | return b; 235 | }); 236 | 237 | //+ unshift :: a -> [a] -> [a] 238 | Arrays.unshift = curry(function unshift( value, a ){ 239 | var b = a.slice(0); 240 | b.unshift( value ); 241 | return b; 242 | }); 243 | 244 | 245 | // REGEXPS 246 | // ========================= 247 | 248 | //+ exec :: Regexp -> String -> [String] 249 | Regexps.exec = curry(function exec( r, str ){ 250 | return r.exec( str ); 251 | }); 252 | 253 | //+ test :: Regexp -> String -> Boolean 254 | Regexps.test = curry(function test( r, str ){ 255 | return r.test( str ); 256 | }); 257 | 258 | 259 | 260 | // OBJECTS 261 | // ========================= 262 | 263 | //+ String -> {} -> Boolean 264 | Objects.hasOwnProperty = curry(function hasOwnProperty( prop, o ){ 265 | return o.hasOwnProperty( prop ); 266 | }); 267 | 268 | //+ isPrototypeOf :: {} -> Function -> Boolean 269 | Objects.isPrototypeOf = curry(function isPrototypeOf( a, b ){ 270 | return b.prototype.isPrototypeOf( a ); 271 | }); 272 | 273 | 274 | 275 | // NUMBERS 276 | // ========================= 277 | 278 | //+ toExponential :: Int -> Number -> String 279 | Numbers.toExponential = curry(function toExponential( fractionDigits, n ){ 280 | return n.toExponential( fractionDigits ); 281 | }); 282 | 283 | 284 | //+ toFixed :: Number -> Number -> String 285 | Numbers.toFixed = curry(function toFixed( digits, n ){ 286 | return n.toFixed( digits ); 287 | }) 288 | 289 | //+ toPrecision :: Number -> Number -> String 290 | Numbers.toPrecision = curry(function toPrecision( precision, n ){ 291 | return n.toPrecision( precision ); 292 | }); 293 | 294 | 295 | // LAMBDAJS 296 | // ========================= 297 | 298 | //+ concat :: [[a]] -> [a] 299 | LambdaJS.concat = curry(function concat(x) { 300 | var kind = (typeof x == "string") ? Strings : Arrays; // better way? 301 | return kind.concat.apply("", arguments); 302 | }, 2); 303 | 304 | //+ slice :: Int -> [a] 305 | LambdaJS.slice = curry(function slice( begin, a ){ 306 | console.log('lambda a', a, begin) 307 | return a.slice( begin ); 308 | }); 309 | 310 | //+ slice_ :: Int -> Int -> [a] 311 | LambdaJS.slice_ = curry(function slice_( begin, end, a ){ 312 | return a.slice( begin, end ); 313 | }); 314 | 315 | // //+ toString :: a -> String 316 | // LambdaJS.toString = function toString( s ){ 317 | // return s.toString(); 318 | // } 319 | 320 | // //+ valueOf :: a -> a 321 | // LambdaJS.valueOf = function valueOf( a ){ 322 | // return a.valueOf(); 323 | // } 324 | 325 | // EXPORTING 326 | // ======================== 327 | 328 | LambdaJS.expose = function(env, mod) { 329 | var win = getFreeGlobal(root); 330 | [Strings, Arrays, Regexps, Objects, Numbers, LambdaJS].map(function(mod){ 331 | exposeModuleToGlobal(win, mod); 332 | }); 333 | } 334 | 335 | function exposeModuleToGlobal(win, mod) { 336 | var f; 337 | for (f in mod) { 338 | if (f !== 'expose' && mod.hasOwnProperty(f)) { 339 | win[f] = mod[f]; 340 | } 341 | } 342 | } 343 | 344 | function getFreeGlobal(_window) { 345 | return (typeof global == "object") ? global : window; 346 | var env_global = _window 347 | , free_global = typeof env_global == 'object' && env_global; 348 | if (free_global.global === free_global) { 349 | return free_global; 350 | } 351 | return _window; 352 | } 353 | 354 | // Some AMD build optimizers, like r.js, check for specific condition patterns 355 | // like the following: 356 | if ( 357 | typeof define == 'function' && 358 | typeof define.amd == 'object' && 359 | define.amd 360 | ) { 361 | define(function() { 362 | return LambdaJS; 363 | }); 364 | } else if (freeExports && !freeExports.nodeType) { 365 | if (freeModule) { // in Node.js or RingoJS v0.8.0+ 366 | freeModule.exports = LambdaJS; 367 | } else { // in Narwhal or RingoJS v0.7.0- 368 | for (key in LambdaJS) { 369 | LambdaJS.hasOwnProperty(key) && (freeExports[key] = LambdaJS[key]); 370 | } 371 | } 372 | } else { // in Rhino or a web browser 373 | root.LambdaJS = LambdaJS; 374 | } 375 | }(this)); 376 | -------------------------------------------------------------------------------- /vendor/PreludeJS/prelude.js: -------------------------------------------------------------------------------- 1 | ;(function (window, undefined) { 2 | // Detect free variables "exports" and "global", and create 3 | // "prelude" namespace 4 | var freeExports = typeof exports == 'object' && exports, 5 | freeGlobal = typeof global == 'object' && global, 6 | functional = {}, 7 | prelude = {}, 8 | oldPrelude = {}; 9 | 10 | // Helpers 11 | //+ isArray :: a -> Boolean 12 | isArray = function(obj) { 13 | return (obj && obj.constructor == Array); 14 | } 15 | 16 | //+ isObj :: a -> Boolean 17 | isObj = function(obj) { 18 | return (typeof obj == "object" && !isArray(obj)); 19 | } 20 | 21 | //+ isNumber :: a -> Boolean 22 | isNumber = function(n) { 23 | return !isNaN(parseFloat(n)) && isFinite(n); 24 | }; 25 | 26 | //+ nTimes :: Integer -> (-> a) -> [a] 27 | nTimes = function(times, fun) { 28 | var result = []; 29 | for(var i=0;i a 34 | log = function(what) { 35 | console.log(what); 36 | return what; 37 | } 38 | 39 | //+ log2 :: String -> a -> a 40 | log2 = function(one, two) { 41 | log(one); 42 | return log(two); 43 | }.autoCurry(); 44 | 45 | 46 | 47 | // Array 48 | //+ take :: Integer -> [a] -> [a] 49 | take = function(n, xs) { 50 | return xs.slice(0, n); 51 | }.autoCurry(); 52 | 53 | //+ drop :: Integer -> [a] -> [a] 54 | drop = function(n, xs) { 55 | return xs.slice(n, xs.length); 56 | }.autoCurry(); 57 | 58 | //+ unshift :: [a] -> b -> [b,a] 59 | unshift = function(xs, x) { 60 | return x.concat(xs); 61 | }.autoCurry(); 62 | 63 | //+ push :: a -> [a] -> [a] 64 | push = function(x, xs) { 65 | var ys = xs.slice(0); 66 | ys.push(x); 67 | return ys; 68 | }.autoCurry(); 69 | 70 | //+ cons :: a -> [b] -> [a,b] 71 | cons = function(x, xs) { 72 | return [x].concat(xs); 73 | }.autoCurry(); 74 | 75 | //+ concat :: [a] -> [b] -> [a,b] 76 | concat = function(xs, ys) { 77 | return xs.concat(ys); 78 | }.autoCurry(); 79 | 80 | //+ first :: [a] -> a 81 | first = function(xs) { 82 | return xs[0]; 83 | }; 84 | 85 | //+ rest :: [a] -> [a] 86 | rest = function(xs) { 87 | return (typeof xs == "string") ? xs.substr(1, xs.length) : xs.slice(1, xs.length); 88 | }; 89 | 90 | //+ last :: [a] -> a 91 | last = function(xs) { 92 | return xs[xs.length -1]; 93 | }; 94 | 95 | //+ join :: String -> [String] -> String 96 | join = function(token, xs) { 97 | return xs.join(token); 98 | }.autoCurry(); 99 | 100 | //+ groupsOf :: Integer -> [a] -> [[a]] 101 | groupsOf = function(n, xs) { 102 | if(!xs.length) return []; 103 | return cons(take(n, xs), groupsOf(n, drop(n,xs))); 104 | }.autoCurry(); 105 | 106 | //+ zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] 107 | zipWith = function(f, xs, ys) { 108 | f = f.toFunction(); 109 | return xs.reduce(function(result, x, i){ 110 | return result.concat(f(x, ys[i])); 111 | }, []); 112 | }.autoCurry(); 113 | 114 | //+ uniq :: [a] -> [a] 115 | uniq = function(xs) { 116 | var result = []; 117 | for(var i=0;i b) -> [a] -> [a] 122 | uniqBy = function(fun, xs) { 123 | var result = [], len = xs.length, fun = fun.toFunction(); 124 | for(var i=0;i [a] 133 | reverse = function(xs) { 134 | var mempty = (typeof xs == "string") ? "" : []; 135 | if(isArray(xs)) { 136 | //destructive 137 | var ys = xs.slice(0); 138 | return ys.reverse(); 139 | } else { 140 | return reduce(function(x, acc){ return acc.concat(x); }, mempty, xs); 141 | } 142 | }.autoCurry(); 143 | 144 | //+ sort :: [a] -> [a] 145 | sort = function(xs) { 146 | //destructive 147 | is_num_array = reduce(andand, true, map(isNumber,xs)); 148 | num_sort_func = function(a,b) {return a - b;}; 149 | return is_num_array ? xs.sort(num_sort_func) : xs.sort(); 150 | } 151 | 152 | //+ element :: [a] -> b -> Boolean 153 | element = function(arr, x) { 154 | return arr.indexOf(x) >= 0; 155 | }.autoCurry(); 156 | 157 | //+ flatten :: [[a]] -> [a] 158 | flatten = reduce(function(a,b){return a.concat(b);}, []); 159 | 160 | //+ sortBy :: (a -> b) -> [a] -> [a] 161 | sortBy = function(fun, xs) { 162 | var _sortBy = function(iterator, xs, context) { 163 | return map('.value', map(function(value, index) { 164 | return { 165 | value: value, 166 | criteria: iterator.call(context, value, index) 167 | }; 168 | }, xs).sort(function(left, right) { 169 | var a = left.criteria, b = right.criteria; 170 | return a < b ? -1 : a > b ? 1 : 0; 171 | })); 172 | } 173 | var f = fun.toFunction(); 174 | return _sortBy(f, xs); 175 | }.autoCurry(); 176 | 177 | //+ groupBy :: (a -> Boolean) -> [a] -> {false: [a], true: [a]} 178 | groupBy = function(fun, xs) { 179 | var f = fun.toFunction(); 180 | var _makeHash = function(obj, x) { 181 | var val = f(x); 182 | if(!obj[val]) obj[val] = []; 183 | obj[val].push(x); 184 | return obj; 185 | } 186 | 187 | return reduce(_makeHash, {}, xs); 188 | }.autoCurry(); 189 | 190 | //+ detectBy :: (a -> b) -> b -> [a] -> a 191 | detectBy = function(findFn, val, xs) { 192 | var len = xs.length; 193 | for(i=0;i String 210 | strip = function(str) { 211 | return str.replace(/\s+/g, ""); 212 | } 213 | 214 | //+ split :: String -> String -> [String] 215 | split = function(token, xs) { 216 | return xs.split(token); 217 | }.autoCurry(); 218 | 219 | //+ test :: RegEx -> String -> Boolean 220 | test = function(expr, x) { 221 | return expr.test(x); 222 | }.autoCurry(); 223 | 224 | //+ match :: RegEx -> String -> [] 225 | match = function(expr, x) { 226 | return x.match(expr); 227 | }.autoCurry(); 228 | 229 | //+ replace :: RegEx -> String -> String -> String 230 | replace = function(pattern, sub, str) { 231 | return str.replace(pattern, sub); 232 | }.autoCurry(); 233 | 234 | //+ toLowerCase :: String -> String 235 | toLowerCase = function(str) { 236 | return str.toLowerCase(); 237 | } 238 | 239 | 240 | 241 | // Conditional 242 | //+ when :: Boolean -> (? -> a) -> a 243 | when = function(pred, f) { 244 | return function() { 245 | if(pred.apply(this, arguments)) return f.apply(this, arguments); 246 | } 247 | }.autoCurry(); 248 | 249 | //+ ifelse :: (-> Boolean) -> (-> a) -> (-> b) -> a|b 250 | ifelse = function(pred, f, g) { 251 | return function() { 252 | return pred.apply(this, arguments) ? f.apply(this, arguments) : g.apply(this, arguments); 253 | } 254 | }.autoCurry(); 255 | 256 | //+ negate :: Boolean -> Boolean 257 | negate = function(bool) { 258 | return !bool; 259 | } 260 | 261 | //+ andand :: a -> b -> Boolean 262 | andand = function(x, y) { 263 | return x && y; 264 | }.autoCurry(); 265 | 266 | //+ oror :: a -> b -> Boolean 267 | oror = function(x, y) { 268 | return x || y; 269 | }.autoCurry(); 270 | 271 | 272 | 273 | // Object 274 | //+ setVal :: String -> Object -> a -> a 275 | setVal = function(attribute, x, val) { 276 | x[attribute] = val; 277 | return val; 278 | }.autoCurry(); 279 | 280 | 281 | //+ setVals :: Object -> Object -> a 282 | setVals = function(obj1, obj2) { 283 | var target = {} 284 | for(k in obj1) { target[k] = obj1[k](obj2); } 285 | return target; 286 | }.autoCurry(); 287 | 288 | //+ getVal :: String -> Object -> a 289 | getVal = function(attribute, x) { 290 | return function(){ return x[attribute]; }; 291 | }.autoCurry(); 292 | 293 | //+ merge :: Object -> Object -> Object 294 | merge = function(x,y) { 295 | var target = {}; 296 | for(property in x) target[property] = x[property]; 297 | 298 | for(property in y) { 299 | if(isObj(y[property])) { 300 | merge(target[property], y[property]); 301 | } else { 302 | if(target && y) target[property] = y[property]; 303 | } 304 | } 305 | return target; 306 | }.autoCurry(); 307 | 308 | //+ unionWith :: (a -> b -> c) -> Object -> Object -> Object 309 | unionWith = function(f, x, y) { 310 | f = f.toFunction(); 311 | var target = {}; 312 | for(property in x){ if(x.hasOwnProperty(property)) target[property] = x[property]; } 313 | 314 | for(property in y) { 315 | if(y.hasOwnProperty(property)) { 316 | if(isObj(y[property].valueOf())) { 317 | unionWith(f, target[property], y[property]); 318 | } else { 319 | if(x[property]) { 320 | target[property] = f(x[property], y[property]); 321 | } else { 322 | target[property] = y[property]; 323 | } 324 | } 325 | } 326 | } 327 | return target; 328 | }.autoCurry(); 329 | 330 | 331 | range = function(start, end) { 332 | var values = []; 333 | for (var i = start; i <= end; i++){ values.push(i); } 334 | return values; 335 | } 336 | 337 | 338 | // Math 339 | //+ random :: Integer-> Integer 340 | random = function(i) { 341 | return Math.floor(Math.random()*i); 342 | } 343 | 344 | //+ subtract :: Number -> Number -> Number 345 | subtract = function(x,y){ 346 | return y - x; 347 | }.autoCurry(); 348 | 349 | //+ sum :: [Number] -> Number 350 | sum = reduce('+', 0); 351 | 352 | eq = function(x, y){ return x == y; }.autoCurry(); 353 | 354 | lt = function(x, y){ return x < y; }.autoCurry(); 355 | 356 | gt = function(x, y){ return x > y; }.autoCurry(); 357 | 358 | gte = function(x, y){ return x >= y; }.autoCurry(); 359 | 360 | lte = function(x, y){ return x <= y; }.autoCurry(); 361 | 362 | //+ div :: Number -> Number -> Number 363 | div = function(x,y){ return x / y; } 364 | 365 | //+ average :: [Number] -> Number 366 | average = function(xs) { 367 | var zerolessArr = filter('!==0', xs); 368 | return div(sum(zerolessArr), zerolessArr.length); 369 | } 370 | 371 | 372 | 373 | // Other 374 | //+ repeat :: a -> Integer -> [a] 375 | repeat = function(arg, n) { 376 | return nTimes(n, id.curry(arg)); 377 | }.autoCurry(); 378 | 379 | 380 | // Add functions to the "functional" namespace, 381 | // autoCurry() functions where appropriate 382 | //prelude.argsToList = argsToList; 383 | prelude.argsToList = function(x) { return Array.prototype.slice.call(x); }; 384 | prelude.isArray = isArray; 385 | prelude.isObj = isObj; 386 | 387 | // Detect free variable "global" and use it as "window" 388 | if (freeGlobal.global === freeGlobal) { 389 | window = freeGlobal; 390 | } 391 | 392 | // Used to restore the original reference in "noConflict()" 393 | oldPrelude = window.prelude; 394 | 395 | // Reverts the "functional" variable to its previous value and 396 | // returns a reference to the "functional" function. 397 | // example: 398 | // var functional = functional.noConflict(); 399 | prelude.noConflict = function noConflict() { 400 | window.prelude = oldPrelude; 401 | return this; 402 | } 403 | 404 | // Expose all functions to the global namespace, or specified environment 405 | prelude.expose = function expose(env) { 406 | var fn; 407 | env = env || window; 408 | for (fn in prelude) { 409 | if (fn !== 'expose' && prelude.hasOwnProperty(fn)) { 410 | env[fn] = prelude[fn]; 411 | } 412 | } 413 | }; 414 | prelude.expose(); 415 | 416 | // Expose FunctionalJS library 417 | // Some AMD build optimizers, like r.js, check for specific condition 418 | // patterns like the following: 419 | if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { 420 | // Expose FunctionalJs to the global object even when an AMD loader 421 | // is present, in case FunctionalJS was injected by a third-party 422 | // script and not intended to be loaded as module. The global 423 | // assignment can be reverted in the FunctionalJS module via its 424 | // "noConflict()" method. 425 | window.prelude = prelude; 426 | 427 | // Define an anonymous AMD module, require functional.js lib 428 | define(['FunctionalJS'], function (functional) { return prelude; }); 429 | } 430 | 431 | // Check for "exports" after "define", in case a build optimizer adds 432 | // an "exports" object. 433 | else if (freeExports) { 434 | // Require functional.js lib 435 | functional = require('../FunctionalJS/functional'); 436 | 437 | // Node.js or RingoJS v0.8.0+ 438 | if (typeof module == 'object' && module && module.exports == freeExports) { 439 | module.exports = prelude; 440 | } 441 | // Narwhal or RingoJS v0.7.0- 442 | else { 443 | freeExports.prelude = prelude; 444 | } 445 | } 446 | 447 | }(this)); 448 | -------------------------------------------------------------------------------- /vendor/typeclasses/amd/index.js: -------------------------------------------------------------------------------- 1 | define( 2 | 'util',["exports"], 3 | function(__exports__) { 4 | 5 | 6 | var Constructor = function(f) { 7 | var x = function(){ 8 | if(!(this instanceof x)){ 9 | var inst = new x(); 10 | f.apply(inst, arguments); 11 | return inst; 12 | } 13 | f.apply(this, arguments); 14 | }; 15 | 16 | return x; 17 | }; 18 | __exports__.Constructor = Constructor; 19 | var makeType = function(f) { 20 | f = f || function(v){ this.val = v; } 21 | return Constructor(f); 22 | }; 23 | __exports__.makeType = makeType; 24 | var toArray = function(x) { 25 | return Array.prototype.slice.call(x); 26 | } 27 | 28 | var curry = function (fn /* variadic number of args */) { 29 | var args = Array.prototype.slice.call(arguments, 1); 30 | var f = function () { 31 | return fn.apply(this, args.concat(toArray(arguments))); 32 | }; 33 | return f; 34 | }; 35 | 36 | var autoCurry = function (fn, numArgs) { 37 | numArgs = numArgs || fn.length; 38 | var f = function () { 39 | if (arguments.length < numArgs) { 40 | return numArgs - arguments.length > 0 ? 41 | autoCurry(curry.apply(this, [fn].concat(toArray(arguments))), 42 | numArgs - arguments.length) : 43 | curry.apply(this, [fn].concat(toArray(arguments))); 44 | } 45 | else { 46 | return fn.apply(this, arguments); 47 | } 48 | }; 49 | f.toString = function(){ return fn.toString(); }; 50 | f.curried = true; 51 | f.fn = fn; 52 | f.arity = fn.length; 53 | return f; 54 | }; 55 | __exports__.autoCurry = autoCurry; 56 | Function.prototype.autoCurry = function(n) { 57 | return autoCurry(this, n); 58 | } 59 | 60 | 61 | var K = function(x){return function(){return x;};}; 62 | __exports__.K = K;var I = function(x){return x;}; 63 | __exports__.I = I; 64 | }); 65 | define( 66 | 'types',["./util","exports"], 67 | function(__dependency1__, __exports__) { 68 | 69 | var makeType = __dependency1__.makeType; 70 | var autoCurry = __dependency1__.autoCurry;var Identity = makeType(); 71 | __exports__.Identity = Identity;var Maybe = makeType(); 72 | __exports__.Maybe = Maybe; 73 | }); 74 | define( 75 | 'functor',["./util","./types","exports"], 76 | function(__dependency1__, __dependency2__, __exports__) { 77 | 78 | var autoCurry = __dependency1__.autoCurry;var Identity = __dependency2__.Identity; 79 | var Maybe = __dependency2__.Maybe;var Functor = function(type, defs) { 80 | type.prototype.fmap = defs.fmap; 81 | }; 82 | __exports__.Functor = Functor; 83 | var fmap = function(f, obj) { 84 | return obj.fmap(f); 85 | }.autoCurry(); 86 | __exports__.fmap = fmap; 87 | // Some default instances: 88 | 89 | // Functor(Array, { 90 | // fmap: function(f){ 91 | // return this.map(function(x){ 92 | // return f(x); 93 | // }); 94 | // } // expand map function with lambda since map passes index in which messes with curried functions on applicatives 95 | // }); 96 | 97 | Functor(Function, { 98 | fmap: function(f){ return compose(f, this); } 99 | }); 100 | 101 | Functor(Identity, { 102 | fmap: function(f){ return Identity(f(this.val)); } 103 | }); 104 | 105 | Functor(Maybe, { 106 | fmap: function(f) { 107 | if(this.val == null) return this; 108 | return Maybe(f(this.val)); 109 | } 110 | }); 111 | }); 112 | define( 113 | 'applicative',["./util","./functor","exports"], 114 | function(__dependency1__, __dependency2__, __exports__) { 115 | 116 | var K = __dependency1__.K;var fmap = __dependency2__.fmap; 117 | 118 | var Applicative = function(type, defs) { 119 | type.prototype.pure = defs.pure; 120 | type.prototype.ap = defs.ap.autoCurry(); 121 | }; 122 | __exports__.Applicative = Applicative; 123 | var ap = function(a1, a2) { 124 | return a1.ap(a2); 125 | }.autoCurry(); 126 | __exports__.ap = ap; 127 | var pure = function(f) { 128 | f.ap = fmap(f); 129 | return f; 130 | }; 131 | __exports__.pure = pure; 132 | var liftA2 = function(f, a1, a2) { 133 | return pure(f).ap(a1).ap(a2); 134 | }.autoCurry(); 135 | __exports__.liftA2 = liftA2; 136 | var liftA3 = function(f, a1, a2, a3) { 137 | return pure(f).ap(a1).ap(a2).ap(a3); 138 | }.autoCurry(); 139 | __exports__.liftA3 = liftA3; 140 | Applicative(Function, { 141 | pure: K, 142 | ap: function(g) { 143 | var f = this; 144 | return function(x) { 145 | return f(x, g(x)); 146 | }; 147 | } 148 | }); 149 | 150 | Applicative(Array, { 151 | pure: Array, // needs to be infinite to be correct ziplist 152 | ap: function(a2) { 153 | // ziplist implementation 154 | return map(function(f,i){ return f(a2[i]); }, this); 155 | } 156 | }); 157 | }); 158 | define( 159 | 'monoid',["./util","exports"], 160 | function(__dependency1__, __exports__) { 161 | 162 | var K = __dependency1__.K; 163 | 164 | var mappend = function(x, y) { 165 | return x.mappend(x, y); 166 | }; 167 | __exports__.mappend = mappend; 168 | var mconcat = function() { 169 | var xs = Array.prototype.slice.call(arguments); 170 | if(xs.length == 1) xs = xs[0]; //skip having to call apply 171 | var f = xs[0].mappend; 172 | var e = xs[0].mempty(); 173 | return xs.reduce(f, e); 174 | }; 175 | __exports__.mconcat = mconcat; 176 | var Monoid = function(type, defs) { 177 | type.prototype.mempty = defs.mempty; 178 | type.prototype.mappend = defs.mappend.autoCurry(); 179 | }; 180 | __exports__.Monoid = Monoid; 181 | // Monoid(Object, { 182 | // mempty: function(){ return Object({}) }, 183 | // mappend: function(x,y){ 184 | // return Object(unionWith(mappend, x, y)); 185 | // } 186 | // }); 187 | 188 | Monoid(Number, { 189 | mempty: K(0), 190 | mappend: function(x,y) { return x + y; } 191 | }); 192 | 193 | // Monoid(Array, { 194 | // mempty: K([]), 195 | // mappend: function(x, y) { return x.concat(y); } 196 | // }); 197 | 198 | Monoid(String, { 199 | mempty: K(""), 200 | mappend: function(x,y) { return x + y; } 201 | }); 202 | 203 | Monoid(Boolean, { 204 | mempty: K(false), 205 | mappend: function(x,y){ return (x || y); } 206 | }); 207 | 208 | Monoid(Function, { 209 | mempty: K(K({mappend: function(f, g) { return mappend(g.mempty(), g);} })), 210 | mappend: function(f,g){ 211 | return function() { 212 | return mappend(f.apply(this, arguments), 213 | g.apply(this, arguments)); 214 | } 215 | } 216 | }); 217 | }); 218 | define( 219 | 'monad',["./util","./types","exports"], 220 | function(__dependency1__, __dependency2__, __exports__) { 221 | 222 | var Constructor = __dependency1__.Constructor; 223 | var Identity = __dependency2__.Identity; 224 | var Maybe = __dependency2__.Maybe; 225 | 226 | var Monad = function(type, defs) { 227 | var mbindViaJoin = function(f, mv) { 228 | return mjoin(mv.fmap(f)); 229 | }.autoCurry(); 230 | 231 | var joinViaMbind = function(mmv) { return mmv.mbind(id); } 232 | 233 | type.prototype.mresult = defs.mresult; 234 | type.prototype.mbind = (defs.mbind && defs.mbind.autoCurry()) || mbindViaJoin; 235 | type.prototype.mjoin = defs.mjoin || joinViaMbind; 236 | }; 237 | __exports__.Monad = Monad; 238 | var mjoin = function(mmv) { 239 | return mmv.mjoin(); 240 | }; 241 | __exports__.mjoin = mjoin; 242 | var mbind = function(mv, f) { 243 | f.mresult = mv.mresult; 244 | return mv.mbind(f, mv); 245 | }.autoCurry(); 246 | __exports__.mbind = mbind; 247 | var ap = function(mf, m) { 248 | return mbind(mf, function(f){ 249 | return mbind(m, function(x) { 250 | return m.mresult.call(this, f(x)); 251 | }) 252 | }) 253 | }.autoCurry(); 254 | __exports__.ap = ap; 255 | // takes variable args like compose does though. 256 | //+ _mcompose :: (b -> m c) -> (a -> m b) -> (a -> m c) 257 | // 258 | //BROKEN: compiled to ES5 strict mode, where assignment 259 | //to arguments is not allowed 260 | //export var mcompose = function(){ 261 | //var fns= map(Function.toFunction,arguments), 262 | //arglen=fns.length; 263 | //return function() { 264 | //var restlen = arglen-1; 265 | //arguments = [fns[arglen-1].apply(this, arguments)]; 266 | //for(var i=restlen;--i>=0;) { 267 | //console.log(arguments[0]); 268 | //arguments = [arguments[0].mbind(fns[i], arguments[0])]; 269 | //} 270 | //return arguments[0]; 271 | //} 272 | //}; 273 | 274 | 275 | // liftM2 and on, but needs to work with ap. 276 | var _liftApplicative = function(f) { 277 | return function() { 278 | var args = Array.prototype.slice.apply(arguments) 279 | , arg_length = args.length 280 | , result = args[0].mresult.call(this, f) 281 | , current_arg_idx = 0; 282 | 283 | while(current_arg_idx < arg_length) { 284 | result = ap(result, args[current_arg_idx]); 285 | current_arg_idx++; 286 | } 287 | 288 | return result; 289 | } 290 | }; 291 | 292 | var _liftFunctor = function(f) { 293 | return function(m) { 294 | return mbind(m, function(x){ 295 | return m.mresult.call(this, f(x)); 296 | }); 297 | } 298 | }; 299 | 300 | var liftM = function(f) { 301 | f = f.toFunction(); 302 | return f.curried ? _liftApplicative(f) : _liftFunctor(f); 303 | }; 304 | __exports__.liftM = liftM; 305 | 306 | // Built ins 307 | 308 | Monad(Identity, { 309 | mjoin: function() { 310 | return this.val; 311 | }, 312 | mresult: function(x){ return Identity(x); } 313 | }); 314 | 315 | // Monad(Array, { 316 | // mresult: Array, 317 | // mbind: function(f) { 318 | // return flatten(this.map(f)); 319 | // } 320 | // }); 321 | 322 | Monad(Maybe, { 323 | mjoin: function() { 324 | return this.val ? this.val : Maybe(undefined); 325 | }, 326 | mresult: function(x){ return Maybe(x); } 327 | }); 328 | 329 | //Monad(_Either, { 330 | //mjoin: function() { 331 | //return this.right ? this.right : this.left; 332 | //}, 333 | //mresult: function(x){ return Either(this.left, x); } 334 | //}); 335 | 336 | var State = Constructor(function(runState){ 337 | this.runState = runState; 338 | }); 339 | __exports__.State = State; 340 | Monad(State, { 341 | mresult: function(x){ 342 | return State(function(s){ return [x, s]}); 343 | }, 344 | mbind: function(f) { 345 | var that = this; 346 | return State(function(s){ 347 | var result = that.runState(s) 348 | , g = f(result[0]); 349 | return g.runState(result[1]); 350 | }); 351 | } 352 | }); 353 | }); 354 | define( 355 | 'typeclasses',["./util","./functor","./applicative","./monoid","./monad","exports"], 356 | function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __exports__) { 357 | 358 | var autoCurry = __dependency1__.autoCurry; 359 | 360 | var hasAC = Boolean(Function.prototype.autoCurry); 361 | 362 | if(!hasAC) { 363 | //the rest of the lib wants autoCurry on Function's prototype 364 | //this sucks, but I'll clean it up later 365 | Function.prototype.autoCurry = function(n) { 366 | return autoCurry(this, n); 367 | } 368 | }; 369 | 370 | var Functor = __dependency2__.Functor; 371 | var fmap = __dependency2__.fmap; 372 | var Applicative = __dependency3__.Applicative; 373 | var ap = __dependency3__.ap; 374 | var pure = __dependency3__.pure; 375 | var liftA2 = __dependency3__.liftA2; 376 | var liftA3 = __dependency3__.liftA3; 377 | var Monoid = __dependency4__.Monoid; 378 | var mappend = __dependency4__.mappend; 379 | var mconcat = __dependency4__.mconcat; 380 | var Monad = __dependency5__.Monad; 381 | var mjoin = __dependency5__.mjoin; 382 | var mbind = __dependency5__.mbind; 383 | var mcompose = __dependency5__.mcompose; 384 | var liftM = __dependency5__.liftM; 385 | var State = __dependency5__.State; 386 | 387 | if(!hasAC) { 388 | //remove autoCurry from function's prototype so that it 389 | //doesn't affect users 390 | //delete Function.prototype.autoCurry; 391 | }; 392 | 393 | __exports__.Functor = Functor; 394 | __exports__.fmap = fmap; 395 | __exports__.Applicative = Applicative; 396 | __exports__.ap = ap; 397 | __exports__.pure = pure; 398 | __exports__.liftA2 = liftA2; 399 | __exports__.liftA3 = liftA3; 400 | __exports__.Monoid = Monoid; 401 | __exports__.mappend = mappend; 402 | __exports__.mconcat = mconcat; 403 | __exports__.Monad = Monad; 404 | __exports__.mjoin = mjoin; 405 | __exports__.mbind = mbind; 406 | __exports__.mcompose = mcompose; 407 | __exports__.liftM = liftM; 408 | __exports__.State = State; 409 | }); 410 | -------------------------------------------------------------------------------- /support/lambdajs/docs/docs_files/github-btn.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Fork 0 -------------------------------------------------------------------------------- /vendor/PreludeJS/specs/prelude_spec.coffee: -------------------------------------------------------------------------------- 1 | functional = require('../../FunctionalJS/functional') 2 | functional.expose() 3 | 4 | prelude = require('../prelude') 5 | prelude.expose() 6 | 7 | describe('preludeJS', () -> 8 | it('loads and requires properly', -> 9 | expect(prelude).not.toBeUndefined() 10 | expect(typeof prelude.argsToList).toEqual('function') 11 | ) 12 | 13 | describe('expose', -> 14 | it('can attach functions to the global namespace', -> 15 | expect(typeof prelude.expose).toEqual('function') 16 | expect(typeof argsToList).toEqual('function') 17 | ) 18 | ) 19 | 20 | describe('helpers', () -> 21 | describe('isArray', ()-> 22 | it('tests for Array', ()-> 23 | expect(isArray([])).toBeTruthy() 24 | expect(isArray({})).toBeFalsy() 25 | ) 26 | ) 27 | 28 | describe('isObj', () -> 29 | it('tests for Object', () -> 30 | expect(isObj([])).toBeFalsy() 31 | expect(isObj({})).toBeTruthy() 32 | ) 33 | ) 34 | 35 | describe('isNumber', ()-> 36 | it('test for float or integer',()-> 37 | expect(isNumber(3)).toBeTruthy() 38 | expect(isNumber(-1)).toBeTruthy() 39 | expect(isNumber(0.42)).toBeTruthy() 40 | expect(isNumber(-0.42)).toBeTruthy() 41 | expect(isNumber(-1.42)).toBeTruthy() 42 | expect(isNumber(1.42)).toBeTruthy() 43 | expect(isNumber({})).toBeFalsy() 44 | expect(isNumber('a')).toBeFalsy() 45 | expect(isNumber([])).toBeFalsy() 46 | ) 47 | ) 48 | 49 | describe('nTimes', ()-> 50 | it('runs a function n times and returns output n times in list', ()-> 51 | returnHellos = () -> "hello" 52 | list = nTimes(3, returnHellos) 53 | expect(list).toEqual(['hello', 'hello', 'hello']) 54 | ) 55 | 56 | it('runs a function n times and returns output n times in list', ()-> 57 | obj = {prop: 2} 58 | returnObj = () -> obj 59 | list = nTimes(3, returnObj) 60 | expect(list).toEqual([obj,obj,obj]) 61 | ) 62 | 63 | it('returns undefined n times when value is not returned from function', ()-> 64 | expect(nTimes(2, (()->))).toEqual([undefined, undefined]) 65 | ) 66 | ) 67 | 68 | describe('log', ()-> 69 | it('logs the input to STDOUT and returns input as output', ()-> 70 | output = log('.') 71 | expect(output).toEqual('.') 72 | ) 73 | ) 74 | 75 | describe('log2', ()-> 76 | it('logs a message and input, returns input as output', ()-> 77 | output = log2('.', '.') 78 | expect(output).toEqual('.') 79 | ) 80 | ) 81 | ) 82 | 83 | describe('Array', ()-> 84 | describe('take', ()-> 85 | it('takes a number of elements from an array', ()-> 86 | three_elems = take(3, [1,2,3,4]) 87 | expect(three_elems).toEqual([1,2,3]) 88 | ) 89 | 90 | it('takes only amount of elements it can from array', ()-> 91 | all = take(5, [1,2]) 92 | expect(all).toEqual([1,2]) 93 | none = take(5, []) 94 | expect(none).toEqual([]) 95 | ) 96 | ) 97 | 98 | describe('drop', ()-> 99 | it('drops a number of elements from an array', ()-> 100 | three_elems = drop(2, [1,2,3,4,5]) 101 | expect(three_elems).toEqual([3,4,5]) 102 | ) 103 | 104 | it('drops only amount of elements it can from array', ()-> 105 | all = drop(5, [1,2]) 106 | expect(all).toEqual([]) 107 | none = drop(0, [1,2]) 108 | expect(none).toEqual([1,2]) 109 | ) 110 | ) 111 | 112 | describe('unshift', ()-> 113 | it('adds second arg to end of an array', ()-> 114 | expect(unshift(['x'],[2])).toEqual([2,'x']) 115 | ) 116 | 117 | it('flattens array', ()-> 118 | expect(unshift(['x'],[2])).not.toEqual([2,['x']]) 119 | ) 120 | ) 121 | 122 | describe('cons', ()-> 123 | it('adds an elem to the beginning of array', ()-> 124 | expect(cons([1],[2])).toEqual([[1], 2]) 125 | ) 126 | 127 | it('doesnt flatten array', ()-> 128 | expect(cons([1],[2])).not.toEqual([[1], [2]]) 129 | ) 130 | ) 131 | 132 | describe('concat', ()-> 133 | it('adds second arg to end of an array', ()-> 134 | expect(concat([2], 'x')).toEqual([2, 'x']) 135 | ) 136 | 137 | it('flattens array', ()-> 138 | expect(concat(['x'],[2])).toEqual(['x',2]) 139 | ) 140 | ) 141 | 142 | describe('first', ()-> 143 | it('returns first elem of an array', ()-> 144 | expect(first([2, 'x', 3])).toEqual(2) 145 | ) 146 | 147 | it('returns undefined if array is empty', ()-> 148 | expect(first([])).toBeUndefined() 149 | ) 150 | ) 151 | 152 | describe('rest', ()-> 153 | it('drops the first element of the array and returns the rest of array', ()-> 154 | expect(rest([1,2,3])).toEqual([2,3]) 155 | ) 156 | 157 | it('returns an empty array if supplied with empty array', ()-> 158 | expect(rest([])).toEqual([]) 159 | ) 160 | ) 161 | 162 | describe('last', ()-> 163 | it('returns last elem of an array', ()-> 164 | expect(last([2, 'x', 3])).toEqual(3) 165 | ) 166 | 167 | it('returns undefined if array is empty', ()-> 168 | expect(last([])).toBeUndefined() 169 | ) 170 | ) 171 | 172 | describe('join', ()-> 173 | it('joins elems of an array with token supplied', ()-> 174 | expect(join('-', ['h', 'e', 'l', 'l', 'o'])).toEqual('h-e-l-l-o') 175 | ) 176 | 177 | it('only joins array elements of type String', ()-> 178 | expect(join('-', [{}, []])).not.toEqual('{}-[]') 179 | ) 180 | ) 181 | 182 | describe('groupsOf', ()-> 183 | it('takes number and array and returns a new array with arrays of elements with length of number supplied for each inner array', ()-> 184 | expect(groupsOf(3, [1,2,3,4,5,6])).toEqual([[1,2,3],[4,5,6]]) 185 | expect(groupsOf(4, [1,2,3,4,5,6])).toEqual([[1,2,3,4],[5,6]]) 186 | ) 187 | 188 | it('takes only as much as it can from array', ()-> 189 | expect(groupsOf(4, [1,2,3])).toEqual([[1,2,3]]) 190 | ) 191 | 192 | it('returns empty array if supplied empty array', ()-> 193 | expect(groupsOf(4, [])).toEqual([]) 194 | ) 195 | ) 196 | 197 | describe('zipWith', ()-> 198 | it('zips two lists with supplied function', ()-> 199 | zip_func = '+' 200 | xs = [1,2,3] 201 | ys = [1,2,3] 202 | expect(zipWith(zip_func, xs, ys)).toEqual([2,4,6]) 203 | ) 204 | ) 205 | 206 | describe('uniq', ()-> 207 | it('returns only unique values in array', ()-> 208 | expect(uniq([1,2,2,3,3,3])).toEqual([1,2,3]) 209 | expect(uniq([1,1])).not.toEqual([1,1]) 210 | ) 211 | 212 | it('returns an empty array if supplied with empty array', ()-> 213 | expect(uniq([])).toEqual([]) 214 | ) 215 | ) 216 | 217 | describe('uniqBy', ()-> 218 | it('takes a function to check array for function return value and returns unique array', ()-> 219 | expect(uniqBy('.id', [{id: 1},{id: 2},{id: 1}])).toEqual([{id:1},{id:2}]) 220 | ) 221 | ) 222 | 223 | describe('reverse', ()-> 224 | it('reverses a string or an array of strings to a string', ()-> 225 | expect(reverse('linux')).toEqual('xunil') 226 | expect(reverse(['l','i','n','u','x'])).toEqual(['x','u','n','i','l']) 227 | ) 228 | 229 | it('reverses an array of non strings to an array', ()-> 230 | expect(reverse([1,2,3])).toEqual([3,2,1]) 231 | expect(reverse([1,2,{}])).toEqual([{},2,1]) 232 | ) 233 | ) 234 | 235 | describe('sort', ()-> 236 | it('sorts an array of homogenous values', ()-> 237 | expect(sort([1,78,2])).toEqual([1,2,78]) 238 | expect(sort(['c','z','a'])).toEqual(['a','c','z']) 239 | ) 240 | 241 | it('sorts numbers ascending', ()-> 242 | expect(sort([1,100,2,78])).toEqual([1,2,78,100]) 243 | ) 244 | 245 | it('doesnt sort heterogenous values, must be equatable constraint', ()-> 246 | expect(sort([1,100,'a'])).not.toEqual(['a',1,100]) 247 | expect(sort([1,100,'a'])).not.toEqual([1,'a',100]) 248 | ) 249 | ) 250 | 251 | describe('element', ()-> 252 | it('test if an element is present in array', ()-> 253 | expect(element([1,2,3], 1)).toBeTruthy() 254 | expect(element([1,'b',3], 'b')).toBeTruthy() 255 | expect(element([1,2,3], 5)).toBeFalsy() 256 | ) 257 | ) 258 | 259 | describe('flatten', ()-> 260 | it('flattens single level deep nested arrays into a single array', ()-> 261 | single_nested_arrays = [[2,3],[1],[5]] 262 | expect(flatten(single_nested_arrays)).toEqual([2,3,1,5]) 263 | double_nested_arrays = [1,[2],[[3]]] 264 | expect(flatten(double_nested_arrays)).toEqual([1,2,[3]]) 265 | ) 266 | ) 267 | 268 | describe('sortBy', ()-> 269 | it('sorts by property', ()-> 270 | obj1= {name: 'alice'} 271 | obj2 = {name: 'bob'} 272 | expect(sortBy('.name', [obj2,obj1])).toEqual([obj1,obj2]) 273 | ) 274 | ) 275 | 276 | describe('groupBy', ()-> 277 | it('groups elems in array by predicate function and returns hash with keys true and false', ()-> 278 | expect(groupBy('>4', [1,2,3,4,5,6,7,8])).toEqual({false: [1,2,3,4], true: [5,6,7,8]}) 279 | ) 280 | ) 281 | ) 282 | 283 | describe('String', ()-> 284 | describe('strip', ()-> 285 | it('relaces all whitespace with empty string', ()-> 286 | str = ' a g ba df ' 287 | expect(strip(str)).toEqual('agbadf') 288 | ) 289 | ) 290 | 291 | describe('split', ()-> 292 | it('splits a string based on token supplied and returns array', ()-> 293 | str = 'h-e-l-l-o' 294 | expect(split('-', str)).toEqual(['h','e','l','l','o']) 295 | expect(split('a', str)).toEqual([str]) 296 | ) 297 | ) 298 | 299 | describe('test', ()-> 300 | it('tests to see if a regex matches in the string and returns predicate', ()-> 301 | str = 'hello world' 302 | expect(test(/h/, str)).toBeTruthy() 303 | expect(test(/a/, str)).toBeFalsy() 304 | ) 305 | ) 306 | 307 | describe('match', ()-> 308 | it('test if a regex matches the string and returns match array', ()-> 309 | str = 'hello world' 310 | expect(match(/h/, str)[0]).toEqual('h') 311 | ) 312 | ) 313 | 314 | describe('replace', ()-> 315 | it('replaces patterns in the string with substitution supplied', ()-> 316 | str = 'hello world' 317 | expect(replace(/hello/,'goodbye', str)).toEqual('goodbye world') 318 | expect(replace(/l/,'x', str)).toEqual('hexlo world') 319 | expect(replace(/l/g,'x', str)).toEqual('hexxo worxd') 320 | ) 321 | ) 322 | ) 323 | 324 | describe('Conditional', ()-> 325 | describe('when', ()-> 326 | xit('takes a predicate function and other function, when predicate function returns true it applies other function to args', ()-> 327 | #TODO: when function conflicts with coffeescript when keyword, wont run spec 328 | #true_func = () -> true 329 | #false_func = () -> false 330 | #my_func = () -> 'lamp' 331 | #output = when(true_func, my_func)() 332 | #expect(output).toEqual('lamp') 333 | #output = when(false_func, my_func)() 334 | #expect(output).toBeUndefined() 335 | ) 336 | ) 337 | 338 | describe('ifelse', ()-> 339 | it('takes a function, returns true, runs first function', ()-> 340 | true_func = ()-> true 341 | func_called_output = ifelse(true_func, (()-> 'im the true path'), id)() 342 | expect(func_called_output).toEqual('im the true path') 343 | ) 344 | 345 | it('takes a function, returns false, runs second function', ()-> 346 | false_func = ()-> false 347 | func_called_output = ifelse(false_func, id,(()-> 'im the false path'))() 348 | expect(func_called_output).toEqual('im the false path') 349 | ) 350 | ) 351 | 352 | describe('negate', ()-> 353 | it('turns true to false', ()-> 354 | expect(negate(false)).toBeTruthy() 355 | ) 356 | 357 | it('turns false to true', ()-> 358 | expect(negate(true)).toBeFalsy() 359 | ) 360 | ) 361 | 362 | describe('andand', ()-> 363 | it('returns true if both args are true', ()-> 364 | expect(andand(true, true)).toBeTruthy() 365 | expect(andand(true, 'a')).toBeTruthy() 366 | ) 367 | 368 | it('returns false if first arg is false', ()-> 369 | expect(andand(false, true)).toBeFalsy() 370 | expect(andand(0, true)).toBeFalsy() 371 | expect(andand(null, true)).toBeFalsy() 372 | expect(andand(undefined, true)).toBeFalsy() 373 | expect(andand('', true)).toBeFalsy() 374 | ) 375 | 376 | it('returns false if second arg is false', ()-> 377 | expect(andand(true, false)).toBeFalsy() 378 | expect(andand(true, 0)).toBeFalsy() 379 | expect(andand(true, null)).toBeFalsy() 380 | expect(andand(true, undefined)).toBeFalsy() 381 | expect(andand(true, '')).toBeFalsy() 382 | ) 383 | ) 384 | 385 | describe('oror', ()-> 386 | it('returns true if first arg is true', ()-> 387 | expect(oror(true, false)).toBeTruthy() 388 | ) 389 | 390 | it('returns true if second arg is true', ()-> 391 | expect(oror(false, true)).toBeTruthy() 392 | expect(oror(0, true)).toBeTruthy() 393 | expect(oror(null, true)).toBeTruthy() 394 | expect(oror(undefined, true)).toBeTruthy() 395 | expect(oror('', true)).toBeTruthy() 396 | ) 397 | 398 | it('returns false if both args are false', ()-> 399 | expect(oror(false, false)).toBeFalsy() 400 | ) 401 | ) 402 | ) 403 | 404 | describe('Object', ()-> 405 | describe('setVal', ()-> 406 | it('sets a value on an object', ()-> 407 | obj = {} 408 | setVal('prop', obj, 'set') 409 | expect(obj.prop).toEqual('set') 410 | ) 411 | 412 | it('returns the value that was set', ()-> 413 | obj = {} 414 | return_val = setVal('prop', obj, 'set') 415 | expect(return_val).toEqual('set') 416 | ) 417 | ) 418 | 419 | describe('getVal', ()-> 420 | it('returns a function that returns the value of some property on an object', ()-> 421 | obj = {prop: 'set'} 422 | get_val_func = getVal('prop', obj) 423 | expect(get_val_func()).toEqual('set') 424 | ) 425 | ) 426 | 427 | describe('merge', ()-> 428 | it('merges one object into another and returns new obj', ()-> 429 | obj1 = {arr: [1], num: 2} 430 | obj2 = {} 431 | new_obj = merge(obj1, obj2) 432 | expect(new_obj.arr).toEqual([1]) 433 | expect(new_obj.num).toEqual(2) 434 | ) 435 | 436 | it('deep merges object', ()-> 437 | obj1 = {a_obj: {num: 9}} 438 | obj2 = {} 439 | new_obj = merge(obj1, obj2) 440 | expect(new_obj.a_obj.num).toEqual(9) 441 | ) 442 | 443 | it('merges functions', ()-> 444 | obj1 = {a_func: () -> 7} 445 | obj2 = {} 446 | new_obj = merge(obj1, obj2) 447 | expect(new_obj.a_func()).toEqual(7) 448 | ) 449 | ) 450 | 451 | describe('unionWith', ()-> 452 | it('adds to values from keys of objects', ()-> 453 | obj1 = {first_name:'Bob', last_name:'Barker'} 454 | obj2 = {first_name:'Happy', last_name:'Gilmore'} 455 | expect(unionWith('+',obj1,obj2)).toEqual({first_name:'BobHappy', last_name:'BarkerGilmore'}) 456 | ) 457 | ) 458 | ) 459 | 460 | describe('Math', ()-> 461 | describe('random', ()-> 462 | it('returns a random value from 0 to n', ()-> 463 | expect(random(5)).toBeLessThan(6) 464 | expect(random(5)).toBeGreaterThan(-1) 465 | expect(random(-5)).toBeLessThan(1) 466 | expect(random(-5)).toBeGreaterThan(-6) 467 | ) 468 | ) 469 | 470 | describe('subtract', ()-> 471 | it('subtracts two scalar values', ()-> 472 | expect(subtract(3, 5)).toEqual(2) 473 | expect(subtract(5, 3)).toEqual(-2) 474 | expect(subtract(3.2, 4.2)).toEqual(1) 475 | ) 476 | ) 477 | 478 | describe('sum', ()-> 479 | it('sums an array of values', ()-> 480 | expect(sum([1,2,3,4,5,6,7,8,9])).toEqual(45) 481 | expect(sum([1,2.2,3,4,5,6,7,8,9])).toEqual(45.2) 482 | ) 483 | ) 484 | 485 | describe('div', ()-> 486 | it('divides to scalar values', ()-> 487 | expect(div(10,5)).toEqual(2) 488 | expect(div(2,10)).toEqual(div(1,5)) 489 | ) 490 | ) 491 | 492 | describe('average', ()-> 493 | it('averages an array of values and returns a float', ()-> 494 | expect(average([4,8])).toEqual(6.0) 495 | expect(average([0,4,8])).toEqual(6.0) 496 | 497 | ) 498 | ) 499 | 500 | describe('Other', ()-> 501 | describe('repeat', ()-> 502 | it('repeats the argument n times and returns array of length n', ()-> 503 | expect(repeat(4, 3)).toEqual([4,4,4]) 504 | expect(repeat('a', 3)).toEqual(['a', 'a', 'a']) 505 | expect(repeat([1], 3)).toEqual([[1], [1], [1]]) 506 | expect(repeat({a:1}, 3)).toEqual([{a:1},{a:1},{a:1}]) 507 | ) 508 | ) 509 | ) 510 | ) 511 | ) 512 | -------------------------------------------------------------------------------- /support/node-promise/promise.js: -------------------------------------------------------------------------------- 1 | 2 | // Kris Zyp 3 | // Updates/added features by ...Max... (Max Motovilov) 4 | 5 | // this is based on the CommonJS spec for promises: 6 | // http://wiki.commonjs.org/wiki/Promises 7 | // Includes convenience functions for promises, much of this is taken from Tyler Close's ref_send 8 | // and Kris Kowal's work on promises. 9 | // // MIT License 10 | 11 | // A typical usage: 12 | // A default Promise constructor can be used to create a self-resolving deferred/promise: 13 | // var Promise = require("promise").Promise; 14 | // var promise = new Promise(); 15 | // asyncOperation(function(){ 16 | // Promise.resolve("succesful result"); 17 | // }); 18 | // promise -> given to the consumer 19 | // 20 | // A consumer can use the promise 21 | // promise.then(function(result){ 22 | // ... when the action is complete this is executed ... 23 | // }, 24 | // function(error){ 25 | // ... executed when the promise fails 26 | // }); 27 | // 28 | // Alternately, a provider can create a deferred and resolve it when it completes an action. 29 | // The deferred object a promise object that provides a separation of consumer and producer to protect 30 | // promises from being fulfilled by untrusted code. 31 | // var defer = require("promise").defer; 32 | // var deferred = defer(); 33 | // asyncOperation(function(){ 34 | // deferred.resolve("succesful result"); 35 | // }); 36 | // deferred.promise -> given to the consumer 37 | // 38 | // Another way that a consumer can use the promise (using promise.then is also allowed) 39 | // var when = require("promise").when; 40 | // when(promise,function(result){ 41 | // ... when the action is complete this is executed ... 42 | // }, 43 | // function(error){ 44 | // ... executed when the promise fails 45 | // }); 46 | try{ 47 | var enqueue = require("event-queue").enqueue; 48 | } 49 | catch(e){ 50 | // squelch the error, and only complain if the queue is needed 51 | } 52 | if(!enqueue){ 53 | enqueue = (typeof process !== "undefined" && process.nextTick) || function(func){ 54 | func(); 55 | } 56 | } 57 | // commented out due to: http://code.google.com/p/v8/issues/detail?id=851 58 | var freeze = /*Object.freeze || */function(){}; 59 | 60 | /** 61 | * Default constructor that creates a self-resolving Promise. Not all promise implementations 62 | * need to use this constructor. 63 | */ 64 | var Promise = function(canceller){ 65 | }; 66 | 67 | /** 68 | * Promise implementations must provide a "then" function. 69 | */ 70 | Promise.prototype.then = function(resolvedCallback, errorCallback, progressCallback){ 71 | throw new TypeError("The Promise base class is abstract, this function must be implemented by the Promise implementation"); 72 | }; 73 | 74 | /** 75 | * If an implementation of a promise supports a concurrency model that allows 76 | * execution to block until the promise is resolved, the wait function may be 77 | * added. 78 | */ 79 | /** 80 | * If an implementation of a promise can be cancelled, it may add this function 81 | */ 82 | // Promise.prototype.cancel = function(){ 83 | // }; 84 | 85 | Promise.prototype.get = function(propertyName){ 86 | return this.then(function(value){ 87 | return value[propertyName]; 88 | }); 89 | }; 90 | 91 | Promise.prototype.put = function(propertyName, value){ 92 | return this.then(function(object){ 93 | return object[propertyName] = value; 94 | }); 95 | }; 96 | 97 | Promise.prototype.call = function(functionName /*, args */){ 98 | return this.then(function(value){ 99 | return value[functionName].apply(value, Array.prototype.slice.call(arguments, 1)); 100 | }); 101 | }; 102 | 103 | /** Dojo/NodeJS methods*/ 104 | Promise.prototype.addCallback = function(callback){ 105 | return this.then(callback); 106 | }; 107 | 108 | Promise.prototype.addErrback = function(errback){ 109 | return this.then(function(){}, errback); 110 | }; 111 | 112 | /*Dojo methods*/ 113 | Promise.prototype.addBoth = function(callback){ 114 | return this.then(callback, callback); 115 | }; 116 | 117 | Promise.prototype.addCallbacks = function(callback, errback){ 118 | return this.then(callback, errback); 119 | }; 120 | 121 | /*NodeJS method*/ 122 | Promise.prototype.wait = function(){ 123 | return exports.wait(this); 124 | }; 125 | 126 | Deferred.prototype = Promise.prototype; 127 | // A deferred provides an API for creating and resolving a promise. 128 | exports.Promise = exports.Deferred = exports.defer = defer; 129 | function defer(){ 130 | return new Deferred(); 131 | } 132 | 133 | var contextHandler = exports.contextHandler = {}; 134 | 135 | function Deferred(canceller){ 136 | var result, finished, isError, waiting = [], handled; 137 | var promise = this.promise = new Promise(); 138 | var currentContextHandler = contextHandler.getHandler && contextHandler.getHandler(); 139 | 140 | function notifyAll(value){ 141 | if(finished){ 142 | throw new Error("This deferred has already been resolved"); 143 | } 144 | result = value; 145 | finished = true; 146 | for(var i = 0; i < waiting.length; i++){ 147 | notify(waiting[i]); 148 | } 149 | } 150 | function notify(listener){ 151 | var func = (isError ? listener.error : listener.resolved); 152 | if(func){ 153 | handled = true; 154 | enqueue(function(){ 155 | if(currentContextHandler){ 156 | currentContextHandler.resume(); 157 | } 158 | try{ 159 | var newResult = func(result); 160 | if(newResult && typeof newResult.then === "function"){ 161 | newResult.then(listener.deferred.resolve, listener.deferred.reject); 162 | return; 163 | } 164 | listener.deferred.resolve(newResult); 165 | } 166 | catch(e){ 167 | listener.deferred.reject(e); 168 | } 169 | finally{ 170 | if(currentContextHandler){ 171 | currentContextHandler.suspend(); 172 | } 173 | } 174 | }); 175 | } 176 | else{ 177 | if(isError){ 178 | if (listener.deferred.reject(result, true)) { 179 | handled = true; 180 | } 181 | } 182 | else{ 183 | listener.deferred.resolve.apply(listener.deferred, result); 184 | } 185 | } 186 | } 187 | // calling resolve will resolve the promise 188 | this.resolve = this.callback = this.emitSuccess = function(value){ 189 | notifyAll(value); 190 | }; 191 | 192 | // calling error will indicate that the promise failed 193 | var reject = this.reject = this.errback = this.emitError = function(error, dontThrow){ 194 | isError = true; 195 | notifyAll(error); 196 | if (!dontThrow) { 197 | enqueue(function () { 198 | if (!handled) { 199 | throw error; 200 | } 201 | }); 202 | } 203 | return handled; 204 | }; 205 | 206 | // call progress to provide updates on the progress on the completion of the promise 207 | this.progress = function(update){ 208 | for(var i = 0; i < waiting.length; i++){ 209 | var progress = waiting[i].progress; 210 | progress && progress(update); 211 | } 212 | } 213 | // provide the implementation of the promise 214 | this.then = promise.then = function(resolvedCallback, errorCallback, progressCallback){ 215 | var returnDeferred = new Deferred(promise.cancel); 216 | var listener = {resolved: resolvedCallback, error: errorCallback, progress: progressCallback, deferred: returnDeferred}; 217 | if(finished){ 218 | notify(listener); 219 | } 220 | else{ 221 | waiting.push(listener); 222 | } 223 | return returnDeferred.promise; 224 | }; 225 | var timeout; 226 | if(typeof setTimeout !== "undefined") { 227 | this.timeout = function (ms) { 228 | if (ms === undefined) { 229 | return timeout; 230 | } 231 | timeout = ms; 232 | setTimeout(function () { 233 | if (!finished) { 234 | if (promise.cancel) { 235 | promise.cancel(new Error("timeout")); 236 | } 237 | else { 238 | reject(new Error("timeout")); 239 | } 240 | } 241 | }, ms); 242 | return promise; 243 | }; 244 | } 245 | 246 | if(canceller){ 247 | this.cancel = promise.cancel = function(){ 248 | var error = canceller(); 249 | if(!(error instanceof Error)){ 250 | error = new Error(error); 251 | } 252 | reject(error); 253 | } 254 | } 255 | freeze(promise); 256 | }; 257 | 258 | function perform(value, async, sync){ 259 | try{ 260 | if(value && typeof value.then === "function"){ 261 | value = async(value); 262 | } 263 | else{ 264 | value = sync(value); 265 | } 266 | if(value && typeof value.then === "function"){ 267 | return value; 268 | } 269 | var deferred = new Deferred(); 270 | deferred.resolve(value); 271 | return deferred.promise; 272 | }catch(e){ 273 | var deferred = new Deferred(); 274 | deferred.reject(e); 275 | return deferred.promise; 276 | } 277 | 278 | } 279 | /** 280 | * Promise manager to make it easier to consume promises 281 | */ 282 | 283 | /** 284 | * Registers an observer on a promise. 285 | * @param value promise or value to observe 286 | * @param resolvedCallback function to be called with the resolved value 287 | * @param rejectCallback function to be called with the rejection reason 288 | * @param progressCallback function to be called when progress is made 289 | * @return promise for the return value from the invoked callback 290 | */ 291 | exports.whenPromise = function(value, resolvedCallback, rejectCallback, progressCallback){ 292 | return perform(value, function(value){ 293 | return value.then(resolvedCallback, rejectCallback, progressCallback); 294 | }, 295 | function(value){ 296 | return resolvedCallback(value); 297 | }); 298 | }; 299 | /** 300 | * Registers an observer on a promise. 301 | * @param value promise or value to observe 302 | * @param resolvedCallback function to be called with the resolved value 303 | * @param rejectCallback function to be called with the rejection reason 304 | * @param progressCallback function to be called when progress is made 305 | * @return promise for the return value from the invoked callback or the value if it 306 | * is a non-promise value 307 | */ 308 | exports.when = function(value, resolvedCallback, rejectCallback, progressCallback){ 309 | if(value && typeof value.then === "function"){ 310 | return exports.whenPromise(value, resolvedCallback, rejectCallback, progressCallback); 311 | } 312 | return resolvedCallback(value); 313 | }; 314 | 315 | /** 316 | * Gets the value of a property in a future turn. 317 | * @param target promise or value for target object 318 | * @param property name of property to get 319 | * @return promise for the property value 320 | */ 321 | exports.get = function(target, property){ 322 | return perform(target, function(target){ 323 | return target.get(property); 324 | }, 325 | function(target){ 326 | return target[property] 327 | }); 328 | }; 329 | 330 | /** 331 | * Invokes a method in a future turn. 332 | * @param target promise or value for target object 333 | * @param methodName name of method to invoke 334 | * @param args array of invocation arguments 335 | * @return promise for the return value 336 | */ 337 | exports.post = function(target, methodName, args){ 338 | return perform(target, function(target){ 339 | return target.call(property, args); 340 | }, 341 | function(target){ 342 | return target[methodName].apply(target, args); 343 | }); 344 | }; 345 | 346 | /** 347 | * Sets the value of a property in a future turn. 348 | * @param target promise or value for target object 349 | * @param property name of property to set 350 | * @param value new value of property 351 | * @return promise for the return value 352 | */ 353 | exports.put = function(target, property, value){ 354 | return perform(target, function(target){ 355 | return target.put(property, value); 356 | }, 357 | function(target){ 358 | return target[property] = value; 359 | }); 360 | }; 361 | 362 | 363 | /** 364 | * Waits for the given promise to finish, blocking (and executing other events) 365 | * if necessary to wait for the promise to finish. If target is not a promise 366 | * it will return the target immediately. If the promise results in an reject, 367 | * that reject will be thrown. 368 | * @param target promise or value to wait for. 369 | * @return the value of the promise; 370 | */ 371 | exports.wait = function(target){ 372 | if(!queue){ 373 | throw new Error("Can not wait, the event-queue module is not available"); 374 | } 375 | if(target && typeof target.then === "function"){ 376 | var isFinished, isError, result; 377 | target.then(function(value){ 378 | isFinished = true; 379 | result = value; 380 | }, 381 | function(error){ 382 | isFinished = true; 383 | isError = true; 384 | result = error; 385 | }); 386 | while(!isFinished){ 387 | queue.processNextEvent(true); 388 | } 389 | if(isError){ 390 | throw result; 391 | } 392 | return result; 393 | } 394 | else{ 395 | return target; 396 | } 397 | }; 398 | 399 | 400 | 401 | /** 402 | * Takes an array of promises and returns a promise that is fulfilled once all 403 | * the promises in the array are fulfilled 404 | * @param array The array of promises 405 | * @return the promise that is fulfilled when all the array is fulfilled, resolved to the array of results 406 | */ 407 | 408 | function composeAll(fail_on_error) { 409 | return function(array) { 410 | var deferred = new Deferred( cancel ), 411 | once = true; 412 | 413 | if( !(array instanceof Array) ) 414 | array = Array.prototype.slice.call(arguments); 415 | else 416 | array = array.slice(); 417 | var todo = array.reduce( function(count,p){ return count+(p&&p.then?1:0); }, 0 ); 418 | if( todo === 0 ) 419 | deferred.resolve(array); 420 | else 421 | array.forEach( function( p, i ) { 422 | if( p && p.then ) 423 | exports.when( p, succeed, fail_on_error ? failOnce : succeed ); 424 | 425 | function succeed( v ) { 426 | array[i] = v; 427 | if( --todo === 0 ) 428 | deferred.resolve(array); 429 | } 430 | 431 | function failOnce( err ) { 432 | if( once ) { 433 | cancel( i ); 434 | deferred.reject( err ); 435 | once = false; 436 | } 437 | } 438 | } ); 439 | 440 | return deferred.promise; 441 | 442 | function cancel( except ) { 443 | array.forEach( function(p,i) { 444 | if( i !== except && p.then && p.cancel ) 445 | p.cancel(); 446 | } ); 447 | } 448 | } 449 | } 450 | 451 | exports.all = composeAll(false); 452 | 453 | /** 454 | * Variation of all() -- fails if any of the promises fail 455 | */ 456 | exports.allOrNone = composeAll(true); 457 | 458 | /** 459 | * Takes an array of promises and returns a promise that is fulfilled when the first 460 | * promise in the array of promises is fulfilled 461 | * @param array The array of promises 462 | * @return a promise that is fulfilled with the value of the value of first promise to be fulfilled 463 | */ 464 | exports.first = function(array){ 465 | var deferred = new Deferred(); 466 | if(!(array instanceof Array)){ 467 | array = Array.prototype.slice.call(arguments); 468 | } 469 | var fulfilled; 470 | array.forEach(function(promise, index){ 471 | exports.when(promise, function(value){ 472 | if (!fulfilled) { 473 | fulfilled = true; 474 | deferred.resolve(value); 475 | } 476 | }, 477 | function(error){ 478 | if (!fulfilled) { 479 | fulfilled = true; 480 | deferred.resolve(error); 481 | } 482 | }); 483 | }); 484 | return deferred.promise; 485 | }; 486 | 487 | /** 488 | * Takes an array of asynchronous functions (that return promises) and 489 | * executes them sequentially. Each funtion is called with the return value of the last function 490 | * @param array The array of function 491 | * @param startingValue The value to pass to the first function 492 | * @return the value returned from the last function 493 | */ 494 | exports.seq = function(array, startingValue){ 495 | array = array.concat(); // make a copy 496 | var deferred = new Deferred(); 497 | function next(value){ 498 | var nextAction = array.shift(); 499 | if(nextAction){ 500 | exports.when(nextAction(value), next, deferred.reject); 501 | } 502 | else { 503 | deferred.resolve(value); 504 | } 505 | } 506 | next(startingValue); 507 | return deferred.promise; 508 | }; 509 | 510 | 511 | /** 512 | * Delays for a given amount of time and then fulfills the returned promise. 513 | * @param milliseconds The number of milliseconds to delay 514 | * @return A promise that will be fulfilled after the delay 515 | */ 516 | if(typeof setTimeout !== "undefined") { 517 | exports.delay = function(milliseconds) { 518 | var deferred = new Deferred(); 519 | setTimeout(function(){ 520 | deferred.resolve(); 521 | }, milliseconds); 522 | return deferred.promise; 523 | }; 524 | } 525 | 526 | 527 | 528 | /** 529 | * Runs a function that takes a callback, but returns a Promise instead. 530 | * @param func node compatible async function which takes a callback as its last argument 531 | * @return promise for the return value from the callback from the function 532 | */ 533 | exports.execute = function(asyncFunction){ 534 | var args = Array.prototype.slice.call(arguments, 1); 535 | 536 | var deferred = new Deferred(); 537 | args.push(function(error, result){ 538 | if(error) { 539 | deferred.emitError(error); 540 | } 541 | else { 542 | if(arguments.length > 2){ 543 | // if there are multiple success values, we return an array 544 | Array.prototype.shift.call(arguments, 1); 545 | deferred.emitSuccess(arguments); 546 | } 547 | else{ 548 | deferred.emitSuccess(result); 549 | } 550 | } 551 | }); 552 | asyncFunction.apply(this, args); 553 | return deferred.promise; 554 | }; 555 | 556 | /** 557 | * Converts a Node async function to a promise returning function 558 | * @param func node compatible async function which takes a callback as its last argument 559 | * @return A function that returns a promise 560 | */ 561 | exports.convertNodeAsyncFunction = function(asyncFunction, callbackNotDeclared){ 562 | var arity = asyncFunction.length; 563 | if(callbackNotDeclared){ 564 | arity++; 565 | } 566 | return function(){ 567 | var deferred = new Deferred(); 568 | arguments.length = arity; 569 | arguments[arity - 1] = function(error, result){ 570 | if(error) { 571 | deferred.emitError(error); 572 | } 573 | else { 574 | if(arguments.length > 2){ 575 | // if there are multiple success values, we return an array 576 | Array.prototype.shift.call(arguments, 1); 577 | deferred.emitSuccess(arguments); 578 | } 579 | else{ 580 | deferred.emitSuccess(result); 581 | } 582 | } 583 | }; 584 | asyncFunction.apply(this, arguments); 585 | return deferred.promise; 586 | }; 587 | }; 588 | -------------------------------------------------------------------------------- /support/lambdajs/test/lib/jasmine-1.2.0/jasmine-html.js: -------------------------------------------------------------------------------- 1 | jasmine.HtmlReporterHelpers = {}; 2 | 3 | jasmine.HtmlReporterHelpers.createDom = function(type, attrs, childrenVarArgs) { 4 | var el = document.createElement(type); 5 | 6 | for (var i = 2; i < arguments.length; i++) { 7 | var child = arguments[i]; 8 | 9 | if (typeof child === 'string') { 10 | el.appendChild(document.createTextNode(child)); 11 | } else { 12 | if (child) { 13 | el.appendChild(child); 14 | } 15 | } 16 | } 17 | 18 | for (var attr in attrs) { 19 | if (attr == "className") { 20 | el[attr] = attrs[attr]; 21 | } else { 22 | el.setAttribute(attr, attrs[attr]); 23 | } 24 | } 25 | 26 | return el; 27 | }; 28 | 29 | jasmine.HtmlReporterHelpers.getSpecStatus = function(child) { 30 | var results = child.results(); 31 | var status = results.passed() ? 'passed' : 'failed'; 32 | if (results.skipped) { 33 | status = 'skipped'; 34 | } 35 | 36 | return status; 37 | }; 38 | 39 | jasmine.HtmlReporterHelpers.appendToSummary = function(child, childElement) { 40 | var parentDiv = this.dom.summary; 41 | var parentSuite = (typeof child.parentSuite == 'undefined') ? 'suite' : 'parentSuite'; 42 | var parent = child[parentSuite]; 43 | 44 | if (parent) { 45 | if (typeof this.views.suites[parent.id] == 'undefined') { 46 | this.views.suites[parent.id] = new jasmine.HtmlReporter.SuiteView(parent, this.dom, this.views); 47 | } 48 | parentDiv = this.views.suites[parent.id].element; 49 | } 50 | 51 | parentDiv.appendChild(childElement); 52 | }; 53 | 54 | 55 | jasmine.HtmlReporterHelpers.addHelpers = function(ctor) { 56 | for(var fn in jasmine.HtmlReporterHelpers) { 57 | ctor.prototype[fn] = jasmine.HtmlReporterHelpers[fn]; 58 | } 59 | }; 60 | 61 | jasmine.HtmlReporter = function(_doc) { 62 | var self = this; 63 | var doc = _doc || window.document; 64 | 65 | var reporterView; 66 | 67 | var dom = {}; 68 | 69 | // Jasmine Reporter Public Interface 70 | self.logRunningSpecs = false; 71 | 72 | self.reportRunnerStarting = function(runner) { 73 | var specs = runner.specs() || []; 74 | 75 | if (specs.length == 0) { 76 | return; 77 | } 78 | 79 | createReporterDom(runner.env.versionString()); 80 | doc.body.appendChild(dom.reporter); 81 | 82 | reporterView = new jasmine.HtmlReporter.ReporterView(dom); 83 | reporterView.addSpecs(specs, self.specFilter); 84 | }; 85 | 86 | self.reportRunnerResults = function(runner) { 87 | reporterView && reporterView.complete(); 88 | }; 89 | 90 | self.reportSuiteResults = function(suite) { 91 | reporterView.suiteComplete(suite); 92 | }; 93 | 94 | self.reportSpecStarting = function(spec) { 95 | if (self.logRunningSpecs) { 96 | self.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); 97 | } 98 | }; 99 | 100 | self.reportSpecResults = function(spec) { 101 | reporterView.specComplete(spec); 102 | }; 103 | 104 | self.log = function() { 105 | var console = jasmine.getGlobal().console; 106 | if (console && console.log) { 107 | if (console.log.apply) { 108 | console.log.apply(console, arguments); 109 | } else { 110 | console.log(arguments); // ie fix: console.log.apply doesn't exist on ie 111 | } 112 | } 113 | }; 114 | 115 | self.specFilter = function(spec) { 116 | if (!focusedSpecName()) { 117 | return true; 118 | } 119 | 120 | return spec.getFullName().indexOf(focusedSpecName()) === 0; 121 | }; 122 | 123 | return self; 124 | 125 | function focusedSpecName() { 126 | var specName; 127 | 128 | (function memoizeFocusedSpec() { 129 | if (specName) { 130 | return; 131 | } 132 | 133 | var paramMap = []; 134 | var params = doc.location.search.substring(1).split('&'); 135 | 136 | for (var i = 0; i < params.length; i++) { 137 | var p = params[i].split('='); 138 | paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); 139 | } 140 | 141 | specName = paramMap.spec; 142 | })(); 143 | 144 | return specName; 145 | } 146 | 147 | function createReporterDom(version) { 148 | dom.reporter = self.createDom('div', { id: 'HTMLReporter', className: 'jasmine_reporter' }, 149 | dom.banner = self.createDom('div', { className: 'banner' }, 150 | self.createDom('span', { className: 'title' }, "Jasmine "), 151 | self.createDom('span', { className: 'version' }, version)), 152 | 153 | dom.symbolSummary = self.createDom('ul', {className: 'symbolSummary'}), 154 | dom.alert = self.createDom('div', {className: 'alert'}), 155 | dom.results = self.createDom('div', {className: 'results'}, 156 | dom.summary = self.createDom('div', { className: 'summary' }), 157 | dom.details = self.createDom('div', { id: 'details' })) 158 | ); 159 | } 160 | }; 161 | jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter);jasmine.HtmlReporter.ReporterView = function(dom) { 162 | this.startedAt = new Date(); 163 | this.runningSpecCount = 0; 164 | this.completeSpecCount = 0; 165 | this.passedCount = 0; 166 | this.failedCount = 0; 167 | this.skippedCount = 0; 168 | 169 | this.createResultsMenu = function() { 170 | this.resultsMenu = this.createDom('span', {className: 'resultsMenu bar'}, 171 | this.summaryMenuItem = this.createDom('a', {className: 'summaryMenuItem', href: "#"}, '0 specs'), 172 | ' | ', 173 | this.detailsMenuItem = this.createDom('a', {className: 'detailsMenuItem', href: "#"}, '0 failing')); 174 | 175 | this.summaryMenuItem.onclick = function() { 176 | dom.reporter.className = dom.reporter.className.replace(/ showDetails/g, ''); 177 | }; 178 | 179 | this.detailsMenuItem.onclick = function() { 180 | showDetails(); 181 | }; 182 | }; 183 | 184 | this.addSpecs = function(specs, specFilter) { 185 | this.totalSpecCount = specs.length; 186 | 187 | this.views = { 188 | specs: {}, 189 | suites: {} 190 | }; 191 | 192 | for (var i = 0; i < specs.length; i++) { 193 | var spec = specs[i]; 194 | this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom, this.views); 195 | if (specFilter(spec)) { 196 | this.runningSpecCount++; 197 | } 198 | } 199 | }; 200 | 201 | this.specComplete = function(spec) { 202 | this.completeSpecCount++; 203 | 204 | if (isUndefined(this.views.specs[spec.id])) { 205 | this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom); 206 | } 207 | 208 | var specView = this.views.specs[spec.id]; 209 | 210 | switch (specView.status()) { 211 | case 'passed': 212 | this.passedCount++; 213 | break; 214 | 215 | case 'failed': 216 | this.failedCount++; 217 | break; 218 | 219 | case 'skipped': 220 | this.skippedCount++; 221 | break; 222 | } 223 | 224 | specView.refresh(); 225 | this.refresh(); 226 | }; 227 | 228 | this.suiteComplete = function(suite) { 229 | var suiteView = this.views.suites[suite.id]; 230 | if (isUndefined(suiteView)) { 231 | return; 232 | } 233 | suiteView.refresh(); 234 | }; 235 | 236 | this.refresh = function() { 237 | 238 | if (isUndefined(this.resultsMenu)) { 239 | this.createResultsMenu(); 240 | } 241 | 242 | // currently running UI 243 | if (isUndefined(this.runningAlert)) { 244 | this.runningAlert = this.createDom('a', {href: "?", className: "runningAlert bar"}); 245 | dom.alert.appendChild(this.runningAlert); 246 | } 247 | this.runningAlert.innerHTML = "Running " + this.completeSpecCount + " of " + specPluralizedFor(this.totalSpecCount); 248 | 249 | // skipped specs UI 250 | if (isUndefined(this.skippedAlert)) { 251 | this.skippedAlert = this.createDom('a', {href: "?", className: "skippedAlert bar"}); 252 | } 253 | 254 | this.skippedAlert.innerHTML = "Skipping " + this.skippedCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all"; 255 | 256 | if (this.skippedCount === 1 && isDefined(dom.alert)) { 257 | dom.alert.appendChild(this.skippedAlert); 258 | } 259 | 260 | // passing specs UI 261 | if (isUndefined(this.passedAlert)) { 262 | this.passedAlert = this.createDom('span', {href: "?", className: "passingAlert bar"}); 263 | } 264 | this.passedAlert.innerHTML = "Passing " + specPluralizedFor(this.passedCount); 265 | 266 | // failing specs UI 267 | if (isUndefined(this.failedAlert)) { 268 | this.failedAlert = this.createDom('span', {href: "?", className: "failingAlert bar"}); 269 | } 270 | this.failedAlert.innerHTML = "Failing " + specPluralizedFor(this.failedCount); 271 | 272 | if (this.failedCount === 1 && isDefined(dom.alert)) { 273 | dom.alert.appendChild(this.failedAlert); 274 | dom.alert.appendChild(this.resultsMenu); 275 | } 276 | 277 | // summary info 278 | this.summaryMenuItem.innerHTML = "" + specPluralizedFor(this.runningSpecCount); 279 | this.detailsMenuItem.innerHTML = "" + this.failedCount + " failing"; 280 | }; 281 | 282 | this.complete = function() { 283 | dom.alert.removeChild(this.runningAlert); 284 | 285 | this.skippedAlert.innerHTML = "Ran " + this.runningSpecCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all"; 286 | 287 | if (this.failedCount === 0) { 288 | dom.alert.appendChild(this.createDom('span', {className: 'passingAlert bar'}, "Passing " + specPluralizedFor(this.passedCount))); 289 | } else { 290 | showDetails(); 291 | } 292 | 293 | dom.banner.appendChild(this.createDom('span', {className: 'duration'}, "finished in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s")); 294 | }; 295 | 296 | return this; 297 | 298 | function showDetails() { 299 | if (dom.reporter.className.search(/showDetails/) === -1) { 300 | dom.reporter.className += " showDetails"; 301 | } 302 | } 303 | 304 | function isUndefined(obj) { 305 | return typeof obj === 'undefined'; 306 | } 307 | 308 | function isDefined(obj) { 309 | return !isUndefined(obj); 310 | } 311 | 312 | function specPluralizedFor(count) { 313 | var str = count + " spec"; 314 | if (count > 1) { 315 | str += "s" 316 | } 317 | return str; 318 | } 319 | 320 | }; 321 | 322 | jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.ReporterView); 323 | 324 | 325 | jasmine.HtmlReporter.SpecView = function(spec, dom, views) { 326 | this.spec = spec; 327 | this.dom = dom; 328 | this.views = views; 329 | 330 | this.symbol = this.createDom('li', { className: 'pending' }); 331 | this.dom.symbolSummary.appendChild(this.symbol); 332 | 333 | this.summary = this.createDom('div', { className: 'specSummary' }, 334 | this.createDom('a', { 335 | className: 'description', 336 | href: '?spec=' + encodeURIComponent(this.spec.getFullName()), 337 | title: this.spec.getFullName() 338 | }, this.spec.description) 339 | ); 340 | 341 | this.detail = this.createDom('div', { className: 'specDetail' }, 342 | this.createDom('a', { 343 | className: 'description', 344 | href: '?spec=' + encodeURIComponent(this.spec.getFullName()), 345 | title: this.spec.getFullName() 346 | }, this.spec.getFullName()) 347 | ); 348 | }; 349 | 350 | jasmine.HtmlReporter.SpecView.prototype.status = function() { 351 | return this.getSpecStatus(this.spec); 352 | }; 353 | 354 | jasmine.HtmlReporter.SpecView.prototype.refresh = function() { 355 | this.symbol.className = this.status(); 356 | 357 | switch (this.status()) { 358 | case 'skipped': 359 | break; 360 | 361 | case 'passed': 362 | this.appendSummaryToSuiteDiv(); 363 | break; 364 | 365 | case 'failed': 366 | this.appendSummaryToSuiteDiv(); 367 | this.appendFailureDetail(); 368 | break; 369 | } 370 | }; 371 | 372 | jasmine.HtmlReporter.SpecView.prototype.appendSummaryToSuiteDiv = function() { 373 | this.summary.className += ' ' + this.status(); 374 | this.appendToSummary(this.spec, this.summary); 375 | }; 376 | 377 | jasmine.HtmlReporter.SpecView.prototype.appendFailureDetail = function() { 378 | this.detail.className += ' ' + this.status(); 379 | 380 | var resultItems = this.spec.results().getItems(); 381 | var messagesDiv = this.createDom('div', { className: 'messages' }); 382 | 383 | for (var i = 0; i < resultItems.length; i++) { 384 | var result = resultItems[i]; 385 | 386 | if (result.type == 'log') { 387 | messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); 388 | } else if (result.type == 'expect' && result.passed && !result.passed()) { 389 | messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); 390 | 391 | if (result.trace.stack) { 392 | messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); 393 | } 394 | } 395 | } 396 | 397 | if (messagesDiv.childNodes.length > 0) { 398 | this.detail.appendChild(messagesDiv); 399 | this.dom.details.appendChild(this.detail); 400 | } 401 | }; 402 | 403 | jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SpecView);jasmine.HtmlReporter.SuiteView = function(suite, dom, views) { 404 | this.suite = suite; 405 | this.dom = dom; 406 | this.views = views; 407 | 408 | this.element = this.createDom('div', { className: 'suite' }, 409 | this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(this.suite.getFullName()) }, this.suite.description) 410 | ); 411 | 412 | this.appendToSummary(this.suite, this.element); 413 | }; 414 | 415 | jasmine.HtmlReporter.SuiteView.prototype.status = function() { 416 | return this.getSpecStatus(this.suite); 417 | }; 418 | 419 | jasmine.HtmlReporter.SuiteView.prototype.refresh = function() { 420 | this.element.className += " " + this.status(); 421 | }; 422 | 423 | jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SuiteView); 424 | 425 | /* @deprecated Use jasmine.HtmlReporter instead 426 | */ 427 | jasmine.TrivialReporter = function(doc) { 428 | this.document = doc || document; 429 | this.suiteDivs = {}; 430 | this.logRunningSpecs = false; 431 | }; 432 | 433 | jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) { 434 | var el = document.createElement(type); 435 | 436 | for (var i = 2; i < arguments.length; i++) { 437 | var child = arguments[i]; 438 | 439 | if (typeof child === 'string') { 440 | el.appendChild(document.createTextNode(child)); 441 | } else { 442 | if (child) { el.appendChild(child); } 443 | } 444 | } 445 | 446 | for (var attr in attrs) { 447 | if (attr == "className") { 448 | el[attr] = attrs[attr]; 449 | } else { 450 | el.setAttribute(attr, attrs[attr]); 451 | } 452 | } 453 | 454 | return el; 455 | }; 456 | 457 | jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) { 458 | var showPassed, showSkipped; 459 | 460 | this.outerDiv = this.createDom('div', { id: 'TrivialReporter', className: 'jasmine_reporter' }, 461 | this.createDom('div', { className: 'banner' }, 462 | this.createDom('div', { className: 'logo' }, 463 | this.createDom('span', { className: 'title' }, "Jasmine"), 464 | this.createDom('span', { className: 'version' }, runner.env.versionString())), 465 | this.createDom('div', { className: 'options' }, 466 | "Show ", 467 | showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }), 468 | this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "), 469 | showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }), 470 | this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped") 471 | ) 472 | ), 473 | 474 | this.runnerDiv = this.createDom('div', { className: 'runner running' }, 475 | this.createDom('a', { className: 'run_spec', href: '?' }, "run all"), 476 | this.runnerMessageSpan = this.createDom('span', {}, "Running..."), 477 | this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, "")) 478 | ); 479 | 480 | this.document.body.appendChild(this.outerDiv); 481 | 482 | var suites = runner.suites(); 483 | for (var i = 0; i < suites.length; i++) { 484 | var suite = suites[i]; 485 | var suiteDiv = this.createDom('div', { className: 'suite' }, 486 | this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"), 487 | this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description)); 488 | this.suiteDivs[suite.id] = suiteDiv; 489 | var parentDiv = this.outerDiv; 490 | if (suite.parentSuite) { 491 | parentDiv = this.suiteDivs[suite.parentSuite.id]; 492 | } 493 | parentDiv.appendChild(suiteDiv); 494 | } 495 | 496 | this.startedAt = new Date(); 497 | 498 | var self = this; 499 | showPassed.onclick = function(evt) { 500 | if (showPassed.checked) { 501 | self.outerDiv.className += ' show-passed'; 502 | } else { 503 | self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, ''); 504 | } 505 | }; 506 | 507 | showSkipped.onclick = function(evt) { 508 | if (showSkipped.checked) { 509 | self.outerDiv.className += ' show-skipped'; 510 | } else { 511 | self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, ''); 512 | } 513 | }; 514 | }; 515 | 516 | jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) { 517 | var results = runner.results(); 518 | var className = (results.failedCount > 0) ? "runner failed" : "runner passed"; 519 | this.runnerDiv.setAttribute("class", className); 520 | //do it twice for IE 521 | this.runnerDiv.setAttribute("className", className); 522 | var specs = runner.specs(); 523 | var specCount = 0; 524 | for (var i = 0; i < specs.length; i++) { 525 | if (this.specFilter(specs[i])) { 526 | specCount++; 527 | } 528 | } 529 | var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s"); 530 | message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"; 531 | this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild); 532 | 533 | this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString())); 534 | }; 535 | 536 | jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) { 537 | var results = suite.results(); 538 | var status = results.passed() ? 'passed' : 'failed'; 539 | if (results.totalCount === 0) { // todo: change this to check results.skipped 540 | status = 'skipped'; 541 | } 542 | this.suiteDivs[suite.id].className += " " + status; 543 | }; 544 | 545 | jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) { 546 | if (this.logRunningSpecs) { 547 | this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...'); 548 | } 549 | }; 550 | 551 | jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) { 552 | var results = spec.results(); 553 | var status = results.passed() ? 'passed' : 'failed'; 554 | if (results.skipped) { 555 | status = 'skipped'; 556 | } 557 | var specDiv = this.createDom('div', { className: 'spec ' + status }, 558 | this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"), 559 | this.createDom('a', { 560 | className: 'description', 561 | href: '?spec=' + encodeURIComponent(spec.getFullName()), 562 | title: spec.getFullName() 563 | }, spec.description)); 564 | 565 | 566 | var resultItems = results.getItems(); 567 | var messagesDiv = this.createDom('div', { className: 'messages' }); 568 | for (var i = 0; i < resultItems.length; i++) { 569 | var result = resultItems[i]; 570 | 571 | if (result.type == 'log') { 572 | messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString())); 573 | } else if (result.type == 'expect' && result.passed && !result.passed()) { 574 | messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message)); 575 | 576 | if (result.trace.stack) { 577 | messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack)); 578 | } 579 | } 580 | } 581 | 582 | if (messagesDiv.childNodes.length > 0) { 583 | specDiv.appendChild(messagesDiv); 584 | } 585 | 586 | this.suiteDivs[spec.suite.id].appendChild(specDiv); 587 | }; 588 | 589 | jasmine.TrivialReporter.prototype.log = function() { 590 | var console = jasmine.getGlobal().console; 591 | if (console && console.log) { 592 | if (console.log.apply) { 593 | console.log.apply(console, arguments); 594 | } else { 595 | console.log(arguments); // ie fix: console.log.apply doesn't exist on ie 596 | } 597 | } 598 | }; 599 | 600 | jasmine.TrivialReporter.prototype.getLocation = function() { 601 | return this.document.location; 602 | }; 603 | 604 | jasmine.TrivialReporter.prototype.specFilter = function(spec) { 605 | var paramMap = {}; 606 | var params = this.getLocation().search.substring(1).split('&'); 607 | for (var i = 0; i < params.length; i++) { 608 | var p = params[i].split('='); 609 | paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); 610 | } 611 | 612 | if (!paramMap.spec) { 613 | return true; 614 | } 615 | return spec.getFullName().indexOf(paramMap.spec) === 0; 616 | }; 617 | -------------------------------------------------------------------------------- /vendor/FunctionalJS/functional.js: -------------------------------------------------------------------------------- 1 | ;(function (window, undefined) { 2 | 3 | // Detect free variables "exports" and "global", and create 4 | // "functional" namespace 5 | var freeExports = typeof exports == 'object' && exports, 6 | freeGlobal = typeof global == 'object' && global, 7 | _ = Function._ = {}, 8 | _initialFunctionPrototypeState, 9 | functional = {}, 10 | oldFunctional = {}; 11 | 12 | // Add slice() method to JavaScript's built-in Array object, if it 13 | // doesn't already exist. 14 | if (!Array.slice) { 15 | Array.slice = (function (slice) { 16 | return function (object) { 17 | return slice.apply(object, slice.call(arguments, 1)); 18 | }; 19 | })(Array.prototype.slice); 20 | } 21 | 22 | // Add autoCurry() to the Function prototype. The autoCurry() 23 | // method is a Function decorator that returns a duplicate of 24 | // the function, but which can now be partially applied. 25 | // curry/autoCurry is from wu.js 26 | (function() { 27 | var toArray = function(x) { 28 | return Array.prototype.slice.call(x); 29 | } 30 | 31 | var curry = function (fn /* variadic number of args */) { 32 | var args = Array.prototype.slice.call(arguments, 1); 33 | var f = function () { 34 | return fn.apply(this, args.concat(toArray(arguments))); 35 | }; 36 | return f; 37 | }; 38 | 39 | var autoCurry = function (fn, numArgs) { 40 | numArgs = numArgs || fn.length; 41 | var f = function () { 42 | if (arguments.length < numArgs) { 43 | return numArgs - arguments.length > 0 ? 44 | autoCurry(curry.apply(this, [fn].concat(toArray(arguments))), 45 | numArgs - arguments.length) : 46 | curry.apply(this, [fn].concat(toArray(arguments))); 47 | } 48 | else { 49 | return fn.apply(this, arguments); 50 | } 51 | }; 52 | f.toString = function(){ return fn.toString(); }; 53 | f.curried = true; 54 | f.fn = fn; 55 | f.arity = fn.length; 56 | return f; 57 | }; 58 | 59 | Function.prototype.autoCurry = function(n) { 60 | return autoCurry(this, n); 61 | } 62 | })(); 63 | 64 | thread = function(f, n) { 65 | setTimeout(f, (n || 1)); 66 | } 67 | 68 | parallel=function(){ 69 | var fns = map(Function.toFunction,arguments) 70 | , arglen = fns.length; 71 | 72 | return function(x){ 73 | var args = arguments; 74 | for(var i=arglen;--i>=0;) { 75 | thread(fns[i].p(x)); 76 | } 77 | 78 | return arguments[0]; 79 | } 80 | } 81 | 82 | function map(fn, sequence) { 83 | var length = sequence.length, 84 | result = new Array(length), 85 | i; 86 | fn = Function.toFunction(fn); 87 | for (i = 0; i < length; i++) { 88 | result[i] = fn.apply(null, [sequence[i], i]); 89 | } 90 | return result; 91 | } 92 | 93 | compose = function() { 94 | var fns = arguments, 95 | arglen = fns.length; 96 | 97 | return function(){ 98 | for(var i=arglen;--i>=0;) { 99 | var fn = fns[i] 100 | , args = fn.length ? Array.prototype.slice.call(arguments, 0, fn.length) : arguments 101 | , next_args = Array.prototype.slice.call(arguments, (fn.length || 1)); //not right with *args 102 | next_args.unshift(fn.apply(this,args)); 103 | arguments = next_args; 104 | } 105 | return arguments[0]; 106 | } 107 | } 108 | 109 | function sequence() { 110 | var fns = map(Function.toFunction, arguments), 111 | arglen = fns.length; 112 | return function () { 113 | var i; 114 | for (i = 0; i < arglen; i++) { 115 | arguments = [fns[i].apply(this, arguments)]; 116 | } 117 | return arguments[0]; 118 | }; 119 | } 120 | 121 | function memoize(fn) { 122 | return function () { 123 | var args = Array.prototype.slice.call(arguments), 124 | hash = "", 125 | i = args.length; 126 | currentArg = null; 127 | while (i--) { 128 | currentArg = args[i]; 129 | hash += (currentArg === Object(currentArg)) ? 130 | JSON.stringify(currentArg) : currentArg; 131 | fn.memoize || (fn.memoize = {}); 132 | } 133 | return (hash in fn.memoize) ? fn.memoize[hash] : 134 | fn.memoize[hash] = fn.apply(this, args); 135 | }; 136 | } 137 | 138 | function reduce(fn,init,sequence) { 139 | var len = sequence.length, 140 | result = init, 141 | i; 142 | fn = Function.toFunction(fn); 143 | for(i = 0; i < len; i++) { 144 | result = fn.apply(null, [result, sequence[i]]); 145 | } 146 | return result; 147 | } 148 | 149 | function select(fn, sequence) { 150 | var len = sequence.length, 151 | result = [], 152 | i, x; 153 | fn = Function.toFunction(fn); 154 | for(i = 0; i < len; i++) { 155 | x = sequence[i]; 156 | fn.apply(null, [x, i]) && result.push(x); 157 | } 158 | return result; 159 | } 160 | 161 | function guard(guard, fn, otherwise) { 162 | guard = Function.toFunction(guard || I); 163 | fn = Function.toFunction(fn); 164 | otherwise = Function.toFunction(otherwise || I); 165 | return function () { 166 | return (guard.apply(this, arguments) ? fn : otherwise) 167 | .apply(this, arguments); 168 | }; 169 | } 170 | 171 | function flip(f) { return f.flip(); } 172 | 173 | function foldr(fn, init, sequence) { 174 | var len = sequence.length, 175 | result = init, 176 | i; 177 | fn = Function.toFunction(fn); 178 | for(i = len; --i >= 0;) { 179 | result = fn.apply(null, [sequence[i],result]); 180 | } 181 | return result; 182 | } 183 | 184 | function and() { 185 | var args = map(Function.toFunction, arguments), 186 | arglen = args.length; 187 | return function () { 188 | var value = true, i; 189 | for (i = 0; i < arglen; i++) { 190 | if(!(value = args[i].apply(this, arguments))) 191 | break; 192 | } 193 | return value; 194 | }; 195 | } 196 | 197 | function or() { 198 | var args = map(Function.toFunction, arguments), 199 | arglen = args.length; 200 | return function () { 201 | var value = false, i; 202 | for (i = 0; i < arglen; i++) { 203 | if ((value = args[i].apply(this, arguments))) 204 | break; 205 | } 206 | return value; 207 | }; 208 | } 209 | 210 | function some(fn, sequence) { 211 | fn = Function.toFunction(fn); 212 | var len = sequence.length, 213 | value = false, 214 | i; 215 | for (i = 0; i < len; i++) { 216 | if ((value = fn.call(null, sequence[i]))) 217 | break; 218 | } 219 | return value; 220 | } 221 | 222 | function every(fn, sequence) { 223 | fn = Function.toFunction(fn); 224 | var len = sequence.length, 225 | value = true, 226 | i; 227 | for (i = 0; i < len; i++) { 228 | if (!(value = fn.call(null, sequence[i]))) 229 | break; 230 | } 231 | return value; 232 | } 233 | 234 | function not(fn) { 235 | fn = Function.toFunction(fn); 236 | return function () { 237 | return !fn.apply(null, arguments); 238 | }; 239 | } 240 | 241 | function equal() { 242 | var arglen = arguments.length, 243 | args = map(Function.toFunction, arguments); 244 | if (!arglen) { 245 | return K(true); 246 | } 247 | return function () { 248 | var value = args[0].apply(this, arguments), 249 | i; 250 | for (i = 1; i < arglen; i++){ 251 | if (value != args[i].apply(this, args)) 252 | return false; 253 | } 254 | return true; 255 | }; 256 | } 257 | 258 | function lambda(object) { 259 | return object.toFunction(); 260 | } 261 | 262 | function invoke(methodName) { 263 | var args = Array.slice(arguments, 1); 264 | return function(object) { 265 | return object[methodName].apply(object, Array.slice(arguments, 1).concat(args)); 266 | }; 267 | } 268 | 269 | function pluck(name, object) { 270 | return object[name]; 271 | } 272 | 273 | function until(pred, fn) { 274 | fn = Function.toFunction(fn); 275 | pred = Function.toFunction(pred); 276 | return function (value) { 277 | while (!pred.call(null, value)) { 278 | value = fn.call(null, value); 279 | } 280 | return value; 281 | } 282 | } 283 | 284 | function zip() { 285 | var n = Math.min.apply(null, map('.length',arguments)), 286 | results = new Array(n), 287 | key, i; 288 | for (i = 0; i < n; i++) { 289 | key = String(i); 290 | results[key] = map(pluck(key), arguments); 291 | }; 292 | return results; 293 | } 294 | 295 | 296 | // Higher order methods 297 | // Begin tracking changes to the Function.Prototype 298 | _initialFunctionPrototypeState = _startRecordingMethodChanges(Function.prototype); 299 | 300 | Function.prototype.bind = function (object) { 301 | var fn = this, 302 | slice = Array.slice, 303 | args = slice(arguments, 1); 304 | return function () { 305 | return fn.apply(object, args.concat(slice(arguments, 0))); 306 | }; 307 | } 308 | 309 | Function.prototype.saturate = function () { 310 | var fn = this, 311 | args = Array.slice(arguments, 0); 312 | return function () { return fn.apply(this, args); }; 313 | } 314 | 315 | Function.prototype.aritize = function (n) { 316 | var fn = this; 317 | return function () { 318 | return fn.apply(this, Array.slice(arguments, 0, n)); 319 | }; 320 | } 321 | 322 | Function.prototype.curry = function () { 323 | var fn = this, 324 | slice = Array.slice, 325 | args = slice(arguments, 0); 326 | return function () { 327 | return fn.apply(this, args.concat(slice(arguments, 0))); 328 | }; 329 | } 330 | 331 | Function.prototype.rcurry = function () { 332 | var fn = this, 333 | slice = Array.slice, 334 | args = slice(arguments, 0); 335 | return function () { 336 | return fn.apply(this, slice(arguments, 0).concat(args)); 337 | }; 338 | } 339 | 340 | Function.prototype.ncurry = function (n) { 341 | var fn = this, 342 | slice = Array.slice, 343 | largs = slice(arguments, 1); 344 | return function () { 345 | var args = largs.concat(slice(arguments, 0)); 346 | if (args.length ', result); 495 | return result; 496 | }; 497 | } 498 | 499 | Function.toFunction = function (value) { return value.toFunction();} 500 | 501 | // In case to-function.js isn't loaded. 502 | Function.toFunction = Function.toFunction || K; 503 | 504 | Function.prototype.toFunction = function () { return this; } 505 | 506 | // 507 | // String Methods 508 | // 509 | String.prototype.lambda = function () { 510 | var params=[], 511 | expr = this, 512 | sections = expr.ECMAsplit(/\s*->\s*/m);if(sections.length>1){while(sections.length){expr=sections.pop();params=sections.pop().split(/\s*,\s*|\s+/m);sections.length&§ions.push('(function('+params+'){return ('+expr+')})');}}else if(expr.match(/\b_\b/)){params='_';}else{var leftSection=expr.match(/^\s*(?:[+*\/%&|\^\.=<>]|!=)/m),rightSection=expr.match(/[+\-*\/%&|\^\.=<>!]\s*$/m);if(leftSection||rightSection){if(leftSection){params.push('$1');expr='$1'+expr;} 513 | if(rightSection){params.push('$2');expr=expr+'$2';}}else{var vars=this.replace(/(?:\b[A-Z]|\.[a-zA-Z_$])[a-zA-Z_$\d]*|[a-zA-Z_$][a-zA-Z_$\d]*\s*:|this|arguments|'(?:[^'\\]|\\.)*'|"(?:[^"\\]|\\.)*"/g,'').match(/([a-z_$][a-z_$\d]*)/gi)||[];for(var i=0,v;v=vars[i++];) 514 | params.indexOf(v)>=0||params.push(v);}} 515 | return new Function(params,'return ('+expr+')'); 516 | } 517 | 518 | String.prototype.lambda.cache = function () { 519 | var proto = String.prototype, 520 | cache = {}, 521 | uncached = proto.lambda, 522 | cached; 523 | cached = function () { 524 | var key = '#' + this; 525 | return cache[key] || (cache[key] = uncached.call(this)); 526 | }; 527 | cached.cached = function () {}; 528 | cached.uncache = function () { proto.lambda = uncached }; 529 | proto.lambda = cached; 530 | } 531 | 532 | String.prototype.apply = function (thisArg, args) { 533 | return this.toFunction().apply(thisArg, args); 534 | } 535 | 536 | String.prototype.call = function () { 537 | return this.toFunction().apply(arguments[0], Array.prototype.slice.call(arguments,1)); 538 | } 539 | 540 | String.prototype.toFunction = function () { 541 | var body = this; 542 | if (body.match(/\breturn\b/)) { 543 | return new Function(this); 544 | } 545 | return this.lambda(); 546 | } 547 | 548 | String.prototype.ECMAsplit = ('ab'.split(/a*/).length>1?String.prototype.split:function(separator,limit){if(typeof limit!='undefined') 549 | throw"ECMAsplit: limit is unimplemented";var result=this.split.apply(this,arguments),re=RegExp(separator),savedIndex=re.lastIndex,match=re.exec(this);if(match&&match.index==0) 550 | result.unshift('');re.lastIndex=savedIndex;return result;}); 551 | 552 | function _startRecordingMethodChanges(object) { 553 | var initialMethods = {}, name; 554 | for (name in object) { 555 | initialMethods[name] = object[name]; 556 | } 557 | function getChangedMethods() { 558 | var changedMethods = {}; 559 | for (var name in object) { 560 | if (object[name] != initialMethods[name]) { 561 | changedMethods[name] = object[name]; 562 | } 563 | } 564 | return changedMethods; 565 | } 566 | return { getChangedMethods: getChangedMethods } 567 | } 568 | 569 | function _attachMethodDelegates(methods) { 570 | var name; 571 | for (name in methods) { 572 | functional[name] = functional[name] || (function (name) { 573 | var fn = methods[name]; 574 | return function (object) { 575 | return fn.apply(Function.toFunction(object), Array.slice(arguments,1)); 576 | } 577 | })(name); 578 | } 579 | } 580 | 581 | // _attachMethodDelegates(_initialFunctionPrototypeState.getChangedMethods()); 582 | // delete _initialFunctionPrototypeState; 583 | 584 | // Add functions to the "functional" namespace, 585 | // autoCurry() functions where appropriate 586 | functional.map = map.autoCurry(); 587 | functional.parallel = parallel; 588 | functional.compose = compose; 589 | functional.sequence = sequence; 590 | functional.memoize = memoize; 591 | functional.reduce = reduce.autoCurry(); 592 | functional.foldl = reduce.autoCurry(); 593 | functional.select = select.autoCurry(); 594 | functional.filter = select.autoCurry(); 595 | functional.guard = guard; 596 | functional.flip = flip; 597 | functional.foldr = foldr.autoCurry(); 598 | functional.and = and; 599 | functional.andd = and; // alias and() for coffescript 600 | functional.or = or; 601 | functional.orr = or; // alias or() for coffescript 602 | functional.some = some.autoCurry(); 603 | functional.every = every.autoCurry(); 604 | functional.not = not; 605 | functional.nott = not; // alias not() for coffeescript 606 | functional.equal = equal; 607 | functional.lambda = lambda; 608 | functional.invoke = invoke; 609 | functional.pluck = pluck.autoCurry(); 610 | functional.until = until.autoCurry(); 611 | functional.untill = until.autoCurry(); 612 | functional.zip = zip; 613 | functional.I = I; 614 | functional.id = I; 615 | functional.K = K; 616 | functional.constfn = K; 617 | functional.S = S; 618 | 619 | // Detect free variable "global" and use it as "window" 620 | if (freeGlobal.global === freeGlobal) { 621 | window = freeGlobal; 622 | } 623 | 624 | // Used to restore the original reference in "noConflict()" 625 | oldFunctional = window.functional; 626 | 627 | // Reverts the "functional" variable to its previous value and 628 | // returns a reference to the "functional" function. 629 | // example: 630 | // var functional = functional.noConflict(); 631 | functional.noConflict = function noConflict() { 632 | window.functional = oldFunctional; 633 | return this; 634 | } 635 | 636 | // Expose all functions to the global namespace, or specified environment 637 | functional.expose = function expose(env) { 638 | var fn; 639 | env = env || window; 640 | for (fn in functional) { 641 | if (fn !== 'expose' && functional.hasOwnProperty(fn)) { 642 | env[fn] = functional[fn]; 643 | } 644 | } 645 | }; 646 | 647 | functional.expose(); 648 | 649 | // Expose FunctionalJS library 650 | // Some AMD build optimizers, like r.js, check for specific condition 651 | // patterns like the following: 652 | if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { 653 | // Expose FunctionalJs to the global object even when an AMD loader 654 | // is present, in case FunctionalJS was injected by a third-party 655 | // script and not intended to be loaded as module. The global 656 | // assignment can be reverted in the FunctionalJS module via its 657 | // "noConflict()" method. 658 | window.functional = functional; 659 | 660 | // Define an anonymous AMD module 661 | define(function () { return functional; }); 662 | } 663 | 664 | // Check for "exports" after "define", in case a build optimizer adds 665 | // an "exports" object. 666 | else if (freeExports) { 667 | // Node.js or RingoJS v0.8.0+ 668 | if (typeof module == 'object' && module && module.exports == freeExports) { 669 | module.exports = functional; 670 | } 671 | // Narwhal or RingoJS v0.7.0- 672 | else { 673 | freeExports.functional = functional; 674 | } 675 | } 676 | 677 | }(this)); 678 | --------------------------------------------------------------------------------