├── README.md └── node └── public ├── 1.html ├── 2.html ├── 3.html ├── 4.html ├── 5.html ├── 6.html ├── dom ├── fx.js └── fxjs-dom.js └── fxjs2 ├── C.js ├── Concurrency ├── callsC.js ├── catchNoop.js ├── dropC.js ├── everyC.js ├── filterC.js ├── findC.js ├── headC.js ├── mapC.js ├── mapEntriesC.js ├── objectC.js ├── reduceC.js ├── someC.js ├── tailC.js ├── take1C.js ├── takeAllC.js └── takeC.js ├── L.js ├── LICENSE ├── Lazy ├── deepFlatLazy.js ├── dropLazy.js ├── entriesLazy.js ├── filterLazy.js ├── flatLazy.js ├── flatMapLazy.js ├── headTailLazy.js ├── indexValuesLazy.js ├── intervalLazy.js ├── keysLazy.js ├── mapEntriesLazy.js ├── mapLazy.js ├── rangeLazy.js ├── rejectLazy.js ├── reverseLazy.js ├── takeLazy.js ├── takeUntilLazy.js ├── takeWhileLazy.js └── valuesLazy.js ├── README.md ├── baseCalls.js ├── baseExtend.js ├── basePick.js ├── baseSel.js ├── baseSortBy.js ├── call.js ├── calls.js ├── constant.js ├── countBy.js ├── curry.js ├── deepFlat.js ├── defaults.js ├── delay.js ├── drop.js ├── dropRight.js ├── each.js ├── empty.js ├── entries.js ├── every.js ├── extend.js ├── filter.js ├── find.js ├── findWhere.js ├── flat.js ├── flatMap.js ├── fx.js ├── go.js ├── go1.js ├── goS.js ├── groupBy.js ├── has.js ├── head.js ├── hi.js ├── identity.js ├── index.js ├── indexBy.js ├── isArray.js ├── isFunction.js ├── isIterable.js ├── isMatch.js ├── isStop.js ├── isString.js ├── isUndefined.js ├── keys.js ├── last.js ├── log.js ├── map.js ├── mapEntries.js ├── mapObject.js ├── match.js ├── max.js ├── maxBy.js ├── min.js ├── minBy.js ├── negate.js ├── noop.js ├── nop.js ├── not.js ├── object.js ├── omit.js ├── package.json ├── pick.js ├── pipe.js ├── pipeS.js ├── pluck.js ├── promiseAllEntries.js ├── promiseAllObject.js ├── range.js ├── reduce.js ├── reduceS.js ├── reject.js ├── safety.js ├── sel.js ├── some.js ├── sort.js ├── sortBy.js ├── sortByDesc.js ├── sortDesc.js ├── stop.js ├── stopIf.js ├── strMap.js ├── string.js ├── tail.js ├── take.js ├── take1.js ├── takeAll.js ├── takeUntil.js ├── takeWhile.js ├── tap.js ├── toIter.js ├── unique.js ├── uniqueBy.js └── values.js /README.md: -------------------------------------------------------------------------------- 1 | # 네이버 함수형 자바스크립트 강의 과정 2 | 3 | ## 과정 목표 4 | 함수형 프로그래밍과 이터러블 프로그래밍을 익힙니다. 이터러블 프로그래밍 혹은 Lisp(리스트 프로세싱)은 해결해야하는 문제를 리스트로 바라보고 해결하는 프로그래밍 기법이자 언어입니다. 함수형 프로그래밍과 이터러블 프로그래밍은 복잡한 문제를 작은 문제로 나누어 쉽게 해결하도록 하며 오류 없는 코드를 작성할 수 있게 합니다. 본 과정은 이러한 함수형 프로그래밍과 이터러블 프로그래밍을 깊이 다루고, 실무에는 어떻게 적용하는지 상세히 알아보는 과정입니다. 5 | 6 | ## 주요 내용 7 | - 함수형 프로그래밍의 실무 적용 사례 8 | - ES6-8의 주요 기능들과 응용 사례 9 | - 이터러블/이터레이터/제너레이터를 이용한 이터러블 프로그래밍 10 | - Promise/async/await를 이용한 비동기 동시성 프로그래밍 11 | - 에러 핸들링 12 | 13 | ## 참가 대상 14 | - 자바스크립트를 주 언어로 사용하고 있는 프론트엔드 개발자 15 | - Node.js를 사용하고 있는 백엔드 개발자 16 | - 함수형 프로그래밍/이터러블 프로그래밍에 관심이 있는 개발자 17 | - 타 언어로 함수형 프로그래밍을 하고 계신 분 18 | 19 | ## 과정 목차 20 | - 회당 3시간 총 9시간 21 | - 진행 일자 2019/04/12, 04/19, 04/26 22 | 23 | ### 1회 24 | - 명령형 코드를 이터러블 프로그래밍으로 바꾸기 25 | - 지연 평가 26 | - 안전한 합성 27 | 28 | ### 2회 29 | - 객체를 이터러블 프로그래밍으로 다루기 30 | - 커머스 데이터 다루기 31 | - SNS 서비스 데이터 다루기 32 | - 비동기/동시성 프로그래밍 33 | - 에러 핸들링 34 | 35 | ### 3회 36 | - 동시성 프로그래밍, 프론트엔드에서의 Promise 활용 37 | - 템플릿 리터럴 활용 38 | - 이미지 다루기 39 | - SQL 다루기 40 | - 시간을 이터러블로 다루기 41 | - 스케쥴러 만들기 -------------------------------------------------------------------------------- /node/public/1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 1 6 | 7 | 8 | 9 | # 이터레이터/이터러블/제너레이터 10 | 11 | 19 | 20 | # 명령형 코드를 이터러블 프로그래밍으로 바꾸기 21 | 22 | ## 명령형 홀수 n개 더하기 23 | 24 | 39 | 40 | ## 함수형 홀수 n개 더하기 41 | 42 | 91 | 92 | ## 관점 바꾸기 1 93 | - if를 filter로 94 | - 값 변화 후 변수 할당을 map으로 95 | - break를 take로 96 | - 축약 및 합산을 reduce로 97 | 98 | ## 관점 바꾸기2 99 | - while을 range로 100 | 101 | ### while 102 | 113 | 114 | ### range 115 | 139 | 140 | ## 관점 바꾸기3 141 | - 효과를 구분하여 each로 142 | 143 | 146 | 147 | # 일급을 이용한 합성 148 | 149 | 186 | 187 | # 지연 평가와 엄격한 평가 188 | 189 | 214 | 215 | # 2차원 배열 216 | 217 | 241 | 242 | # 리얼월드 243 | 244 | 273 | 274 | # 작은 함수들을 조합하여 함수 만들기 275 | 276 | ## pipe 277 | 278 | 287 | 288 | ## reject 289 | 290 | 298 | 299 | ## find, some, every 300 | 301 | 322 | 323 | # 이터러블을 활용한 안전하고 재밌는 합성 324 | 325 | ## map 326 | 327 | 341 | 342 | ## find 대신 filter take 343 | 344 | 369 | 370 | ## reduce + 복잡한 함수 + acc 보다 map + reduce 371 | 372 | 379 | 380 | ## reduce 하나보다 map filter reduce 381 | 382 | 396 | 397 | 447 | 448 | # 어떠한 값이든 이터러블로 다루기 - 이터러블 프로그래밍 혹은 리습 449 | 450 | ## 객체를 이터러블 프로그래밍으로 다루기 451 | 452 | ### values, entries, keys 453 | 454 | 497 | 498 | ### object 499 | 500 | 516 | 517 | ### mapObject 518 | 519 | 529 | 530 | ### pick 531 | 532 | 543 | 544 | ## Map, Set 545 | 546 | 564 | 565 | ## 사용자 정의 객체 566 | 567 | 632 | 633 | 634 | -------------------------------------------------------------------------------- /node/public/2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 2 6 | 7 | 8 | 9 | # 커머스 데이터 다루기 10 | 11 | 87 | 88 | # SNS 서비스 데이터 다루기 89 | 90 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /node/public/3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 3 6 | 7 | 8 | 9 | # 비동기/동시성 프로그래밍 10 | 11 | ## Promise의 규칙과 일급 12 | 13 | 32 | 33 | ## 일급 활용 34 | 35 | 75 | 76 | # 에러 핸들링 77 | 78 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /node/public/4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 4 6 | 108 | 114 | 115 | 116 | 117 | 123 | 124 | 225 | 226 | 227 | 228 | -------------------------------------------------------------------------------- /node/public/5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 5 6 | 7 | 8 | 9 | # SQL 다루기 10 | 11 | ## 함수형 사고 12 | 13 | 65 | 66 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /node/public/6.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 6 | 7 | 8 | 9 | # 시간을 이터러블로 다루기 10 | 11 | ## range 와 take 의 재해석 12 | 13 | 34 | 35 | ## 스케쥴러 만들기 36 | 37 | ## 아임포트 결제 누락 싱크 38 | - https://github.com/iamport/iamport-manual/blob/master/%EC%9D%B8%EC%A6%9D%EA%B2%B0%EC%A0%9C/README.md#23-notification-url%EA%B0%80%EC%83%81%EA%B3%84%EC%A2%8C-%EC%9E%85%EA%B8%88%ED%86%B5%EB%B3%B4-%ED%8F%AC%ED%95%A8 39 | - https://api.iamport.kr/ 40 | 41 | 93 | 94 | # 마치며 95 | - 강의 코드 https://github.com/indongyoo/NAVER-functional-javascript 96 | - '함수형 자바스크립트' 페북 그룹 https://www.facebook.com/groups/539983619537858 97 | - 마플 깃헙 https://github.com/marpple 98 | - 유인동 indong.yoo@gmail.com 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /node/public/dom/fx.js: -------------------------------------------------------------------------------- 1 | export const 2 | identity = a => a, 3 | 4 | noop = function() {}, 5 | 6 | nop = Symbol('nop'), 7 | 8 | not = a => !a, 9 | 10 | curry = f => 11 | (a, ..._) => _.length < 1 ? (..._) => f(a, ..._) : f(a, ..._), 12 | 13 | log = console.log, 14 | 15 | go1 = (a, f) => a instanceof Promise ? a.then(f) : f(a), 16 | 17 | negate = f => (..._) => go1(f(..._), not), 18 | 19 | constant = a => _ => a; 20 | 21 | export const 22 | isString = a => typeof a == 'string', 23 | 24 | is_string = isString, 25 | 26 | isFunction = a => typeof a == 'function', 27 | 28 | is_function = isFunction, 29 | 30 | isArray = Array.isArray, 31 | 32 | is_array = isArray, 33 | 34 | isUndefined = a => a === undefined, 35 | 36 | is_undefined = isUndefined, 37 | 38 | has = curry((k, obj) => obj.hasOwnProperty(k)), 39 | 40 | hasIter = a => !!(a && a[Symbol.iterator]); 41 | 42 | export const L = {}; 43 | 44 | function *_values(obj) { 45 | for (const k in obj) yield obj[k]; 46 | } 47 | L.values = a => hasIter(a) ? a[Symbol.iterator]() : _values(a); 48 | 49 | L.entries = function *(obj) { 50 | for (const k in obj) yield [k, obj[k]]; 51 | }; 52 | 53 | L.keys = function *(obj) { 54 | for (const k in obj) yield k; 55 | }; 56 | 57 | L.reverse = function *(arr) { 58 | var l = arr.length; 59 | while (l--) yield arr[l]; 60 | }; 61 | 62 | L.tail = function(coll) { 63 | var iter = L.values(coll); 64 | return go1(take(1, iter), _ => iter); 65 | }; 66 | 67 | L.headTail = L.head_tail = function(coll) { 68 | var iter = L.values(coll); 69 | return go1(take(1, iter), ([head]) => [head, iter]); 70 | }; 71 | 72 | L.range = function *(limit) { 73 | var i = -1; 74 | while (++i < limit) yield i; 75 | }; 76 | 77 | L.map = curry(function *(f, coll) { 78 | for (const a of L.values(coll)) yield go1(a, f); 79 | }); 80 | 81 | L.filter = curry(function *(f, coll) { 82 | for (const a of L.values(coll)) { 83 | const b = go1(a, f); 84 | if (b instanceof Promise) yield b.then(b => b ? a : Promise.reject(nop)); 85 | else if (b) yield a; 86 | } 87 | }); 88 | 89 | L.entriesMap = L.esMap = L.es_map = curry(function *(f, coll) { 90 | for (const [k, a] of L.values(coll)) yield go1(go1(a, f), b => [k, b]); 91 | }); 92 | 93 | L.reject = baseReject(L.filter); 94 | 95 | function baseReject(filter) { 96 | return curry((f, coll) => filter(pipe(f, not), coll)); 97 | } 98 | 99 | L.flat = L.flatten = function *(iter) { 100 | for (const a of iter) { 101 | if (hasIter(a)) yield *a; 102 | else yield a; 103 | } 104 | }; 105 | 106 | L.deepFlat = L.deep_flat = L.deepFlatten = L.deep_flatten = function *f(iter) { 107 | for (const a of iter) { 108 | if (typeof a != 'string' && hasIter(a)) yield *f(a); 109 | else yield a; 110 | } 111 | }; 112 | 113 | L.flatMap = L.flat_map = curry((f, iter) => L.flat(L.map(f, iter))); 114 | 115 | export const 116 | call = (f, a) => f(a), 117 | 118 | call2 = (a, f) => f(a); 119 | 120 | export const 121 | set = curry(([k, v], obj) => (obj[k] = v, obj)), 122 | 123 | set2 = curry((obj, kv) => (set(kv, obj), kv)), 124 | 125 | set3 = curry((obj, [k, v]) => (obj[k] = v, obj)); 126 | 127 | export const 128 | last = arr => arr[arr.length-1]; 129 | 130 | const reduceF = (acc, a, f) => 131 | a instanceof Promise ? 132 | a.then(a => f(acc, a), e => e == nop ? acc : Promise.reject(e)) : 133 | f(acc, a); 134 | 135 | export const 136 | reduce = curry(function(f, acc, iter) { 137 | if (arguments.length == 2) return reduce(f, head(iter = L.values(acc)), iter); 138 | 139 | iter = L.values(iter); 140 | return go1(acc, function recur(acc) { 141 | let cur; 142 | while (!(cur = iter.next()).done) { 143 | acc = reduceF(acc, cur.value, f); 144 | if (acc instanceof Promise) return acc.then(recur); 145 | } 146 | return acc; 147 | }); 148 | }), 149 | 150 | go = (..._) => reduce(call2, _), 151 | 152 | pipe = (f, ...fs) => (...as) => reduce(call2, f(...as), fs), 153 | 154 | tap = (f, ...fs) => (a, ...as) => go(reduce(call2, f(a, ...as), fs), _ => a), 155 | 156 | hi = tap(log), 157 | 158 | each = curry((f, coll) => go(reduce((_, a) => f(a), null, coll), _ => coll)); 159 | 160 | export const take = curry((l, iter) => { 161 | if (l === 0) return []; 162 | let res = []; 163 | iter = L.values(iter); 164 | return function recur() { 165 | let cur; 166 | while (!(cur = iter.next()).done) { 167 | const a = cur.value; 168 | if (a instanceof Promise) { 169 | return a 170 | .then(a => (res.push(a), res).length == l ? res : recur()) 171 | .catch(e => e == nop ? recur() : Promise.reject(e)); 172 | } 173 | res.push(a); 174 | if (res.length == l) return res; 175 | } 176 | return res; 177 | } (); 178 | }); 179 | 180 | export const 181 | takeAll = take(Infinity), 182 | 183 | take_all = takeAll, 184 | 185 | take1 = take(1); 186 | 187 | export const 188 | head = iter => go1(take1(iter), ([h]) => h), 189 | 190 | tail = coll => takeAll(L.tail(coll)); 191 | 192 | const baseCalls = (map, esMap) => (fs, ...args) => 193 | hasIter(fs) ? 194 | map(f => f(...args), fs) : 195 | object(esMap(f => f(...args), fs)); 196 | 197 | export const 198 | map = curry(pipe(L.map, takeAll)), 199 | 200 | esMap = curry(pipe(L.eMap, takeAll)), 201 | 202 | entriesMap = esMap, es_map = esMap, 203 | 204 | pluck = curry((k, coll) => map(a => a[k], coll)), 205 | 206 | calls = baseCalls(map, esMap); 207 | 208 | export const 209 | filter = curry(pipe(L.filter, takeAll)), 210 | 211 | reject = baseReject(filter); 212 | 213 | export const 214 | flatten = pipe(L.flatten, takeAll), 215 | 216 | flat = flatten, 217 | 218 | deepFlatten = pipe(L.deepFlatten, takeAll), 219 | 220 | deepFlat = deepFlatten, 221 | 222 | deep_flat = deepFlat, 223 | 224 | deep_flatten = deepFlat, 225 | 226 | flatMap = curry(pipe(L.map, flat)), 227 | 228 | flat_map = flatMap; 229 | 230 | export const 231 | uniqueBy = curry((f, coll) => { 232 | const s = new Set(); 233 | const imobj = !hasIter(coll); 234 | return go( 235 | coll, 236 | imobj ? L.entries : identity, 237 | filter(pipe( 238 | imobj ? last : identity, 239 | f, 240 | b => s.has(b) ? false : s.add(b))), 241 | imobj ? object : identity); 242 | }), 243 | 244 | unique_by = uniqueBy, 245 | 246 | unique = uniqueBy(a => a), 247 | 248 | uniq = unique, 249 | 250 | countBy = curry((f, coll) => 251 | reduce((counts, a) => incSel(counts, f(a)), {}, coll)), 252 | 253 | count_by = countBy, 254 | 255 | groupBy = curry((f, coll) => 256 | reduce((group, a) => pushSel(group, f(a), a), {}, coll)), 257 | 258 | group_by = groupBy, 259 | 260 | indexBy = curry((f, coll) => 261 | reduce((indexed, a) => set([f(a), a], indexed), {}, coll)), 262 | 263 | index_by = indexBy, 264 | 265 | maxBy = curry((f, coll) => 266 | reduce((a, b) => f(a) >= f(b) ? a : b, coll)), 267 | 268 | max_by = maxBy, 269 | 270 | max = maxBy(identity), 271 | 272 | minBy = curry((f, coll) => 273 | reduce((a, b) => f(a) <= f(b) ? a : b, coll)), 274 | 275 | min_by = minBy, 276 | 277 | min = maxBy(identity); 278 | 279 | function incSel(parent, k) { 280 | parent[k] ? parent[k]++ : parent[k] = 1; 281 | return parent; 282 | } 283 | 284 | function pushSel(parent, k, v) { 285 | (parent[k] || (parent[k] = [])).push(v); 286 | return parent; 287 | } 288 | 289 | export const 290 | find = curry(pipe(L.filter, head)), 291 | 292 | some = curry(pipe(L.filter, take1, _ => _.length == 1)), 293 | 294 | every = curry(pipe(L.reject, take1, _ => _.length == 0)); 295 | 296 | export const 297 | object = coll => reduce((obj, [k, v]) => (obj[k] = v, obj), {}, coll), 298 | 299 | entryMap = curry((f, [k, a]) => go1(f(a), b => [k, b])), 300 | 301 | eMap = entryMap, emap = eMap, 302 | 303 | entries = a => a ? Object.entries(a) : [], 304 | 305 | values = a => a ? Object.values(a) : [], 306 | 307 | keys = a => a ? Object.keys(a) : []; 308 | 309 | const basePick = filter => curry((ks, obj) => go( 310 | obj, 311 | L.entries, 312 | filter(([k]) => ks.includes(k)), 313 | object 314 | )); 315 | 316 | export const 317 | pick = basePick(L.filter), 318 | 319 | omit = basePick(L.reject); 320 | 321 | const baseExtend = set => tap((obj, ...objs) => { 322 | const type = typeof obj; 323 | if (obj && (type == 'object' || type == 'function')) reduce(reduce(set), obj, L.map(entries, objs)); 324 | }); 325 | 326 | export const 327 | extend = baseExtend(set3), 328 | 329 | defaults = baseExtend(tap((obj, kv) => has(kv[0], obj) || set3(obj, kv))); 330 | 331 | export const C = {}; 332 | 333 | const catchNoop = ([...arr]) => 334 | (arr.forEach(a => a instanceof Promise ? a.catch(noop) : a), arr); 335 | 336 | C.reduce = curry((f, acc, iter) => iter ? 337 | reduce(f, acc, catchNoop(iter)) : 338 | reduce(f, catchNoop(acc))); 339 | 340 | C.take = curry((l, iter) => take(l, catchNoop(iter))); 341 | 342 | C.takeAll = C.take(Infinity); 343 | 344 | C.map = curry(pipe(L.map, C.takeAll)); 345 | 346 | C.filter = curry(pipe(L.filter, C.takeAll)); 347 | 348 | C.entriesMap = C.esMap = C.es_map = curry(pipe(L.esMap, C.takeAll)); 349 | 350 | C.take1 = C.take(1); 351 | 352 | C.head = pipe(C.take1, ([a]) => a); 353 | 354 | C.tail = coll => C.takeAll(L.tail(coll)); 355 | 356 | C.find = curry(pipe(L.filter, C.head)); 357 | 358 | C.some = curry(pipe(L.filter, C.take1, _ => _.length == 1)); 359 | 360 | C.every = curry(pipe(L.reject, C.take1, _ => _.length == 0)); 361 | 362 | C.calls = baseCalls(C.map, C.esMap); 363 | 364 | export const 365 | isMatch = curry((a, b) => 366 | typeof a == 'function' ? !!a(b) 367 | : 368 | isArray(a) && isArray(b) ? every(v => b.includes(v), a) 369 | : 370 | typeof b == 'object' ? every(([k, v]) => b[k] == v, L.entries(a)) 371 | : 372 | a instanceof RegExp ? b.match(a) 373 | : 374 | a == b 375 | ), 376 | 377 | is_match = isMatch; 378 | 379 | export const 380 | findWhere = curry((w, coll) => find(isMatch(w), coll)), 381 | 382 | find_where = findWhere; 383 | 384 | function baseMatch(targets) { 385 | var cbs = []; 386 | 387 | function evl() { 388 | return go( 389 | targets, 390 | values, 391 | targets => 392 | go(cbs, 393 | find(pb => { return pb._case(...targets); }), 394 | pb => pb._body(...targets))); 395 | } 396 | 397 | function _case(f) { 398 | cbs.push({ _case: typeof f == 'function' ? pipe(...arguments) : isMatch(f) }); 399 | return _body; 400 | } 401 | _case.case = _case; 402 | 403 | function _body() { 404 | cbs[cbs.length-1]._body = pipe(...arguments); 405 | return _case; 406 | } 407 | 408 | _case.else = function() { 409 | _case(_=> true) (...arguments); 410 | return targets ? evl() : (...targets2) => ((targets = targets2), evl()); 411 | }; 412 | 413 | return _case; 414 | } 415 | 416 | export const match = (..._) => baseMatch(_); 417 | match.case = (..._) => baseMatch(null).case(..._); 418 | 419 | export const 420 | baseSel = sep => curry(function f(selector, acc) { 421 | return ( 422 | !selector ? 423 | acc 424 | : 425 | isArray(selector) ? 426 | reduce((acc, selector) => f(selector, acc), acc, selector) 427 | : 428 | typeof selector == 'object' || typeof selector == 'function' ? 429 | findWhere(selector, acc) 430 | : 431 | reduce( 432 | (acc, key, s = key[0]) => 433 | !acc ? acc : 434 | s == '#' ? findWhere({ id: key.substr(1) }, acc) : 435 | s == '[' || s == '{' ? findWhere(JSON.parse(key), acc) : 436 | acc[key], 437 | acc, 438 | selector.split(sep)) 439 | ); 440 | }), 441 | 442 | sel = baseSel('.'); 443 | 444 | export const scat = curry((f, coll) => 445 | reduce((a, b) => `${a}${b}`, '', L.map(f, coll))); 446 | 447 | const arrComparator = (arr) => (a, b) => { 448 | let i = -1; 449 | while (++i < arr.length) { 450 | const ai = a[arr[i]], bi = b[arr[i]]; 451 | if (ai === bi) continue; 452 | return ai < bi ? -1 : 1; 453 | } 454 | return 0; 455 | }; 456 | 457 | const baseSortBy = (left, right) => curry(function sortBy(f, arr) { 458 | return isArray(f) ? sortBy(arrComparator(f), arr) : 459 | typeof f == 'string' ? sortBy(a => a[f], arr) : 460 | f.length == 2 ? [...arr].sort(right == -1 ? pipe(f, n => n * -1) : f) : 461 | [...arr].sort((a, b, fa = f(a), fb = f(b)) => fa == fb ? 0 : fa < fb ? left : right) 462 | }); 463 | 464 | export const 465 | sortBy = baseSortBy(-1, 1), 466 | sort_by = sortBy, 467 | sortByDesc = baseSortBy(1, -1), 468 | sort_by_desc = sortByDesc, 469 | sort = sortBy(identity), 470 | sortDesc = sortByDesc(identity), 471 | sort_desc = sortDesc; -------------------------------------------------------------------------------- /node/public/dom/fxjs-dom.js: -------------------------------------------------------------------------------- 1 | // FxJS-DOM 0.0.12 2 | import { 3 | isUndefined, isArray, isString, 4 | head, 5 | curry, go, pipe, tap, 6 | each, map, 7 | defaults, 8 | L 9 | } from "./fx.js"; 10 | 11 | const $ = sel => document.querySelector(sel); 12 | 13 | $.all = sel => document.querySelectorAll(sel); 14 | export default $; 15 | 16 | const idCreator = _ => { 17 | var i = 0; 18 | return _ => 'fxdom-id-' + i++; 19 | }; 20 | 21 | const createId = idCreator(); 22 | 23 | const baseFind = qs => curry((sel, el) => { 24 | const id = el.id; 25 | el.id = id || createId(); 26 | const res = el[qs]('#' + el.id + (sel[0] == '&' ? sel.substr(1) : ' ' + sel)); 27 | if (!id) el.removeAttribute('id'); 28 | return res; 29 | }); 30 | 31 | $.find = baseFind('querySelector'); 32 | 33 | $.findAll = baseFind('querySelectorAll'); 34 | 35 | $.children = el => el.children; 36 | 37 | $.closest = curry((sel, el) => el.closest(sel)); 38 | 39 | const isEl = node => 40 | node && typeof node == 'object' && (node.nodeType == 1 || node.nodeType == 9); 41 | 42 | const nextOrPrevAll = (k, add) => function f(sel, el) { 43 | if (arguments.length == 1) { 44 | if (typeof sel == 'string') return el => f(sel, el); 45 | el = sel; 46 | sel = '*'; 47 | } 48 | let res = [], cur = el; 49 | while ((cur = cur[k])) if (isEl(cur) && $.is(sel, cur)) res[add](cur); 50 | return res; 51 | }; 52 | 53 | $.prevAll = nextOrPrevAll('previousSibling', 'unshift'); 54 | $.nextAll = nextOrPrevAll('nextSibling', 'push'); 55 | 56 | const nextOrPrev = k => function f(sel, el) { 57 | if (arguments.length == 1) { 58 | if (typeof sel == 'string') return el => f(sel, el); 59 | el = sel; 60 | sel = '*'; 61 | } 62 | let cur = el; 63 | while ((cur = cur[k]) && (!isEl(cur) || !$.is(sel, cur))) {} 64 | return cur; 65 | }; 66 | 67 | $.prev = nextOrPrev('previousSibling'); 68 | $.next = nextOrPrev('nextSibling'); 69 | 70 | const docEl = document.documentElement; 71 | const matches = docEl.matches || docEl.webkitMatchesSelector || docEl.mozMatchesSelector || docEl.msMatchesSelector; 72 | 73 | $.is = curry((sel, el) => el && matches.call(el, sel)); 74 | 75 | $.contains = curry((parent, child) => parent.contains(child)); 76 | 77 | const 78 | fragmentRE = /^\s*<(\w+|!)[^>]*>/, 79 | table = document.createElement('table'), 80 | tableRow = document.createElement('tr'), 81 | div = document.createElement('div'), 82 | containers = { 83 | 'tr': document.createElement('tbody'), 84 | 'tbody': table, 'thead': table, 'tfoot': table, 85 | 'td': tableRow, 'th': tableRow 86 | }; 87 | 88 | $.els = html => { 89 | html = html.trim(); 90 | const name = fragmentRE.test(html) && RegExp.$1; 91 | const container = containers[name] || div; 92 | container.innerHTML = html; 93 | return each($.remove, [...container.childNodes]); 94 | }; 95 | 96 | $.el = html => { 97 | html = html.trim(); 98 | return html[0] == '<' ? head($.els(html)) : document.createElement(html); 99 | }; 100 | 101 | $.append = curry((parent, child) => parent.appendChild(child)); 102 | 103 | $.prepend = curry((parent, child) => parent.insertBefore(child, parent.firstChild)); 104 | 105 | $.before = curry((after, before) => after.parentNode.insertBefore(before, after)); 106 | 107 | $.after = curry((before, after) => 108 | before.nextSibling ? $.before(before.nextSibling, after) : $.append(before.parentNode, after)); 109 | 110 | $.remove = el => el.parentNode.removeChild(el); 111 | 112 | $.text = el => el.textContent; 113 | 114 | $.setText = $.set_text = curry((text, el) => (el.textContent = text, el)); 115 | 116 | $.html = el => el.innerHTML; 117 | 118 | $.setHtml = $.set_html = curry((html, el) => (el.innerHTML = html, el)); 119 | 120 | $.outerHTML = el => el.outerHTML; 121 | 122 | $.setOuterHTML = $.set_outer_html = curry((html, el) => el.outerHTML = html); 123 | 124 | $.val = el => el.value; 125 | 126 | $.setVal = $.set_val = curry((value, el) => (el.value = value, el)); 127 | 128 | $.attr = curry((k, el) => el.getAttribute(k)); 129 | 130 | $.setAttr = $.set_attr = curry((kv, el) => ( 131 | isArray(kv) ? 132 | el.setAttribute(...kv) : 133 | each(kv => el.setAttribute(...kv), L.entries(kv)), el)); 134 | 135 | $.removeAttr = $.remove_attr = curry((k, el) => (el.removeAttribute(k), el)); 136 | 137 | var methodClass = method => curry((class_names, el) => ( 138 | each(cn => el.classList[method](cn), class_names.split(' ')), el 139 | )); 140 | 141 | $.addClass = $.add_class = methodClass('add'); 142 | $.removeClass = $.remove_class = methodClass('remove'); 143 | $.toggleClass = $.toggle_class = methodClass('toggle'); 144 | 145 | function baseScroll(el, val, prop, method) { 146 | el = el || window; 147 | var top = prop == "pageYOffset"; 148 | var win = el == window || el == document ? window : null; 149 | if (val == undefined) return win ? win[ prop ] : el[ method ]; 150 | if (win) win.scrollTo(!top ? val : win.pageXOffset, top ? val : win.pageYOffset); 151 | else el[method] = val; 152 | return el; 153 | } 154 | 155 | $.scrollTop = $.scroll_top = el => baseScroll(el, undefined, "pageYOffset", "scrollTop"); 156 | 157 | $.scrollLeft = $.scroll_left = el => baseScroll(el, undefined, "pageXOffset", "scrollLeft"); 158 | 159 | $.setScrollTop = $.set_scroll_top = (val, el) => baseScroll(el, val, "pageYOffset", "scrollTop"); 160 | 161 | $.setScrollLeft = $.set_scroll_left = (val, el) => baseScroll(el, val, "pageXOffset", "scrollLeft"); 162 | 163 | $.offset = el => { 164 | const rect = el.getBoundingClientRect(); 165 | return { 166 | top: rect.top + window.pageYOffset - docEl.clientTop, 167 | left: rect.left + window.pageXOffset - docEl.clientLeft 168 | }; 169 | }; 170 | 171 | const baseOnOff = method => (event, sel, f, ...opts) => tap(el => 172 | !isString(sel) ? 173 | el[method](event, sel, ...[f, ...opts]) : 174 | go(el, 175 | $.findAll(sel), 176 | each(el => el[method](event, f, ...opts))) 177 | ); 178 | 179 | $.on = baseOnOff('addEventListener'); 180 | $.off = baseOnOff('removeEventListener'); 181 | 182 | $.delegate = (event, sel, f) => tap(el => 183 | el.addEventListener(event, e => go( 184 | el, 185 | $.findAll(sel), 186 | L.filter(el => el.contains(e.target)), 187 | each(currentTarget => f(defaults({ originalEvent: e, currentTarget, delegateTarget: el }, e))) 188 | )) 189 | ); 190 | 191 | const me = 'MouseEvents'; 192 | const mouseEvents = { 193 | click: me, 194 | mousedown: me, 195 | mouseup: me, 196 | mousemove: me, 197 | }; 198 | 199 | $.trigger = function(event, props, el) { 200 | if (!el) { el = props; props = {}; } 201 | if (event == 'submit') return el.submit(), el; 202 | let e = document.createEvent(mouseEvents[event] || 'Events'); 203 | var bubbles = true; 204 | for (var name in props) (name == 'bubbles') ? (bubbles = !!props[name]) : (e[name] = props[name]); 205 | e.initEvent(event, bubbles, true); 206 | el.dispatchEvent(e); 207 | return el; 208 | }; 209 | 210 | $.focus = el => el.focus(); 211 | $.blur = el => el.blur(); 212 | 213 | const 214 | resJSON = res => res.ok ? res.json() : Promise.reject(res), 215 | 216 | fetchBaseOpt = { 217 | headers: { "Content-Type": "application/json" }, 218 | credentials: 'same-origin' 219 | }, 220 | 221 | fetchBaseOptF = headers => headers ? defaults({ 222 | headers: defaults(headers, fetchBaseOpt.headers) 223 | }, fetchBaseOpt) : fetchBaseOpt, 224 | 225 | fetchWithBody = method => curry((url, data, headers) => go( 226 | fetch(url, Object.assign({ 227 | method: method, 228 | body: JSON.stringify(data) 229 | }, fetchBaseOptF(headers))), 230 | resJSON)); 231 | 232 | $.get = curry((url, data, headers) => go( 233 | fetch(url + (data === undefined ? '' : '?' + $.param(data)), fetchBaseOptF(headers)), 234 | resJSON 235 | )); 236 | 237 | $.post = fetchWithBody('POST'); 238 | $.put = fetchWithBody('PUT'); 239 | $.delete = fetchWithBody('DELETE'); 240 | 241 | $.post_form = curry((url, form_el) => go( 242 | new FormData(form_el), 243 | form => fetch(url, { method: 'POST', body: form }), 244 | res => res.ok ? res.json() : Promise.reject(res), 245 | )); 246 | 247 | $.param = pipe( 248 | L.entries, 249 | L.reject(([_, a]) => isUndefined(a)), 250 | L.map(map(encodeURIComponent)), 251 | map(([k, v]) => `${k}=${v}`), 252 | strs => strs.join('&').replace(/%20/g, '+')); 253 | 254 | const dataMap = new WeakMap(); 255 | 256 | $.setData = $.set_data = curry((data, el) => { 257 | dataMap.set(el, data); 258 | return el; 259 | }); 260 | 261 | $.data = el => { 262 | if (dataMap.has(el)) return dataMap.get(el); 263 | $.setData(JSON.parse($.attr('fxd-data', el)), el); 264 | $.setAttr(['fxd-data', 'IN_WEAK_MAP'], el); 265 | return dataMap.get(el); 266 | }; 267 | 268 | const toCamel = str => str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()); 269 | 270 | $.css = curry((k, el) => 271 | typeof k == 'string' ? 272 | el.style[k] || el.ownerDocument.defaultView.getComputedStyle(el, null)[toCamel(k)] : 273 | /* isArray(k) ? */ 274 | object(L.map(k => [k, $.css(k, el)], k))); 275 | 276 | var numberTypes = { 277 | "animationIterationCount": true, 278 | "columnCount": true, 279 | "fillOpacity": true, 280 | "flexGrow": true, 281 | "flexShrink": true, 282 | "fontWeight": true, 283 | "lineHeight": true, 284 | "opacity": true, 285 | "order": true, 286 | "orphans": true, 287 | "widows": true, 288 | "zIndex": true, 289 | "zoom": true 290 | }; 291 | 292 | const isNumeric = n => !isNaN(parseFloat(n)) && isFinite(n); 293 | 294 | const addPx = (k, v) => numberTypes[k] ? v : isNumeric(v) ? v + 'px' : v; 295 | 296 | $.setCss = $.set_css = curry((kv, el) => { 297 | if (isArray(kv)) { 298 | const k = toCamel(kv[0]); 299 | el.style[k] = addPx(k, kv[1]); 300 | } else { 301 | each(kv => $.setCss(kv, el), L.entries(kv)); 302 | } 303 | return el; 304 | }); 305 | 306 | const docWidth = (isHeight, b = document.body) => 307 | isHeight ? 308 | Math.max(b.offsetHeight, b.scrollHeight, docEl.offsetHeight, docEl.offsetHeight, docEl.clientHeight) : 309 | Math.max(b.offsetWidth, b.scrollWidth, docEl.offsetWidth, docEl.offsetWidth, docEl.clientWidth); 310 | 311 | const cssF = (k, el) => parseFloat($.css(k, el)) || 0; 312 | 313 | function elWidth(el, prefix = '', isHeight) { 314 | if (isHeight) var width = 'height', Left = 'Top', Right = 'Bottom'; 315 | else width = 'width', Left = 'Left', Right = 'Right'; 316 | 317 | const hide = $.css('display', el) == 'none' && $.show(el); 318 | 319 | let res = cssF(width, el); 320 | const isBorderBox = $.css('boxSizing', el) == 'border-box'; 321 | const borderBoxVal = (prefix && !isBorderBox) || (!prefix && isBorderBox) ? 322 | cssF('border'+Left+'Width', el) + 323 | cssF('border'+Right+'Width', el) + 324 | cssF('padding'+Left, el) + 325 | cssF('padding'+Right, el) : 0; 326 | res += prefix ? borderBoxVal : -borderBoxVal; 327 | if (prefix == 'outer') res += cssF('margin'+Left, el) + cssF('margin'+Right, el); 328 | 329 | hide && $.hide(el); 330 | 331 | return res; 332 | } 333 | 334 | $.width = el => el == window ? el.innerWidth : el == document ? docWidth() : elWidth(el); 335 | $.innerWidth = $.inner_width = el => elWidth(el, 'inner'); 336 | $.outerWidth = $.outer_width = el => elWidth(el, 'outer'); 337 | 338 | $.height = el => el == window ? el.innerHeight : el == document ? docWidth(true) : elWidth(el, '', true); 339 | $.innerHeight = $.inner_height = el => elWidth(el, 'inner', true); 340 | $.outerHeight = $.outer_height = el => elWidth(el, 'outer', true); 341 | 342 | const defaultDisplays = {}; 343 | function getDefaultDisplays(el) { 344 | var nodeName = el.nodeName, display = defaultDisplays[nodeName]; 345 | if (display) return display; 346 | 347 | var temp, doc = el.ownerDocument; 348 | temp = doc.body.appendChild(doc.createElement(nodeName)); 349 | display = $.css('display', temp); 350 | temp.parentNode.removeChild(temp); 351 | 352 | if (display == 'none') display = 'block'; 353 | return defaultDisplays[nodeName] = display; 354 | } 355 | 356 | const prevDisplays = new WeakMap(); 357 | 358 | $.show = el => { 359 | if (el.style.display == 'none') el.style.display = ''; 360 | if ($.css('display', el) == 'none') el.style.display = getDefaultDisplays(el); 361 | return el; 362 | }; 363 | 364 | $.hide = el => { 365 | const prev_display = $.css('display', el); 366 | if (prev_display != 'none') { 367 | prevDisplays.set(el, prev_display); 368 | el.style.display = 'none'; 369 | } 370 | return el; 371 | }; 372 | 373 | $.toggle = el => $.css('display', el) == 'none' ? $.show(el) : $.hide(el); -------------------------------------------------------------------------------- /node/public/fxjs2/C.js: -------------------------------------------------------------------------------- 1 | import tailC from './Concurrency/tailC.js'; 2 | import reduceC from './Concurrency/reduceC.js'; 3 | import takeC from './Concurrency/takeC.js'; 4 | import mapEntriesC from './Concurrency/mapEntriesC.js'; 5 | import findC from './Concurrency/findC.js'; 6 | import mapC from './Concurrency/mapC.js'; 7 | import everyC from './Concurrency/everyC.js'; 8 | import filterC from './Concurrency/filterC.js'; 9 | import takeAllC from './Concurrency/takeAllC.js'; 10 | import headC from './Concurrency/headC.js'; 11 | import take1C from './Concurrency/take1C.js'; 12 | import callsC from './Concurrency/callsC.js'; 13 | import someC from './Concurrency/someC.js'; 14 | import dropC from "./Concurrency/dropC.js"; 15 | 16 | const C = { 17 | tail: tailC, 18 | reduce: reduceC, 19 | take: takeC, 20 | mapEntries: mapEntriesC, 21 | map_entries: mapEntriesC, 22 | entriesMap: mapEntriesC, 23 | entries_map: mapEntriesC, 24 | find: findC, 25 | map: mapC, 26 | every: everyC, 27 | filter: filterC, 28 | takeAll: takeAllC, 29 | take_all: takeAllC, 30 | head: headC, 31 | take1: take1C, 32 | calls: callsC, 33 | some: someC, 34 | drop: dropC 35 | }; 36 | 37 | export { 38 | C, 39 | tailC, 40 | reduceC, 41 | takeC, 42 | mapEntriesC, 43 | findC, 44 | mapC, 45 | everyC, 46 | filterC, 47 | takeAllC, 48 | headC, 49 | take1C, 50 | callsC, 51 | someC, 52 | dropC 53 | } -------------------------------------------------------------------------------- /node/public/fxjs2/Concurrency/callsC.js: -------------------------------------------------------------------------------- 1 | import baseCalls from "../baseCalls.js"; 2 | import mapC from "./mapC.js"; 3 | import objectC from "./objectC.js"; 4 | 5 | export default baseCalls(mapC, objectC); -------------------------------------------------------------------------------- /node/public/fxjs2/Concurrency/catchNoop.js: -------------------------------------------------------------------------------- 1 | export function catchNoop(arr) { 2 | arr.forEach(a => a instanceof Promise ? a.catch(function() {}) : a); 3 | return arr; 4 | } 5 | 6 | export default catchNoop; -------------------------------------------------------------------------------- /node/public/fxjs2/Concurrency/dropC.js: -------------------------------------------------------------------------------- 1 | import curry from "../curry.js"; 2 | import catchNoop from "./catchNoop.js"; 3 | import drop from "../drop.js"; 4 | 5 | export default curry(function dropC(l, iter) { 6 | return drop(l, catchNoop([...iter])); 7 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/Concurrency/everyC.js: -------------------------------------------------------------------------------- 1 | import take1C from "./take1C.js"; 2 | import curry from "../curry.js"; 3 | import rejectLazy from "../Lazy/rejectLazy.js"; 4 | import go1 from "../go1.js"; 5 | 6 | export default curry(function everyC(f, iter) { 7 | return go1(take1C(rejectLazy(f, iter)), ({length}) => length == 0); 8 | });; -------------------------------------------------------------------------------- /node/public/fxjs2/Concurrency/filterC.js: -------------------------------------------------------------------------------- 1 | import filterLazy from "../Lazy/filterLazy.js"; 2 | import takeAllC from "./takeAllC.js"; 3 | import curry from "../curry.js"; 4 | 5 | export default curry(function filterC(f, iter) { 6 | return takeAllC(filterLazy(f, iter)); 7 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/Concurrency/findC.js: -------------------------------------------------------------------------------- 1 | import curry from "../curry.js"; 2 | import filterLazy from "../Lazy/filterLazy.js"; 3 | import headC from "./headC.js"; 4 | 5 | export default curry(function findC(f, iter) { 6 | return headC(filterLazy(f, iter)); 7 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/Concurrency/headC.js: -------------------------------------------------------------------------------- 1 | import takeC from "./takeC.js"; 2 | import go1 from "../go1.js"; 3 | 4 | export default function headC(iter) { 5 | return go1(takeC(1, iter), ([h]) => h); 6 | } -------------------------------------------------------------------------------- /node/public/fxjs2/Concurrency/mapC.js: -------------------------------------------------------------------------------- 1 | import mapLazy from "../Lazy/mapLazy.js"; 2 | import takeAllC from "./takeAllC.js"; 3 | import curry from "../curry.js"; 4 | 5 | export default curry(function mapC(f, iter) { 6 | return takeAllC(mapLazy(f, iter)); 7 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/Concurrency/mapEntriesC.js: -------------------------------------------------------------------------------- 1 | import mapEntriesLazy from "../Lazy/mapEntriesLazy.js"; 2 | import takeAllC from "./takeAllC.js"; 3 | import curry from "../curry.js"; 4 | 5 | export default curry(async function mapEntriesC(f, iter) { 6 | return takeAllC(mapEntriesLazy(f, iter)); 7 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/Concurrency/objectC.js: -------------------------------------------------------------------------------- 1 | import reduceC from "./reduceC.js"; 2 | 3 | export default function objectC(iter) { 4 | return reduceC((obj, [k, v]) => (obj[k] = v, obj), {}, iter); 5 | } -------------------------------------------------------------------------------- /node/public/fxjs2/Concurrency/reduceC.js: -------------------------------------------------------------------------------- 1 | import reduce from "../reduce.js"; 2 | import catchNoop from "./catchNoop.js"; 3 | import curry from "../curry.js"; 4 | 5 | export default curry(function reduceC(f, acc, iter) { 6 | return arguments.length == 2 ? 7 | reduce(f, catchNoop([...acc])) : 8 | reduce(f, acc, catchNoop([...iter])); 9 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/Concurrency/someC.js: -------------------------------------------------------------------------------- 1 | import take1C from "./take1C.js"; 2 | import curry from "../curry.js"; 3 | import filterLazy from "../Lazy/filterLazy.js"; 4 | import go1 from "../go1.js"; 5 | 6 | export default curry(function someC(f, iter) { 7 | return go1(take1C(filterLazy(f, iter)), ({length}) => length == 1); 8 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/Concurrency/tailC.js: -------------------------------------------------------------------------------- 1 | import dropC from "./dropC.js"; 2 | 3 | export default function tailC(iter) { 4 | return dropC(1, iter); 5 | } -------------------------------------------------------------------------------- /node/public/fxjs2/Concurrency/take1C.js: -------------------------------------------------------------------------------- 1 | import takeC from "./takeC.js"; 2 | 3 | export default takeC(1); -------------------------------------------------------------------------------- /node/public/fxjs2/Concurrency/takeAllC.js: -------------------------------------------------------------------------------- 1 | import takeC from "./takeC.js"; 2 | 3 | export default takeC(Infinity); -------------------------------------------------------------------------------- /node/public/fxjs2/Concurrency/takeC.js: -------------------------------------------------------------------------------- 1 | import curry from "../curry.js"; 2 | import catchNoop from "./catchNoop.js"; 3 | import take from "../take.js"; 4 | 5 | export default curry(function takeC(l, iter) { 6 | return take(l, catchNoop([...iter])); 7 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/L.js: -------------------------------------------------------------------------------- 1 | import deepFlatLazy from './Lazy/deepFlatLazy.js'; 2 | import entriesLazy from './Lazy/entriesLazy.js'; 3 | import mapEntriesLazy from './Lazy/mapEntriesLazy.js'; 4 | import filterLazy from './Lazy/filterLazy.js'; 5 | import flatLazy from './Lazy/flatLazy.js'; 6 | import flatMapLazy from './Lazy/flatMapLazy.js'; 7 | import headTailLazy from './Lazy/headTailLazy.js'; 8 | import indexValuesLazy from './Lazy/indexValuesLazy.js'; 9 | import keysLazy from './Lazy/keysLazy.js'; 10 | import mapLazy from './Lazy/mapLazy.js'; 11 | import rangeLazy from './Lazy/rangeLazy.js'; 12 | import rejectLazy from './Lazy/rejectLazy.js'; 13 | import reverseLazy from './Lazy/reverseLazy.js'; 14 | import valuesLazy from './Lazy/valuesLazy.js'; 15 | import takeLazy from './Lazy/takeLazy.js'; 16 | import takeWhileLazy from './Lazy/takeWhileLazy.js'; 17 | import takeUntilLazy from './Lazy/takeUntilLazy.js'; 18 | import intervalLazy from './Lazy/intervalLazy.js'; 19 | import dropLazy from "./Lazy/dropLazy.js"; 20 | 21 | const L = { 22 | deepFlat: deepFlatLazy, 23 | deep_flat: deepFlatLazy, 24 | deepFlatten: deepFlatLazy, 25 | deep_flatten: deepFlatLazy, 26 | entries: entriesLazy, 27 | entriesMap: mapEntriesLazy, 28 | entries_map: mapEntriesLazy, 29 | mapEntries: mapEntriesLazy, 30 | map_entries: mapEntriesLazy, 31 | filter: filterLazy, 32 | flat: flatLazy, 33 | flatMap: flatMapLazy, 34 | flat_map: flatMapLazy, 35 | headTail: headTailLazy, 36 | indexValues: indexValuesLazy, 37 | index_values: indexValuesLazy, 38 | keys: keysLazy, 39 | map: mapLazy, 40 | range: rangeLazy, 41 | reject: rejectLazy, 42 | reverse: reverseLazy, 43 | values: valuesLazy, 44 | take: takeLazy, 45 | takeWhile: takeWhileLazy, 46 | take_while: takeWhileLazy, 47 | takeUntil: takeUntilLazy, 48 | take_until: takeUntilLazy, 49 | interval: intervalLazy, 50 | drop: dropLazy 51 | }; 52 | 53 | export { 54 | L, 55 | deepFlatLazy, 56 | entriesLazy, 57 | mapEntriesLazy, 58 | filterLazy, 59 | flatLazy, 60 | flatMapLazy, 61 | headTailLazy, 62 | indexValuesLazy, 63 | keysLazy, 64 | mapLazy, 65 | rangeLazy, 66 | rejectLazy, 67 | reverseLazy, 68 | valuesLazy, 69 | takeLazy, 70 | takeWhileLazy, 71 | takeUntilLazy, 72 | intervalLazy, 73 | dropLazy 74 | } -------------------------------------------------------------------------------- /node/public/fxjs2/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 MARPPLE 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /node/public/fxjs2/Lazy/deepFlatLazy.js: -------------------------------------------------------------------------------- 1 | import flatLazy from "./flatLazy.js"; 2 | 3 | export default function deepFlatLazy(iter) { 4 | return flatLazy(iter, Infinity); 5 | } -------------------------------------------------------------------------------- /node/public/fxjs2/Lazy/dropLazy.js: -------------------------------------------------------------------------------- 1 | import curry from "../curry.js"; 2 | import safety from "../safety.js"; 3 | import nop from "../nop.js"; 4 | 5 | export default curry(function *dropLazy(l, iter) { 6 | if (l < 1) return yield *safety(iter); 7 | for (const a of safety(iter)) { 8 | if (a instanceof Promise) yield a.then(a => l ? (l--, Promise.reject(nop)) : a); 9 | else if (l) { l--; continue; } 10 | else yield a; 11 | } 12 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/Lazy/entriesLazy.js: -------------------------------------------------------------------------------- 1 | export default function *entriesLazy(obj) { 2 | for (const k in obj) yield [k, obj[k]]; 3 | } -------------------------------------------------------------------------------- /node/public/fxjs2/Lazy/filterLazy.js: -------------------------------------------------------------------------------- 1 | import curry from "../curry.js"; 2 | import go1 from "../go1.js"; 3 | import nop from "../nop.js"; 4 | import safety from "../safety.js"; 5 | 6 | export default curry(function *filterLazy(f, iter) { 7 | for (const a of safety(iter)) { 8 | const b = go1(a, f); 9 | if (b instanceof Promise) yield b.then(b => b ? a : Promise.reject(nop)); 10 | else if (b) yield a; 11 | } 12 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/Lazy/flatLazy.js: -------------------------------------------------------------------------------- 1 | import isIterable from "../isIterable.js"; 2 | import last from "../last.js"; 3 | import toIter from "../toIter.js"; 4 | import nop from "../nop.js"; 5 | 6 | export default function flatLazy(iter, depth = 1) { 7 | const iterStack = [toIter(iter)]; 8 | return { 9 | next: function recur() { 10 | const iter = last(iterStack); 11 | if (!iter) return { done: true }; 12 | const cur = iter.next(); 13 | if (cur.done) { 14 | iterStack.pop(); 15 | return recur(); 16 | } else if (iterStack.length <= depth && isIterable(cur.value) && typeof cur.value != 'string') { 17 | iterStack.push(cur.value[Symbol.iterator]()); 18 | return recur(); 19 | } else if (cur.value instanceof Promise) { 20 | return { 21 | value: cur.value.then(value => { 22 | if (iterStack.length > depth || !isIterable(value) || typeof value == 'string') return value; 23 | const iter = value[Symbol.iterator](), cur = iter.next(); 24 | return cur.done ? Promise.reject(nop) : (iterStack.push(iter), cur.value); 25 | }), 26 | done: false 27 | }; 28 | } else { 29 | return cur; 30 | } 31 | }, 32 | [Symbol.iterator]() { return this; } 33 | }; 34 | } -------------------------------------------------------------------------------- /node/public/fxjs2/Lazy/flatMapLazy.js: -------------------------------------------------------------------------------- 1 | import curry from "../curry.js"; 2 | import flatLazy from "./flatLazy.js"; 3 | import mapLazy from "./mapLazy.js"; 4 | 5 | export default curry(function flatMapLazy(f, iter) { 6 | return flatLazy(mapLazy(f, iter)); 7 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/Lazy/headTailLazy.js: -------------------------------------------------------------------------------- 1 | import toIter from "../toIter.js"; 2 | import go1 from "../go1.js"; 3 | import take from "../take.js"; 4 | 5 | export default function headTailLazy(iter) { 6 | return go1(take(1, iter = toIter(iter)), ([head]) => [head, iter]); 7 | } -------------------------------------------------------------------------------- /node/public/fxjs2/Lazy/indexValuesLazy.js: -------------------------------------------------------------------------------- 1 | import safety from "../safety.js"; 2 | 3 | export default function *indexValuesLazy(iter) { 4 | let i = -1; 5 | for (const a of safety(iter)) yield [++i, a]; 6 | }; -------------------------------------------------------------------------------- /node/public/fxjs2/Lazy/intervalLazy.js: -------------------------------------------------------------------------------- 1 | import delay from "../delay.js"; 2 | import mapLazy from "./mapLazy.js"; 3 | import rangeLazy from "./rangeLazy.js"; 4 | 5 | export default function intervalLazy(time) { 6 | return mapLazy(delay(time), rangeLazy(Infinity)); 7 | } -------------------------------------------------------------------------------- /node/public/fxjs2/Lazy/keysLazy.js: -------------------------------------------------------------------------------- 1 | export default function *keysLazy(obj) { 2 | for (const k in obj) yield k; 3 | }; -------------------------------------------------------------------------------- /node/public/fxjs2/Lazy/mapEntriesLazy.js: -------------------------------------------------------------------------------- 1 | import curry from "../curry.js"; 2 | import go1 from "../go1.js"; 3 | import safety from "../safety.js"; 4 | 5 | export default curry(function *mapEntriesLazy(f, iter) { 6 | for (const [k, a] of safety(iter)) yield go1(go1(a, f), b => [k, b]); 7 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/Lazy/mapLazy.js: -------------------------------------------------------------------------------- 1 | import curry from '../curry.js'; 2 | import go1 from '../go1.js'; 3 | import safety from "../safety.js"; 4 | 5 | export default curry(function *mapLazy(f, iter) { 6 | for (const a of safety(iter)) yield go1(a, f); 7 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/Lazy/rangeLazy.js: -------------------------------------------------------------------------------- 1 | export default function *rangeLazy(start = 0, stop = start, step = 1) { 2 | if (arguments.length == 1) start = 0; 3 | while (start < stop) { 4 | yield start; 5 | start += step; 6 | } 7 | } -------------------------------------------------------------------------------- /node/public/fxjs2/Lazy/rejectLazy.js: -------------------------------------------------------------------------------- 1 | import filterLazy from "./filterLazy.js"; 2 | import curry from "../curry.js"; 3 | import go1 from "../go1.js"; 4 | import not from "../not.js"; 5 | 6 | export default curry(function rejectLazy(f, iter) { 7 | return filterLazy(a => go1(f(a), not), iter); 8 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/Lazy/reverseLazy.js: -------------------------------------------------------------------------------- 1 | export default function *reverseLazy(arr) { 2 | var l = arr.length; 3 | while (l--) yield arr[l]; 4 | } -------------------------------------------------------------------------------- /node/public/fxjs2/Lazy/takeLazy.js: -------------------------------------------------------------------------------- 1 | import curry from "../curry.js"; 2 | import safety from "../safety.js"; 3 | 4 | export default curry(function *takeLazy(l, iter) { 5 | if (l < 1) return; 6 | for (const a of safety(iter)) { 7 | if (a instanceof Promise) yield a.then(a => (--l, a)); 8 | else yield (--l, a); 9 | if (!l) break; 10 | } 11 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/Lazy/takeUntilLazy.js: -------------------------------------------------------------------------------- 1 | import curry from "../curry.js"; 2 | import go1 from "../go1.js"; 3 | import safety from "../safety.js"; 4 | 5 | export default curry(function *takeUntilLazy(f, iter) { 6 | let ok = false; 7 | for (const a of safety(iter)) { 8 | ok = go1(a, f); 9 | if (ok instanceof Promise) yield ok.then(_ok => ((ok = _ok), a)); 10 | else yield a; 11 | if (ok) break; 12 | } 13 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/Lazy/takeWhileLazy.js: -------------------------------------------------------------------------------- 1 | import curry from "../curry.js"; 2 | import nop from "../nop.js"; 3 | import go1 from "../go1.js"; 4 | import safety from "../safety.js"; 5 | 6 | export default curry(function *takeWhileLazy(f, iter) { 7 | let ok = false; 8 | for (const a of safety(iter)) { 9 | ok = go1(a, f); 10 | if (ok instanceof Promise) yield ok.then(_ok => (ok = _ok) ? a : Promise.reject(nop)); 11 | else if (ok) yield a; 12 | if (!ok) break; 13 | } 14 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/Lazy/valuesLazy.js: -------------------------------------------------------------------------------- 1 | export default function *valuesLazy(obj) { 2 | for (const k in obj) yield obj[k]; 3 | } -------------------------------------------------------------------------------- /node/public/fxjs2/README.md: -------------------------------------------------------------------------------- 1 | [EN](https://github.com/marpple/FxJS) | [KR](https://github.com/marpple/FxJS/blob/master/README_kr.md) 2 | 3 | ## FxJS - Functional Extensions for Javascript 4 | 5 | FxJS is a functional programming library that uses basic JavaScript values ​​and emphasizes repeatable programming and Promise. 6 | 7 | ### iterable 8 | 9 | ```javascript 10 | const res = go( 11 | L.range(Infinity), 12 | L.filter(a => a % 2), 13 | L.take(3), 14 | reduce(add)); 15 | 16 | log(res); // 9 17 | ``` 18 | 19 | ### iterable + time 20 | 21 | ```javascript 22 | go( 23 | L.range(Infinity), 24 | L.map(delay(1000)), 25 | L.map(a => a + 10), 26 | L.take(3), 27 | each(log)); 28 | // After 1 second 10 29 | // After 2 seconds 11 30 | // After 3 seconds 12 31 | ``` 32 | 33 | ### iterable + time + Promise 34 | 35 | ```javascript 36 | // L.interval = time => L.map(delay(time), L.range(Infinity)); 37 | 38 | (async () => { 39 | await go( 40 | L.interval(1000), 41 | L.map(a => a + 30), 42 | L.takeUntil(a => a == 33), 43 | each(log)); 44 | // After 1 second 30 45 | // After 2 seconds 31 46 | // After 3 seconds 32 47 | // After 4 seconds 33 48 | 49 | const res = await go( 50 | L.interval(1000), 51 | L.map(a => a + 20), 52 | L.takeWhile(a => a < 23), 53 | L.map(tap(log)), 54 | reduce(add)); 55 | // After 5 seconds 20 56 | // After 6 seconds 21 57 | // After 7 seconds 22 58 | 59 | log(res); 60 | // 63 61 | } ()); 62 | ``` 63 | 64 | ### Install 65 | 66 | ``` 67 | npm i fxjs2 68 | ``` 69 | 70 | ### API 71 | 72 | - [map](#map) 73 | - [filter](#filter) 74 | - [reduce](#reduce) 75 | - [take](#take) 76 | - [L.map](#L.map) 77 | - [L.filter](#L.filter) 78 | - [go + try catch + Asynchronous error handling](#go--try-catch--Asynchronous-error-handling) 79 | - [stop](#stop) 80 | 81 | #### map 82 | 83 | ```javascript 84 | map(a => a + 10, [1, 2, 3]); 85 | // [11, 12, 13] 86 | ``` 87 | 88 | #### filter 89 | 90 | ```javascript 91 | filter(a => a % 2, [1, 2, 3]); 92 | // [1, 3] 93 | ``` 94 | 95 | #### reduce 96 | 97 | ```javascript 98 | const add = (a, b) => a + b 99 | reduce(add, [1, 2, 3]); 100 | // 6 101 | 102 | reduce(add, 10, [1, 2, 3]); 103 | // 16 104 | 105 | reduce(add, {a: 1, b: 2, c: 3}); 106 | // 6 107 | 108 | await reduce(add, [Promise.resolve(1), 2, 3]) 109 | // 6 110 | ``` 111 | 112 | #### take 113 | 114 | ```javascript 115 | take(1, [1, 2, 3]); 116 | // [1] 117 | 118 | take(2, [1, 2, 3]) 119 | // [1, 2] 120 | ``` 121 | 122 | #### L.map 123 | 124 | ```javascript 125 | const iterator = L.map(a => a + 10, [1, 2, 3]); 126 | take(2, iterator); 127 | // [11, 12] 128 | ``` 129 | 130 | #### L.filter 131 | 132 | ```javascript 133 | const iterator = L.filter(a => a % 2, [1, 2, 3, 4, 5]); 134 | take(2, iterator); 135 | // [1, 3] 136 | ``` 137 | 138 | ```javascript 139 | const iterator = L.filter(a => a % 2, L.map(a => a + 10, [1, 2, 3, 4, 5])); 140 | take(2, iterator); 141 | // [11, 13] 142 | ``` 143 | 144 | #### go + try catch + Asynchronous error handling 145 | 146 | ```javascript 147 | const b = go( 148 | 0, 149 | a => a + 1, 150 | a => a + 10, 151 | a => a + 100); 152 | 153 | console.log(b); 154 | // 111 155 | 156 | try { 157 | const b = go( 158 | 0, 159 | a => { throw { hi: 'ho' } }, 160 | a => a + 10, 161 | a => a + 100); 162 | 163 | console.log(b); 164 | } catch (c) { 165 | console.log(c); 166 | } 167 | // { hi: 'ho' } 168 | 169 | const b = await go( 170 | 0, 171 | a => Promise.resolve(a + 1), 172 | a => a + 10, 173 | a => a + 100); 174 | 175 | console.log(b); 176 | // 111 177 | 178 | try { 179 | const b = await go( 180 | 0, 181 | a => Promise.resolve(a + 1), 182 | a => Promise.reject({ hi: 'ho' }), 183 | a => a + 100); 184 | 185 | console.log(b); 186 | } catch (c) { 187 | console.log(c); 188 | } 189 | // { hi: 'ho' } 190 | 191 | try { 192 | const b = await go( 193 | 0, 194 | a => Promise.resolve(a + 1), 195 | a => Promise.reject({ hi: 'ho' }), 196 | a => a + 100); 197 | 198 | console.log(b); 199 | } catch (c) { 200 | console.log(c); 201 | } 202 | // { hi: 'ho' } 203 | ``` 204 | 205 | ### stop 206 | 207 | ```javascript 208 | const f1 = pipeS( 209 | a => a % 2 ? stop(a) : a, 210 | a => a + 10); 211 | f1(1); // 1 212 | f1(2); // 12 213 | 214 | goS({a: 1, b: 2}, 215 | stopIf({a: 1}), 216 | ({a, b}) => ({a: a + 10, b})); // {a: 1, b: 2} 217 | 218 | goS({a: 2, b: 2}, 219 | stopIf({a: 1}), 220 | ({a, b}) => ({a: a + 10, b})); // {a: 12, b: 2} 221 | 222 | goS({a: 1, b: 2}, 223 | stopIf({a: 1}, null), 224 | ({a, b}) => ({a: a + 10, b})); 225 | // null 226 | ``` -------------------------------------------------------------------------------- /node/public/fxjs2/baseCalls.js: -------------------------------------------------------------------------------- 1 | import isIterable from "./isIterable.js"; 2 | import entriesLazy from "./Lazy/entriesLazy.js"; 3 | import mapEntriesLazy from "./Lazy/mapEntriesLazy.js"; 4 | 5 | const baseCalls = (map, object) => function calls(fs, ...args) { 6 | return isIterable(fs) ? 7 | map(f => f(...args), fs) : 8 | object(mapEntriesLazy(f => f(...args), entriesLazy(fs))); 9 | }; 10 | 11 | export default baseCalls; -------------------------------------------------------------------------------- /node/public/fxjs2/baseExtend.js: -------------------------------------------------------------------------------- 1 | import reduce from "./reduce.js"; 2 | import mapLazy from "./Lazy/mapLazy.js"; 3 | import entriesLazy from "./Lazy/entriesLazy.js"; 4 | 5 | export default function baseExtend(set, obj, objs) { 6 | const type = typeof obj; 7 | obj && 8 | (type == 'object' || type == 'function') && 9 | reduce(reduce(set), obj, mapLazy(entriesLazy, objs)); 10 | return obj; 11 | } -------------------------------------------------------------------------------- /node/public/fxjs2/basePick.js: -------------------------------------------------------------------------------- 1 | import entriesLazy from "./Lazy/entriesLazy.js"; 2 | import go from "./go.js"; 3 | import object from "./object.js"; 4 | 5 | export function basePick(filter, ks, obj) { 6 | return go( 7 | obj, 8 | entriesLazy, 9 | filter(([k]) => ks.includes(k)), 10 | object); 11 | } 12 | 13 | export default basePick; -------------------------------------------------------------------------------- /node/public/fxjs2/baseSel.js: -------------------------------------------------------------------------------- 1 | import curry from "./curry.js"; 2 | import isArray from "./isArray.js"; 3 | import reduce from "./reduce.js"; 4 | import findWhere from "./findWhere.js"; 5 | 6 | export default sep => curry(function sel(selector, acc) { 7 | return ( 8 | !selector ? 9 | acc 10 | : 11 | isArray(selector) ? 12 | reduce((acc, selector) => sel(selector, acc), acc, selector) 13 | : 14 | typeof selector == 'object' || typeof selector == 'function' ? 15 | findWhere(selector, acc) 16 | : 17 | reduce( 18 | (acc, key, s = key[0]) => 19 | !acc ? acc : 20 | s == '#' ? findWhere({ id: key.substr(1) }, acc) : 21 | s == '[' || s == '{' ? findWhere(JSON.parse(key), acc) : 22 | acc[key], 23 | acc, 24 | selector.split(sep)) 25 | ); 26 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/baseSortBy.js: -------------------------------------------------------------------------------- 1 | import pipe from "./pipe.js"; 2 | import isArray from "./isArray.js"; 3 | 4 | const arrComparator = (arr) => (a, b) => { 5 | let i = -1; 6 | while (++i < arr.length) { 7 | const ai = a[arr[i]], bi = b[arr[i]]; 8 | if (ai === bi) continue; 9 | return ai < bi ? -1 : 1; 10 | } 11 | return 0; 12 | }; 13 | 14 | export default function baseSortBy(left, right, f, arr) { 15 | return isArray(f) ? baseSortBy(left, right, arrComparator(f), arr) : 16 | typeof f == 'string' ? baseSortBy(left, right, a => a[f], arr) : 17 | f.length == 2 ? [...arr].sort(right == -1 ? pipe(f, n => n * -1) : f) : 18 | [...arr].sort((a, b, fa = f(a), fb = f(b)) => fa == fb ? 0 : fa < fb ? left : right) 19 | } -------------------------------------------------------------------------------- /node/public/fxjs2/call.js: -------------------------------------------------------------------------------- 1 | export default function call(a, f) { 2 | return f(a); 3 | } -------------------------------------------------------------------------------- /node/public/fxjs2/calls.js: -------------------------------------------------------------------------------- 1 | import baseCalls from "./baseCalls.js"; 2 | import map from "./map.js"; 3 | import object from "./object.js"; 4 | 5 | export default baseCalls(map, object); -------------------------------------------------------------------------------- /node/public/fxjs2/constant.js: -------------------------------------------------------------------------------- 1 | export default function constant(a) { 2 | return _ => a; 3 | } -------------------------------------------------------------------------------- /node/public/fxjs2/countBy.js: -------------------------------------------------------------------------------- 1 | import curry from "./curry.js"; 2 | import reduce from "./reduce.js"; 3 | 4 | function incSel(parent, k) { 5 | parent[k] ? parent[k]++ : parent[k] = 1; 6 | return parent; 7 | } 8 | 9 | export default curry(function countBy(f, iter) { 10 | return reduce((counts, a) => incSel(counts, f(a)), {}, iter); 11 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/curry.js: -------------------------------------------------------------------------------- 1 | export default function curry(f) { 2 | return (a, ..._) => _.length < 1 ? (..._) => f(a, ..._) : f(a, ..._); 3 | } -------------------------------------------------------------------------------- /node/public/fxjs2/deepFlat.js: -------------------------------------------------------------------------------- 1 | import takeAll from "./takeAll.js"; 2 | import deepFlatLazy from "./Lazy/deepFlatLazy.js"; 3 | 4 | export default function deepFlat(iter) { 5 | return takeAll(deepFlatLazy(iter)); 6 | } -------------------------------------------------------------------------------- /node/public/fxjs2/defaults.js: -------------------------------------------------------------------------------- 1 | import baseExtend from "./baseExtend.js"; 2 | import has from "./has.js"; 3 | 4 | const setter = (obj, [k, v]) => { 5 | return (has(k, obj) || (obj[k] = v, obj), obj); 6 | }; 7 | 8 | export function defaults(obj, ...objs) { 9 | return baseExtend(setter, obj, objs); 10 | } 11 | 12 | export default defaults; -------------------------------------------------------------------------------- /node/public/fxjs2/delay.js: -------------------------------------------------------------------------------- 1 | import curry from "./curry.js"; 2 | 3 | export default curry(function delay(time, a) { 4 | return new Promise(resolve => setTimeout(() => resolve(a), time)); 5 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/drop.js: -------------------------------------------------------------------------------- 1 | import curry from "./curry.js"; 2 | import takeAll from "./takeAll.js"; 3 | import dropLazy from "./Lazy/dropLazy.js"; 4 | 5 | export default curry(function drop(l, iter) { 6 | return takeAll(dropLazy(l, iter)); 7 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/dropRight.js: -------------------------------------------------------------------------------- 1 | import curry from "./curry.js"; 2 | import takeAll from "./takeAll.js"; 3 | import go1 from "./go1.js"; 4 | import take from "./take.js"; 5 | 6 | export default curry(function drop(l, iter) { 7 | return go1(takeAll(iter), arr => take(arr.length - l, arr)); 8 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/each.js: -------------------------------------------------------------------------------- 1 | import go1 from "./go1.js"; 2 | import reduce from "./reduce.js"; 3 | import curry from "./curry.js"; 4 | 5 | export default curry(function each(f, iter) { 6 | return go1(reduce((_, a) => f(a), null, iter), _ => iter); 7 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/empty.js: -------------------------------------------------------------------------------- 1 | export default (function *() {} ()); 2 | -------------------------------------------------------------------------------- /node/public/fxjs2/entries.js: -------------------------------------------------------------------------------- 1 | import entriesLazy from "./Lazy/entriesLazy.js"; 2 | import takeAll from "./takeAll.js"; 3 | 4 | export default function entries(a) { 5 | return takeAll(entriesLazy(a)); 6 | } -------------------------------------------------------------------------------- /node/public/fxjs2/every.js: -------------------------------------------------------------------------------- 1 | import rejectLazy from "./Lazy/rejectLazy.js"; 2 | import take1 from "./take1.js"; 3 | import go1 from "./go1.js"; 4 | import curry from "./curry.js"; 5 | 6 | export default curry(function every(f, iter) { 7 | return go1(take1(rejectLazy(f, iter)), ({length}) => length == 0); 8 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/extend.js: -------------------------------------------------------------------------------- 1 | import baseExtend from "./baseExtend.js"; 2 | 3 | const setter = (obj, [k, v]) => (obj[k] = v, obj); 4 | 5 | export default function extend(obj, ...objs) { 6 | return baseExtend(setter, obj, objs); 7 | } -------------------------------------------------------------------------------- /node/public/fxjs2/filter.js: -------------------------------------------------------------------------------- 1 | import filterLazy from "./Lazy/filterLazy.js"; 2 | import curry from "./curry.js"; 3 | import takeAll from "./takeAll.js"; 4 | 5 | export default curry(function filter(f, iter) { 6 | return takeAll(filterLazy(f, iter)); 7 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/find.js: -------------------------------------------------------------------------------- 1 | import head from './head.js'; 2 | import filterLazy from "./Lazy/filterLazy.js"; 3 | import curry from "./curry.js"; 4 | 5 | export default curry(function find(f, iter) { 6 | return head(filterLazy(f, iter)); 7 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/findWhere.js: -------------------------------------------------------------------------------- 1 | import find from "./find.js"; 2 | import isMatch from "./isMatch.js"; 3 | import curry from "./curry.js"; 4 | 5 | export default curry(function findWhere(w, iter) { 6 | return find(isMatch(w), iter); 7 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/flat.js: -------------------------------------------------------------------------------- 1 | import takeAll from "./takeAll.js"; 2 | import flatLazy from "./Lazy/flatLazy.js"; 3 | 4 | export default function flat(iter) { 5 | return takeAll(flatLazy(iter)); 6 | } -------------------------------------------------------------------------------- /node/public/fxjs2/flatMap.js: -------------------------------------------------------------------------------- 1 | import curry from "./curry.js"; 2 | import flat from "./flat.js"; 3 | import map from "./map.js"; 4 | 5 | export default curry(function flatMap(f, iter) { 6 | return flat(map(f, iter)); 7 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/fx.js: -------------------------------------------------------------------------------- 1 | export { default as minBy, default as min_by } from './minBy.js'; 2 | export { default as sortDesc, default as sort_desc } from './sortDesc.js'; 3 | export { default as go } from './go.js'; 4 | export { default as goS } from './goS.js'; 5 | export { default as identity } from './identity.js'; 6 | export { default as reduce } from './reduce.js'; 7 | export { default as reduceS } from './reduceS.js'; 8 | export { default as stop } from './stop.js'; 9 | export { default as stopIf, default as stop_if } from './stopIf.js'; 10 | export { default as take } from './take.js'; 11 | export { default as omit } from './omit.js'; 12 | export { default as values } from './values.js'; 13 | export { default as groupBy, default as group_by } from './groupBy.js'; 14 | export { default as tap } from './tap.js'; 15 | export { default as pipe } from './pipe.js'; 16 | export { default as pipeS } from './pipeS.js'; 17 | export { default as isString, default as is_string } from './isString.js'; 18 | export { default as max } from './max.js'; 19 | export { default as pluck } from './pluck.js'; 20 | export { default as takeAll, default as take_all } from './takeAll.js'; 21 | export { default as countBy, default as count_by } from './countBy.js'; 22 | export { default as keys } from './keys.js'; 23 | export { default as isUndefined, default as is_undefined } from './isUndefined.js'; 24 | export { default as constant } from './constant.js'; 25 | export { default as unique, default as uniq } from './unique.js'; 26 | export { default as indexBy, default as index_by } from './indexBy.js'; 27 | export { default as min } from './min.js'; 28 | export { default as sortByDesc, default as sort_by_desc } from './sortByDesc.js'; 29 | export { default as noop } from './noop.js'; 30 | export { default as hi } from './hi.js'; 31 | export { default as extend } from './extend.js'; 32 | export { default as empty } from './empty.js'; 33 | export { default as takeWhile, default as take_while } from './takeWhile.js'; 34 | export { default as isMatch, default as is_match } from './isMatch.js'; 35 | export { default as mapEntries, default as map_entries, default as entriesMap, default as entries_map } from './mapEntries.js'; 36 | export { default as object } from './object.js'; 37 | export { default as negate } from './negate.js'; 38 | export { default as nop } from './nop.js'; 39 | export { default as call } from './call.js'; 40 | export { default as some } from './some.js'; 41 | export { default as deepFlat, default as deepFlatten, default as deep_flat, default as deep_flatten } from './deepFlat.js'; 42 | export { default as toIter, default as to_iter } from './toIter.js'; 43 | export { default as maxBy, default as max_by } from './maxBy.js'; 44 | export { default as flat, default as flatten } from './flat.js'; 45 | export { default as baseSel, default as base_sel } from './baseSel.js'; 46 | export { default as sortBy, default as sort_by } from './sortBy.js'; 47 | export { default as not } from './not.js'; 48 | export { default as go1 } from './go1.js'; 49 | export { default as find } from './find.js'; 50 | export { default as isArray, default as is_array } from './isArray.js'; 51 | export { default as each } from './each.js'; 52 | export { default as entries } from './entries.js'; 53 | export { default as filter } from './filter.js'; 54 | export { default as sort } from './sort.js'; 55 | export { default as curry } from './curry.js'; 56 | export { default as isFunction, default as is_function } from './isFunction.js'; 57 | export { default as sel } from './sel.js'; 58 | export { default as match } from './match.js'; 59 | export { default as map } from './map.js'; 60 | export { default as head } from './head.js'; 61 | export { default as every } from './every.js'; 62 | export { default as has } from './has.js'; 63 | export { default as isIterable, default as is_iterable } from './isIterable.js'; 64 | export { default as uniqueBy, default as unique_by } from './uniqueBy.js'; 65 | export { default as flatMap, default as flat_map } from './flatMap.js'; 66 | export { default as string } from './string.js'; 67 | export { default as strMap, default as str_map, default as scat } from './strMap.js'; 68 | export { default as findWhere, default as find_where } from './findWhere.js'; 69 | export { default as reject } from './reject.js'; 70 | export { default as pick } from './pick.js'; 71 | export { default as last } from './last.js'; 72 | export { default as take1 } from './take1.js'; 73 | export { default as tail } from './tail.js'; 74 | export { default as log } from './log.js'; 75 | export { default as takeUntil, default as take_until } from './takeUntil.js'; 76 | export { default as defaults } from './defaults.js'; 77 | export { default as calls } from './calls.js'; 78 | export { default as delay } from './delay.js'; 79 | export { default as safety } from './safety.js'; 80 | export { default as mapObject, default as map_object } from './mapObject.js'; 81 | export { default as promiseAllObject, default as promise_all_object } from './promiseAllObject.js'; 82 | export { default as promiseAllEntries, default as promise_all_entries } from './promiseAllEntries.js'; 83 | export { default as isStop, default as is_stop } from './isStop.js'; 84 | export { default as range } from './range.js'; 85 | export { default as drop } from './drop.js'; 86 | export { default as dropRight, default as drop_right } from './dropRight.js'; 87 | export * from './L.js'; 88 | export * from './C.js'; -------------------------------------------------------------------------------- /node/public/fxjs2/go.js: -------------------------------------------------------------------------------- 1 | import reduce from "./reduce.js"; 2 | import call from "./call.js"; 3 | 4 | export default function go(..._) { 5 | return reduce(call, _); 6 | } -------------------------------------------------------------------------------- /node/public/fxjs2/go1.js: -------------------------------------------------------------------------------- 1 | export default function go1(a, f) { 2 | return a instanceof Promise ? a.then(f) : f(a); 3 | } -------------------------------------------------------------------------------- /node/public/fxjs2/goS.js: -------------------------------------------------------------------------------- 1 | import reduceS from "./reduceS.js"; 2 | import call from "./call.js"; 3 | 4 | export default function goS(..._) { 5 | return reduceS(call, _); 6 | } -------------------------------------------------------------------------------- /node/public/fxjs2/groupBy.js: -------------------------------------------------------------------------------- 1 | import curry from "./curry.js"; 2 | import reduce from "./reduce.js"; 3 | 4 | function pushSel(parent, k, v) { 5 | (parent[k] || (parent[k] = [])).push(v); 6 | return parent; 7 | } 8 | 9 | export default curry(function groupBy(f, iter) { 10 | return reduce((group, a) => pushSel(group, f(a), a), {}, iter); 11 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/has.js: -------------------------------------------------------------------------------- 1 | import curry from "./curry.js"; 2 | 3 | export default curry(function has(k, obj) { 4 | return !!(obj && obj.hasOwnProperty(k)); 5 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/head.js: -------------------------------------------------------------------------------- 1 | import take from "./take.js"; 2 | import go1 from "./go1.js"; 3 | 4 | export default function head(iter) { 5 | return go1(take(1, iter), ([h]) => h); 6 | } -------------------------------------------------------------------------------- /node/public/fxjs2/hi.js: -------------------------------------------------------------------------------- 1 | import tap from "./tap.js"; 2 | import log from "./log.js"; 3 | 4 | const f = tap(log); 5 | 6 | export default function hi(..._) { return f(..._); } -------------------------------------------------------------------------------- /node/public/fxjs2/identity.js: -------------------------------------------------------------------------------- 1 | export default a => a; -------------------------------------------------------------------------------- /node/public/fxjs2/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('esm')(module, { cache: false })('./fx.js'); 2 | -------------------------------------------------------------------------------- /node/public/fxjs2/indexBy.js: -------------------------------------------------------------------------------- 1 | import curry from "./curry.js"; 2 | import reduce from "./reduce.js"; 3 | 4 | export default curry(function indexBy(f, iter) { 5 | return reduce((obj, a) => (obj[f(a)] = a, obj), {}, iter); 6 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/isArray.js: -------------------------------------------------------------------------------- 1 | export const { isArray } = Array; 2 | 3 | export default isArray; -------------------------------------------------------------------------------- /node/public/fxjs2/isFunction.js: -------------------------------------------------------------------------------- 1 | export default function isFunction(a) { 2 | return typeof a == 'function'; 3 | } -------------------------------------------------------------------------------- /node/public/fxjs2/isIterable.js: -------------------------------------------------------------------------------- 1 | export default function isIterable(a) { 2 | return a != null && !!a[Symbol.iterator]; 3 | } -------------------------------------------------------------------------------- /node/public/fxjs2/isMatch.js: -------------------------------------------------------------------------------- 1 | import curry from "./curry.js"; 2 | import isArray from "./isArray.js"; 3 | import every from "./every.js"; 4 | import entriesLazy from "./Lazy/entriesLazy.js"; 5 | 6 | export default curry(function isMatch(a, b) { 7 | return ( 8 | typeof a == 'function' ? !!a(b) 9 | : 10 | isArray(a) && isArray(b) ? every(v => b.includes(v), a) 11 | : 12 | typeof b == 'object' ? every(([k, v]) => b[k] == v, entriesLazy(a)) 13 | : 14 | a instanceof RegExp ? b.match(a) 15 | : 16 | a == b 17 | ); 18 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/isStop.js: -------------------------------------------------------------------------------- 1 | const SymbolStop = Symbol.for('stop'); 2 | 3 | export default function isStop(a) { 4 | return !!(a && a[SymbolStop]); 5 | } -------------------------------------------------------------------------------- /node/public/fxjs2/isString.js: -------------------------------------------------------------------------------- 1 | export default function isString(a) { 2 | return typeof a == 'string'; 3 | } -------------------------------------------------------------------------------- /node/public/fxjs2/isUndefined.js: -------------------------------------------------------------------------------- 1 | export default a => a === undefined; -------------------------------------------------------------------------------- /node/public/fxjs2/keys.js: -------------------------------------------------------------------------------- 1 | import keysLazy from "./Lazy/keysLazy.js"; 2 | import takeAll from "./takeAll.js"; 3 | 4 | export default function keys(a) { 5 | return takeAll(keysLazy(a)); 6 | } -------------------------------------------------------------------------------- /node/public/fxjs2/last.js: -------------------------------------------------------------------------------- 1 | export default function last(arr) { 2 | return arr[arr.length - 1]; 3 | } -------------------------------------------------------------------------------- /node/public/fxjs2/log.js: -------------------------------------------------------------------------------- 1 | export const { log } = console; 2 | 3 | export default log; -------------------------------------------------------------------------------- /node/public/fxjs2/map.js: -------------------------------------------------------------------------------- 1 | import mapLazy from "./Lazy/mapLazy.js"; 2 | import curry from "./curry.js"; 3 | import takeAll from "./takeAll.js"; 4 | 5 | export default curry(function map(f, iter) { 6 | return takeAll(mapLazy(f, iter)); 7 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/mapEntries.js: -------------------------------------------------------------------------------- 1 | import mapEntriesLazy from "./Lazy/mapEntriesLazy.js"; 2 | import curry from "./curry.js"; 3 | import takeAll from "./takeAll.js"; 4 | 5 | export default curry(function mapEntries(f, iter) { 6 | return takeAll(mapEntriesLazy(f, iter)); 7 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/mapObject.js: -------------------------------------------------------------------------------- 1 | import curry from "./curry.js"; 2 | import entriesLazy from "./Lazy/entriesLazy.js"; 3 | import mapEntriesLazy from "./Lazy/mapEntriesLazy.js"; 4 | import object from "./object.js"; 5 | 6 | export default curry(function mapObject(f, obj) { 7 | return object(mapEntriesLazy(f, entriesLazy(obj))); 8 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/match.js: -------------------------------------------------------------------------------- 1 | import go from "./go.js"; 2 | import values from "./values.js"; 3 | import find from "./find.js"; 4 | import pipe from "./pipe.js"; 5 | import isMatch from "./isMatch.js"; 6 | 7 | function baseMatch(targets) { 8 | var cbs = []; 9 | 10 | function evl() { 11 | return go( 12 | targets, 13 | values, 14 | targets => 15 | go(cbs, 16 | find(pb => { return pb._case(...targets); }), 17 | pb => pb._body(...targets))); 18 | } 19 | 20 | function _case(f) { 21 | cbs.push({ _case: typeof f == 'function' ? pipe(...arguments) : isMatch(f) }); 22 | return _body; 23 | } 24 | _case.case = _case; 25 | 26 | function _body() { 27 | cbs[cbs.length-1]._body = pipe(...arguments); 28 | return _case; 29 | } 30 | 31 | _case.else = function() { 32 | _case(_=> true) (...arguments); 33 | return targets ? evl() : (...targets2) => ((targets = targets2), evl()); 34 | }; 35 | 36 | return _case; 37 | } 38 | 39 | function match(..._) { 40 | return baseMatch(_); 41 | } 42 | 43 | match.case = (..._) => baseMatch(null).case(..._); 44 | 45 | export default match; -------------------------------------------------------------------------------- /node/public/fxjs2/max.js: -------------------------------------------------------------------------------- 1 | import maxBy from "./maxBy.js"; 2 | 3 | export default function max(iter) { 4 | return maxBy(a => a, iter); 5 | } -------------------------------------------------------------------------------- /node/public/fxjs2/maxBy.js: -------------------------------------------------------------------------------- 1 | import curry from "./curry.js"; 2 | import reduce from "./reduce.js"; 3 | 4 | export default curry(function maxBy(f, iter) { 5 | return reduce((a, b) => f(a) >= f(b) ? a : b, iter); 6 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/min.js: -------------------------------------------------------------------------------- 1 | import minBy from "./minBy.js"; 2 | 3 | export default function min(iter) { 4 | return minBy(a => a, iter); 5 | } -------------------------------------------------------------------------------- /node/public/fxjs2/minBy.js: -------------------------------------------------------------------------------- 1 | import curry from "./curry.js"; 2 | import reduce from "./reduce.js"; 3 | 4 | export default curry(function minBy(f, iter) { 5 | return reduce((a, b) => f(a) <= f(b) ? a : b, iter); 6 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/negate.js: -------------------------------------------------------------------------------- 1 | import go1 from "./go1.js"; 2 | import not from "./not.js"; 3 | 4 | export default function negate(f) { 5 | return (..._) => go1(f(..._), not); 6 | } -------------------------------------------------------------------------------- /node/public/fxjs2/noop.js: -------------------------------------------------------------------------------- 1 | export default function noop() {}; -------------------------------------------------------------------------------- /node/public/fxjs2/nop.js: -------------------------------------------------------------------------------- 1 | export const nop = Symbol.for('nop'); 2 | 3 | export default nop; -------------------------------------------------------------------------------- /node/public/fxjs2/not.js: -------------------------------------------------------------------------------- 1 | export default function not(a) { 2 | return !a; 3 | } -------------------------------------------------------------------------------- /node/public/fxjs2/object.js: -------------------------------------------------------------------------------- 1 | import reduce from "./reduce.js"; 2 | 3 | export default function object(iter) { 4 | return reduce((obj, [k, v]) => (obj[k] = v, obj), {}, iter); 5 | } -------------------------------------------------------------------------------- /node/public/fxjs2/omit.js: -------------------------------------------------------------------------------- 1 | import rejectLazy from "./Lazy/rejectLazy.js"; 2 | import curry from "./curry.js"; 3 | import basePick from "./basePick.js"; 4 | 5 | export default curry(function omit(ks, obj) { 6 | return basePick(rejectLazy, ks, obj); 7 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "_from": "fxjs2", 3 | "_id": "fxjs2@0.2.6", 4 | "_inBundle": false, 5 | "_integrity": "sha512-3v3fBVwPbPX6+gyuYFPjPxr0mr9iS+KTpgO08NA2ztxYoguxLxahim3D50B2dHMxM6LQ9ft/Vwg19upSijnVIw==", 6 | "_location": "/fxjs2", 7 | "_phantomChildren": {}, 8 | "_requested": { 9 | "type": "tag", 10 | "registry": true, 11 | "raw": "fxjs2", 12 | "name": "fxjs2", 13 | "escapedName": "fxjs2", 14 | "rawSpec": "", 15 | "saveSpec": null, 16 | "fetchSpec": "latest" 17 | }, 18 | "_requiredBy": [ 19 | "#USER", 20 | "/" 21 | ], 22 | "_resolved": "https://registry.npmjs.org/fxjs2/-/fxjs2-0.2.6.tgz", 23 | "_shasum": "1b5a7cc6803cccb3edf6bbd519db9a6b0fadb37d", 24 | "_spec": "fxjs2", 25 | "_where": "/Users/indongyoo/WebstormProjects/NAVER-functional-javascript/node", 26 | "author": "", 27 | "bugs": { 28 | "url": "https://github.com/marpple/FxJS/issues" 29 | }, 30 | "bundleDependencies": false, 31 | "dependencies": { 32 | "esm": "^3.0.80" 33 | }, 34 | "deprecated": false, 35 | "description": "Functional Extensions for Javascript", 36 | "devDependencies": { 37 | "chai": "^4.1.2", 38 | "mocha": "^5.2.0" 39 | }, 40 | "files": [ 41 | "Concurrency/*", 42 | "Lazy/*", 43 | "*.js", 44 | "LICENSE", 45 | "README.md" 46 | ], 47 | "homepage": "https://github.com/marpple/FxJS#readme", 48 | "license": "MIT", 49 | "main": "index.js", 50 | "name": "fxjs2", 51 | "repository": { 52 | "type": "git", 53 | "url": "git+https://github.com/marpple/FxJS.git" 54 | }, 55 | "scripts": { 56 | "test": "mocha -R spec test/**/*.js" 57 | }, 58 | "version": "0.2.6" 59 | } 60 | -------------------------------------------------------------------------------- /node/public/fxjs2/pick.js: -------------------------------------------------------------------------------- 1 | import filterLazy from "./Lazy/filterLazy.js"; 2 | import curry from "./curry.js"; 3 | import basePick from "./basePick.js"; 4 | 5 | export default curry(function pick(ks, obj) { 6 | return basePick(filterLazy, ks, obj); 7 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/pipe.js: -------------------------------------------------------------------------------- 1 | import reduce from "./reduce.js"; 2 | import call from "./call.js"; 3 | 4 | export default function pipe(f, ...fs) { 5 | return (...as) => reduce(call, f(...as), fs); 6 | } -------------------------------------------------------------------------------- /node/public/fxjs2/pipeS.js: -------------------------------------------------------------------------------- 1 | import reduceS from "./reduceS.js"; 2 | import call from "./call.js"; 3 | 4 | export default function pipeS(f, ...fs) { 5 | return (...as) => reduceS(call, f(...as), fs); 6 | } -------------------------------------------------------------------------------- /node/public/fxjs2/pluck.js: -------------------------------------------------------------------------------- 1 | import curry from "./curry.js"; 2 | import map from "./map.js"; 3 | 4 | export default curry(function pluck(k, iter) { 5 | return map(a => a[k], iter); 6 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/promiseAllEntries.js: -------------------------------------------------------------------------------- 1 | import identity from "./identity.js"; 2 | import mapEntries from "./mapEntries.js"; 3 | 4 | export default function promiseAllEntries(entries) { 5 | return mapEntries(identity, entries); 6 | } -------------------------------------------------------------------------------- /node/public/fxjs2/promiseAllObject.js: -------------------------------------------------------------------------------- 1 | import mapObject from "./mapObject.js"; 2 | import identity from "./identity.js"; 3 | 4 | export default function promiseAllObject(obj) { 5 | return mapObject(identity, obj); 6 | } -------------------------------------------------------------------------------- /node/public/fxjs2/range.js: -------------------------------------------------------------------------------- 1 | import takeAll from "./takeAll.js"; 2 | import rangeLazy from "./Lazy/rangeLazy.js"; 3 | 4 | export default function range(..._) { 5 | return takeAll(rangeLazy(..._)); 6 | } -------------------------------------------------------------------------------- /node/public/fxjs2/reduce.js: -------------------------------------------------------------------------------- 1 | import toIter from "./toIter.js"; 2 | import nop from "./nop.js"; 3 | import go1 from "./go1.js"; 4 | import head from "./head.js"; 5 | 6 | const call2 = (acc, a, f) => 7 | a instanceof Promise ? 8 | a.then(a => f(acc, a), e => e == nop ? acc : Promise.reject(e)) : 9 | f(acc, a); 10 | 11 | export default function reduce(f, acc, iter) { 12 | if (arguments.length == 1) return (..._) => reduce(f, ..._); 13 | if (arguments.length == 2) return reduce(f, head(iter = toIter(acc)), iter); 14 | 15 | iter = toIter(iter); 16 | return go1(acc, function recur(acc) { 17 | let cur; 18 | while (!(cur = iter.next()).done) { 19 | acc = call2(acc, cur.value, f); 20 | if (acc instanceof Promise) return acc.then(recur); 21 | } 22 | return acc; 23 | }); 24 | } -------------------------------------------------------------------------------- /node/public/fxjs2/reduceS.js: -------------------------------------------------------------------------------- 1 | import toIter from "./toIter.js"; 2 | import nop from "./nop.js"; 3 | import go1 from "./go1.js"; 4 | import head from "./head.js"; 5 | import isStop from "./isStop.js"; 6 | 7 | const call2 = (acc, a, f) => 8 | a instanceof Promise ? 9 | a.then(a => f(acc, a), e => e == nop ? acc : Promise.reject(e)) : 10 | f(acc, a); 11 | 12 | export default function reduceS(f, acc, iter) { 13 | if (arguments.length == 1) return (..._) => reduceS(f, ..._); 14 | if (arguments.length == 2) return reduceS(f, head(iter = toIter(acc)), iter); 15 | 16 | iter = toIter(iter); 17 | return go1(acc, function recur(acc) { 18 | let cur; 19 | while (!isStop(acc) && !(cur = iter.next()).done) { 20 | acc = call2(acc, cur.value, f); 21 | if (acc instanceof Promise) return acc.then(recur); 22 | } 23 | return isStop(acc) ? acc.value : acc; 24 | }); 25 | } -------------------------------------------------------------------------------- /node/public/fxjs2/reject.js: -------------------------------------------------------------------------------- 1 | import filter from "./filter.js"; 2 | import curry from "./curry.js"; 3 | import go1 from "./go1.js"; 4 | import not from "./not.js"; 5 | 6 | export default curry(function reject(f, iter) { 7 | return filter(a => go1(f(a), not), iter); 8 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/safety.js: -------------------------------------------------------------------------------- 1 | import empty from "./empty.js"; 2 | 3 | export default function safety(a) { 4 | return a != null && !!a[Symbol.iterator] ? a : empty; 5 | } -------------------------------------------------------------------------------- /node/public/fxjs2/sel.js: -------------------------------------------------------------------------------- 1 | import baseSel from "./baseSel.js"; 2 | 3 | export default baseSel('.'); -------------------------------------------------------------------------------- /node/public/fxjs2/some.js: -------------------------------------------------------------------------------- 1 | import filterLazy from "./Lazy/filterLazy.js"; 2 | import take1 from "./take1.js"; 3 | import go1 from "./go1.js"; 4 | import curry from "./curry.js"; 5 | 6 | export default curry(function some(f, iter) { 7 | return go1(take1(filterLazy(f, iter)), ({length}) => length == 1); 8 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/sort.js: -------------------------------------------------------------------------------- 1 | import sortBy from "./sortBy.js"; 2 | 3 | export default function sort(arr) { 4 | return sortBy(a => a, arr); 5 | } -------------------------------------------------------------------------------- /node/public/fxjs2/sortBy.js: -------------------------------------------------------------------------------- 1 | import baseSortBy from "./baseSortBy.js"; 2 | import curry from "./curry.js"; 3 | 4 | export default curry(function sortBy(f, arr) { 5 | return baseSortBy(-1, 1, f, arr); 6 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/sortByDesc.js: -------------------------------------------------------------------------------- 1 | import baseSortBy from "./baseSortBy.js"; 2 | import curry from "./curry.js"; 3 | 4 | export default curry(function sortByDesc(f, arr) { 5 | return baseSortBy(1, -1, f, arr); 6 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/sortDesc.js: -------------------------------------------------------------------------------- 1 | import sortByDesc from "./sortByDesc.js"; 2 | 3 | export default function sort(arr) { 4 | return sortByDesc(a => a, arr); 5 | } -------------------------------------------------------------------------------- /node/public/fxjs2/stop.js: -------------------------------------------------------------------------------- 1 | const SymbolStop = Symbol.for('stop'); 2 | 3 | export default function stop(value) { 4 | return { [SymbolStop]: true, value }; 5 | } -------------------------------------------------------------------------------- /node/public/fxjs2/stopIf.js: -------------------------------------------------------------------------------- 1 | import match from "./match.js"; 2 | import stop from "./stop.js"; 3 | 4 | export default function stopIf(f, stopVal) { 5 | return match.case(f)(arguments.length == 2 ? _ => stop(stopVal) : stop).else(a => a); 6 | } -------------------------------------------------------------------------------- /node/public/fxjs2/strMap.js: -------------------------------------------------------------------------------- 1 | import mapLazy from "./Lazy/mapLazy.js"; 2 | import string from "./string.js"; 3 | import curry from "./curry.js"; 4 | 5 | export default curry(function strMap(f, iter) { 6 | return string(mapLazy(f, iter)); 7 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/string.js: -------------------------------------------------------------------------------- 1 | import reduce from "./reduce.js"; 2 | import curry from "./curry.js"; 3 | 4 | const sadd = (a, b) => `${a}${b}`; 5 | 6 | export default function string(iter) { 7 | return reduce(sadd, iter); 8 | } -------------------------------------------------------------------------------- /node/public/fxjs2/tail.js: -------------------------------------------------------------------------------- 1 | import drop from "./drop.js"; 2 | 3 | export default function tail(iter) { 4 | return drop(1, iter); 5 | } -------------------------------------------------------------------------------- /node/public/fxjs2/take.js: -------------------------------------------------------------------------------- 1 | import curry from "./curry.js"; 2 | import toIter from "./toIter.js"; 3 | import nop from "./nop.js"; 4 | 5 | export default curry(function take(l, iter) { 6 | if (l < 1) return []; 7 | let res = []; 8 | iter = toIter(iter); 9 | return function recur() { 10 | let cur; 11 | while (!(cur = iter.next()).done) { 12 | const a = cur.value; 13 | if (a instanceof Promise) { 14 | return a 15 | .then(a => (res.push(a), res).length == l ? res : recur()) 16 | .catch(e => e == nop ? recur() : Promise.reject(e)); 17 | } 18 | res.push(a); 19 | if (res.length == l) return res; 20 | } 21 | return res; 22 | } (); 23 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/take1.js: -------------------------------------------------------------------------------- 1 | import take from "./take.js"; 2 | 3 | export const take1 = take(1); 4 | 5 | export default take1; -------------------------------------------------------------------------------- /node/public/fxjs2/takeAll.js: -------------------------------------------------------------------------------- 1 | import take from "./take.js"; 2 | 3 | export default function takeAll(iter) { 4 | return take(Infinity, iter); 5 | } -------------------------------------------------------------------------------- /node/public/fxjs2/takeUntil.js: -------------------------------------------------------------------------------- 1 | import toIter from "./toIter.js"; 2 | import go1 from "./go1.js"; 3 | import nop from "./nop.js"; 4 | import curry from "./curry.js"; 5 | 6 | export const takeUntil = curry(function takeUntil(f, iter) { 7 | let res = []; 8 | iter = toIter(iter); 9 | return function recur() { 10 | let cur; 11 | while (!(cur = iter.next()).done) { 12 | const a = cur.value; 13 | const b = go1(a, a => (res.push(a), f(a, res))); 14 | if (b instanceof Promise) 15 | return b.then(b => b ? res : recur()).catch(e => e == nop ? recur() : Promise.reject(e)); 16 | if (b) break; 17 | } 18 | return res; 19 | } (); 20 | }); 21 | 22 | export default takeUntil; -------------------------------------------------------------------------------- /node/public/fxjs2/takeWhile.js: -------------------------------------------------------------------------------- 1 | import toIter from "./toIter.js"; 2 | import curry from "./curry.js"; 3 | import go1 from "./go1.js"; 4 | import nop from "./nop.js"; 5 | 6 | export default curry(function takeWhile(f, iter) { 7 | let res = []; 8 | iter = toIter(iter); 9 | return function recur() { 10 | let cur; 11 | while (!(cur = iter.next()).done) { 12 | const a = cur.value; 13 | const b = go1(a, a => f(a, res)); 14 | if (!b) return res; 15 | if (b instanceof Promise) { 16 | return b 17 | .then(async b => b ? (res.push(await a), recur()) : res) 18 | .catch(e => e == nop ? recur() : Promise.reject(e)); 19 | } 20 | res.push(a); 21 | } 22 | return res; 23 | } (); 24 | }); -------------------------------------------------------------------------------- /node/public/fxjs2/tap.js: -------------------------------------------------------------------------------- 1 | import reduce from "./reduce.js"; 2 | import call from "./call.js"; 3 | import go1 from "./go1.js"; 4 | 5 | export default function tap(f, ...fs) { 6 | return (a, ...as) => go1(reduce(call, f(a, ...as), fs), _ => a); 7 | } -------------------------------------------------------------------------------- /node/public/fxjs2/toIter.js: -------------------------------------------------------------------------------- 1 | import empty from "./empty.js"; 2 | 3 | export default function toIter(iterable) { 4 | return iterable && iterable[Symbol.iterator] ? iterable[Symbol.iterator]() : empty; 5 | } -------------------------------------------------------------------------------- /node/public/fxjs2/unique.js: -------------------------------------------------------------------------------- 1 | import uniqueBy from "./uniqueBy.js"; 2 | 3 | export default function unique(iter) { 4 | return uniqueBy(a => a, iter); 5 | } -------------------------------------------------------------------------------- /node/public/fxjs2/uniqueBy.js: -------------------------------------------------------------------------------- 1 | import curry from "./curry.js"; 2 | import isIterable from "./isIterable.js"; 3 | import go from "./go.js"; 4 | import identity from "./identity.js"; 5 | import last from "./last.js"; 6 | import pipe from "./pipe.js"; 7 | import filter from "./Lazy/filterLazy.js"; 8 | import entries from "./Lazy/entriesLazy.js"; 9 | import takeAll from "./takeAll.js"; 10 | import object from "./object.js"; 11 | 12 | export const uniqueBy = curry(function uniqueBy(f, iter) { 13 | const s = new Set(); 14 | const isObj = !isIterable(iter); 15 | return go( 16 | iter, 17 | isObj ? entries : identity, 18 | filter(pipe( 19 | isObj ? last : identity, 20 | f, 21 | b => s.has(b) ? false : s.add(b))), 22 | isObj ? object : takeAll); 23 | }); 24 | 25 | export default uniqueBy; -------------------------------------------------------------------------------- /node/public/fxjs2/values.js: -------------------------------------------------------------------------------- 1 | import valuesLazy from "./Lazy/valuesLazy.js"; 2 | import takeAll from "./takeAll.js"; 3 | 4 | export default function values(a) { 5 | return takeAll(valuesLazy(a)); 6 | } --------------------------------------------------------------------------------