diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..720efb3 --- /dev/null +++ b/.babelrc @@ -0,0 +1,5 @@ +{ + "plugins": [ + "transform-async-to-generator" + ] +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 4abc84e..0c88bfb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ +# +node_modules -.idea/functional.es.iml +# for IntelliJ IDE +.idea/*.iml .idea/markdown-navigator.xml .idea/markdown-navigator/profiles_settings.xml .idea/misc.xml @@ -7,6 +10,7 @@ .idea/vcs.xml .idea/watcherTasks.xml .idea/workspace.xml -articles/ES6, 함수형 프로그래밍, 비동기, 동시성 프로그래밍/html/.DS_Store -articles/ES6, 함수형 프로그래밍, 비동기, 동시성 프로그래밍/.DS_Store + +.DS_Store + *.zip diff --git a/functional.es.js b/functional.es.js index 136b17c..85cbed9 100644 --- a/functional.es.js +++ b/functional.es.js @@ -1,3 +1,5 @@ +let root = {}; + !function() { const curry2 = f => (..._) => _.length < 2 ? (..._2) => f(..._, ..._2) : f(..._); @@ -382,7 +384,6 @@ const sel = baseSel(' > '); - const root = typeof global == 'object' ? global : window; root.Functional = { curry2, flip, then, identity, noop, @@ -399,4 +400,10 @@ negate, complement, not, isAny, isUndefined, each, log, }; -} (); \ No newline at end of file +} (); + +if (typeof global == 'object') { + module.exports = root.Functional || {}; +} else { + window.Functional = root.Functional; +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..b42f48a --- /dev/null +++ b/package.json @@ -0,0 +1,35 @@ +{ + "name": "functional.es", + "version": "1.0.0", + "description": "ES6 +, Functional Programming, Asynchronous, Concurrent Programming", + "main": "functional.es.js", + "directories": { + "test": "test" + }, + "scripts": { + "test": "mocha -R spec --require babel-register test/**/*.js" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Functional-JavaScript/FunctionalES.git" + }, + "keywords": [ + "es6+", + "functional", + "programming", + "javascript" + ], + "author": "idy@marpple.com", + "license": "", + "bugs": { + "url": "https://github.com/Functional-JavaScript/FunctionalES/issues" + }, + "homepage": "https://github.com/Functional-JavaScript/FunctionalES#readme", + "devDependencies": { + "babel-cli": "^6.26.0", + "babel-plugin-transform-async-to-generator": "^6.24.1", + "babel-register": "^6.26.0", + "chai": "^4.1.2", + "mocha": "^5.1.0" + } +} diff --git a/test/common.spec.js b/test/common.spec.js new file mode 100644 index 0000000..936d49a --- /dev/null +++ b/test/common.spec.js @@ -0,0 +1,66 @@ +const expect = require('chai').expect +const { curry2, pipe } = require('../functional.es') + +describe('[ curry2 ]', function () { + it('curry2 는 함수를 반환한다.', () => { + const adder = curry2((a, b) => a + b) + expect(adder).to.be.a('function') + }) + + it('curry2 를 통해 반환된 함수는 인자가 1개이면 함수를, 1개보다 많으면 해당 함수를 실행한다.', () => { + const adder = curry2((a, b) => a + b) + const addWith5 = adder(5) + + expect(addWith5).to.be.a('function') + expect(addWith5(3)).to.eql(8) + expect(addWith5(5)).to.eql(10) + }) + + it('curry2 에 함수가 아닌 인자를 입력하는 경우 TypeError 가 발생할 수 있다.', () => { + const unknown = curry2('abc') + + expect(unknown).to.be.a('function') + expect(unknown(1)).to.be.a('function') + expect(() => unknown(1)(2)).to.throw(TypeError, 'Function.prototype.apply was called on abc, which is a string and not a function') + unknown(1)(2) + }) +}) + +describe('[ pipe ]', function () { + const add1 = a => a + 1 + const add1P = a => new Promise(resolve => setTimeout(() => resolve(a + 1), 1000)) + const mul2 = a => a * 2 + + it('pipe 는 인자로 받은 함수들을 순차적으로 실행하는 함수를 반환한다.', () => { + const f = pipe(add1, mul2) + + expect(f).to.be.a('function') + expect(f(1)).to.eql(4) + expect(f(2)).to.eql(6) + }) + + it('pipe 에 promise 를 반환하는 비동키 함수가 포함되는 경우 pipe 함수는 인자로 들어온 함수를 순차적으로 실행하지만 promise 를 반환한다.', async () => { + this.timeout(2000) + + const fP = pipe(add1P, mul2) + expect(fP).to.be.a('function') + + const p1 = fP(1) + const p2 = fP(2) + + expect(p1).to.be.a('Promise') + expect(p2).to.be.a('Promise') + + await p1.then(result => expect(result).to.eql(4)) + await p2.then(result => expect(result).to.eql(6)) + }) + + it('pipe 중간에 함수가 아닌 인자가 들어가는 경우 TypeError 가 발생할 수 있다.', () => { + const f = pipe(add1, mul2, 3) + + expect(f).to.be.a('function') + expect(() => f(1)).to.throw(TypeError, 'f is not a function') + expect(() => f(2)).to.throw(TypeError, 'f is not a function') + f(1) + }) +})