pepka 0.12.2 → 0.13.0-b1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.circleci/config.yml +19 -19
- package/.github/ISSUE_TEMPLATE/bug_report.md +38 -38
- package/.github/ISSUE_TEMPLATE/feature_request.md +20 -20
- package/CODE_OF_CONDUCT.md +76 -76
- package/CONTRIBUTING.md +3 -3
- package/LICENSE +21 -21
- package/README.md +36 -10
- package/dist/bundle.d.ts +18 -11
- package/dist/bundle.dev.js +119 -77
- package/dist/bundle.js +1 -1
- package/dist/es/quick.js +1 -0
- package/dist/es/types.js +1 -0
- package/package.json +14 -16
- package/rollup.config.js +34 -33
- package/src/common.ts +14 -14
- package/src/curry.ts +99 -53
- package/src/index.ts +6 -5
- package/src/quick.ts +98 -97
- package/src/safe.ts +392 -404
- package/src/types.ts +14 -7
- package/src/uncurry.ts +11 -0
- package/src/utils.ts +11 -11
- package/test/in-browser.ts +3 -3
- package/test/workbench.html +9 -9
- package/tsconfig.json +18 -20
- package/tslint.json +24 -24
package/src/curry.ts
CHANGED
|
@@ -1,53 +1,99 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export const __ = (
|
|
5
|
-
|
|
6
|
-
const countArgs = (s:
|
|
7
|
-
let i = 0
|
|
8
|
-
for (const v of s) v!==__ && i++
|
|
9
|
-
return i
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// TODO: try to make it mutable.
|
|
13
|
-
// { 0: __, 1: 10 }, [ 11 ]
|
|
14
|
-
const addArgs = (args:
|
|
15
|
-
const len = args.length
|
|
16
|
-
const new_args = args.slice()
|
|
17
|
-
const _args_len = _args.length
|
|
18
|
-
let _args_left = _args_len
|
|
19
|
-
let i=0
|
|
20
|
-
for (; _args_left && i<len; i++) {
|
|
21
|
-
if(new_args[i] === __) {
|
|
22
|
-
new_args[i] = _args[_args_len-_args_left]
|
|
23
|
-
_args_left--
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
for(i=len; _args_left; i++, _args_left--) {
|
|
27
|
-
new_args[i] = _args[_args_len-_args_left]
|
|
28
|
-
}
|
|
29
|
-
return new_args
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const _curry = (fn: Function, args:
|
|
33
|
-
const args2add = fn.length - args.length - countArgs(new_args)
|
|
34
|
-
if(args2add < 1) {
|
|
35
|
-
return fn(...addArgs(args, new_args))
|
|
36
|
-
} else {
|
|
37
|
-
const curried = (...__args:
|
|
38
|
-
fn,
|
|
39
|
-
addArgs(args, new_args),
|
|
40
|
-
__args
|
|
41
|
-
)
|
|
42
|
-
;(curried as any).$args_left = args2add
|
|
43
|
-
return curried
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export const curry = (
|
|
48
|
-
(fn:
|
|
49
|
-
(...args:
|
|
50
|
-
? _curry(fn, [], args)
|
|
51
|
-
: fn(...args)
|
|
52
|
-
)
|
|
53
|
-
)
|
|
1
|
+
import { F as FT, A } from 'ts-toolbelt'
|
|
2
|
+
import { AnyFunc, AnyArgs } from "./types"
|
|
3
|
+
|
|
4
|
+
export const __ = Symbol('Placeholder') as A.x
|
|
5
|
+
|
|
6
|
+
const countArgs = (s: AnyArgs) => {
|
|
7
|
+
let i = 0
|
|
8
|
+
for (const v of s) v!==__ && i++
|
|
9
|
+
return i
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// TODO: try to make it mutable.
|
|
13
|
+
// { 0: __, 1: 10 }, [ 11 ]
|
|
14
|
+
const addArgs = (args: AnyArgs, _args: AnyArgs) => {
|
|
15
|
+
const len = args.length
|
|
16
|
+
const new_args = args.slice()
|
|
17
|
+
const _args_len = _args.length
|
|
18
|
+
let _args_left = _args_len
|
|
19
|
+
let i=0
|
|
20
|
+
for (; _args_left && i<len; i++) {
|
|
21
|
+
if(new_args[i] === __) {
|
|
22
|
+
new_args[i] = _args[_args_len-_args_left]
|
|
23
|
+
_args_left--
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
for(i=len; _args_left; i++, _args_left--) {
|
|
27
|
+
new_args[i] = _args[_args_len-_args_left]
|
|
28
|
+
}
|
|
29
|
+
return new_args
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const _curry = (fn: Function, args: AnyArgs, new_args: AnyArgs) => {
|
|
33
|
+
const args2add = fn.length - args.length - countArgs(new_args)
|
|
34
|
+
if(args2add < 1) {
|
|
35
|
+
return fn(...addArgs(args, new_args))
|
|
36
|
+
} else {
|
|
37
|
+
const curried = (...__args: AnyArgs) => _curry(
|
|
38
|
+
fn,
|
|
39
|
+
addArgs(args, new_args),
|
|
40
|
+
__args
|
|
41
|
+
)
|
|
42
|
+
;(curried as any).$args_left = args2add
|
|
43
|
+
return curried
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const curry = (
|
|
48
|
+
<Func extends AnyFunc>(fn: AnyFunc) => (
|
|
49
|
+
(...args: AnyArgs) => fn.length>countArgs(args)
|
|
50
|
+
? _curry(fn, [], args)
|
|
51
|
+
: fn(...args)
|
|
52
|
+
) as FT.Curry<Func>
|
|
53
|
+
)
|
|
54
|
+
// type EndlessPh<Func extends FT.Function, ArgT> =
|
|
55
|
+
// (a: ArgT) => ReturnType<Func>
|
|
56
|
+
// | ((a: A.x) => EndlessPh<Func, ArgT>)
|
|
57
|
+
const endlessph = <Func extends FT.Function>(fn: Func) => {
|
|
58
|
+
type ReturnT = ReturnType<Func>
|
|
59
|
+
type p0 = Parameters<Func>[0]
|
|
60
|
+
function _endlessph(a: p0): ReturnT
|
|
61
|
+
function _endlessph(a: A.x): Func
|
|
62
|
+
function _endlessph(a: p0 | A.x) {
|
|
63
|
+
return a===__ ? fn : fn(a)
|
|
64
|
+
}
|
|
65
|
+
return _endlessph
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
type Func2 = (a: any, b: any) => any
|
|
69
|
+
export function curry2<Func extends Func2>(fn: Func) {
|
|
70
|
+
type p0 = Parameters<Func>[0]
|
|
71
|
+
type p1 = Parameters<Func>[1]
|
|
72
|
+
type ReturnT = ReturnType<Func>
|
|
73
|
+
function curried2( a: p0 ): (b: p1) => ReturnT
|
|
74
|
+
function curried2( a: p0, b: p1 ): ReturnT
|
|
75
|
+
function curried2( a: A.x, b: p1 ): (a: p0) => ReturnT
|
|
76
|
+
function curried2( a: p0, b: A.x ): (b: p1) => ReturnT
|
|
77
|
+
function curried2( a: p0 | A.x, b?: p1 ) {
|
|
78
|
+
const withPlaceholder1 = a===__
|
|
79
|
+
const aln = arguments.length
|
|
80
|
+
if(aln === 1 && withPlaceholder1)
|
|
81
|
+
throw new Error('Senseless placeholder usage.')
|
|
82
|
+
return arguments.length>1
|
|
83
|
+
? withPlaceholder1
|
|
84
|
+
? endlessph((a: p0) => fn(a, b))
|
|
85
|
+
: fn(a, b) as ReturnType<Func>
|
|
86
|
+
: (b: p1) => fn(a, b)
|
|
87
|
+
}
|
|
88
|
+
return curried2
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
type Func3 = (a: any, b: any, c: any) => any
|
|
92
|
+
export function curry3<Func extends Func3>(fn: Func) {
|
|
93
|
+
// type p0 = Parameters<Func>[0]
|
|
94
|
+
// type p1 = Parameters<Func>[1]
|
|
95
|
+
// type p2 = Parameters<Func>[2]
|
|
96
|
+
// type ReturnT = ReturnType<Func>
|
|
97
|
+
// TODO: optimize.
|
|
98
|
+
return curry(fn)
|
|
99
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
export * from './curry'
|
|
3
|
-
export * from './
|
|
4
|
-
export * from './
|
|
5
|
-
export * from './
|
|
1
|
+
|
|
2
|
+
export * from './curry'
|
|
3
|
+
export * from './uncurry'
|
|
4
|
+
export * from './common'
|
|
5
|
+
export * from './safe'
|
|
6
|
+
export * from './quick'
|
|
6
7
|
export * from './strings'
|
package/src/quick.ts
CHANGED
|
@@ -1,98 +1,99 @@
|
|
|
1
|
-
import { curry } from "./curry"
|
|
2
|
-
import { type } from "./common"
|
|
3
|
-
import { AnyObject, Reducer, AnyFunc } from "./types"
|
|
4
|
-
import { isFunc, isArray } from "./utils"
|
|
5
|
-
|
|
6
|
-
export const qappend =
|
|
7
|
-
export const qassoc =
|
|
8
|
-
(prop: string, v: any, obj: AnyObject) => {
|
|
9
|
-
obj[prop] = v
|
|
10
|
-
return obj
|
|
11
|
-
}
|
|
12
|
-
)
|
|
13
|
-
export const qreduce =
|
|
14
|
-
(fn: Reducer, accum: any, arr: any[]) =>
|
|
15
|
-
arr.reduce(fn, accum)
|
|
16
|
-
)
|
|
17
|
-
// strategy is for arrays: 1->clean, 2->merge, 3->push.
|
|
18
|
-
const mergeDeep =
|
|
19
|
-
for(let k in o2) {
|
|
20
|
-
switch(type(o2[k])) {
|
|
21
|
-
case 'Array':
|
|
22
|
-
if(strategy>1 && type(o1[k])==='Array') {
|
|
23
|
-
switch(strategy) {
|
|
24
|
-
case 2:
|
|
25
|
-
const o1k = o1[k], o2k = o2[k]
|
|
26
|
-
for(const i in o2k) {
|
|
27
|
-
if(o1k[i]) {
|
|
28
|
-
mergeDeep(strategy, o1k[i], o2k[i])
|
|
29
|
-
} else {
|
|
30
|
-
o1k[i] = o2k[i]
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
break
|
|
34
|
-
case 3: o1[k].push(...o2[k])
|
|
35
|
-
default: break
|
|
36
|
-
}
|
|
37
|
-
} else {
|
|
38
|
-
o1[k] = o2[k]
|
|
39
|
-
}
|
|
40
|
-
break
|
|
41
|
-
case 'Object':
|
|
42
|
-
if(type(o1[k])==='Object') {
|
|
43
|
-
mergeDeep(strategy, o1[k], o2[k])
|
|
44
|
-
break
|
|
45
|
-
}
|
|
46
|
-
default:
|
|
47
|
-
o1[k] = o2[k]
|
|
48
|
-
break
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
return o1
|
|
52
|
-
})
|
|
53
|
-
export const qmergeDeep = mergeDeep(1)
|
|
54
|
-
export const qmergeDeepX = mergeDeep(2)
|
|
55
|
-
export const qmergeDeepAdd = mergeDeep(3)
|
|
56
|
-
/** qmapKeys({ a: 'b' }, { a: 44 }) -> { b: 44 } */
|
|
57
|
-
export const qmapKeys =
|
|
58
|
-
(
|
|
59
|
-
keyMap: {[oldKey: string]: string},
|
|
60
|
-
o: AnyObject
|
|
61
|
-
) => {
|
|
62
|
-
let k: string, mapped: string | AnyFunc, newKey: string, newValue: any
|
|
63
|
-
for(k in keyMap) {
|
|
64
|
-
mapped = keyMap[k]
|
|
65
|
-
;[newKey, newValue] = isFunc(mapped)
|
|
66
|
-
? (mapped as unknown as AnyFunc)(o)
|
|
67
|
-
: [mapped, o[k]]
|
|
68
|
-
o[newKey] = newValue
|
|
69
|
-
if(k !== newKey) {
|
|
70
|
-
delete o[k]
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
return o
|
|
74
|
-
}
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
export const qfilter =
|
|
78
|
-
(
|
|
79
|
-
cond: (v: any, k: string | number) => boolean,
|
|
80
|
-
data: any[] | AnyObject
|
|
81
|
-
) => {
|
|
82
|
-
const isArr = isArray(data)
|
|
83
|
-
for(let k in data) {
|
|
84
|
-
if(!cond(data[k], k)) {
|
|
85
|
-
if(isArr) {
|
|
86
|
-
data.splice(k, 1)
|
|
87
|
-
} else {
|
|
88
|
-
// TODO: handle Maps and Sets ?
|
|
89
|
-
delete data[k]
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return data
|
|
94
|
-
}
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
|
|
1
|
+
import { curry, curry2, curry3 } from "./curry"
|
|
2
|
+
import { type } from "./common"
|
|
3
|
+
import { AnyObject, Reducer, AnyFunc } from "./types"
|
|
4
|
+
import { isFunc, isArray } from "./utils"
|
|
5
|
+
|
|
6
|
+
export const qappend = curry2((s: any, xs: any[]) => {xs.push(s); return xs})
|
|
7
|
+
export const qassoc = curry3(
|
|
8
|
+
(prop: string, v: any, obj: AnyObject) => {
|
|
9
|
+
obj[prop] = v
|
|
10
|
+
return obj
|
|
11
|
+
}
|
|
12
|
+
)
|
|
13
|
+
export const qreduce = curry3(
|
|
14
|
+
(fn: Reducer, accum: any, arr: any[]) =>
|
|
15
|
+
arr.reduce(fn, accum)
|
|
16
|
+
)
|
|
17
|
+
// strategy is for arrays: 1->clean, 2->merge, 3->push.
|
|
18
|
+
const mergeDeep = curry3((strategy: 1|2|3, o1: AnyObject, o2: AnyObject): AnyObject => {
|
|
19
|
+
for(let k in o2) {
|
|
20
|
+
switch(type(o2[k])) {
|
|
21
|
+
case 'Array':
|
|
22
|
+
if(strategy>1 && type(o1[k])==='Array') {
|
|
23
|
+
switch(strategy) {
|
|
24
|
+
case 2:
|
|
25
|
+
const o1k = o1[k], o2k = o2[k]
|
|
26
|
+
for(const i in o2k) {
|
|
27
|
+
if(o1k[i]) {
|
|
28
|
+
mergeDeep(strategy, o1k[i], o2k[i])
|
|
29
|
+
} else {
|
|
30
|
+
o1k[i] = o2k[i]
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
break
|
|
34
|
+
case 3: o1[k].push(...o2[k])
|
|
35
|
+
default: break
|
|
36
|
+
}
|
|
37
|
+
} else {
|
|
38
|
+
o1[k] = o2[k]
|
|
39
|
+
}
|
|
40
|
+
break
|
|
41
|
+
case 'Object':
|
|
42
|
+
if(type(o1[k])==='Object') {
|
|
43
|
+
mergeDeep(strategy, o1[k], o2[k])
|
|
44
|
+
break
|
|
45
|
+
}
|
|
46
|
+
default:
|
|
47
|
+
o1[k] = o2[k]
|
|
48
|
+
break
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return o1
|
|
52
|
+
})
|
|
53
|
+
export const qmergeDeep = mergeDeep(1)
|
|
54
|
+
export const qmergeDeepX = mergeDeep(2)
|
|
55
|
+
export const qmergeDeepAdd = mergeDeep(3)
|
|
56
|
+
/** qmapKeys({ a: 'b' }, { a: 44 }) -> { b: 44 } */
|
|
57
|
+
export const qmapKeys = curry2(
|
|
58
|
+
(
|
|
59
|
+
keyMap: {[oldKey: string]: string},
|
|
60
|
+
o: AnyObject
|
|
61
|
+
) => {
|
|
62
|
+
let k: string, mapped: string | AnyFunc, newKey: string, newValue: any
|
|
63
|
+
for(k in keyMap) {
|
|
64
|
+
mapped = keyMap[k]
|
|
65
|
+
;[newKey, newValue] = isFunc(mapped)
|
|
66
|
+
? (mapped as unknown as AnyFunc)(o)
|
|
67
|
+
: [mapped, o[k]]
|
|
68
|
+
o[newKey] = newValue
|
|
69
|
+
if(k !== newKey) {
|
|
70
|
+
delete o[k]
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return o
|
|
74
|
+
}
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
export const qfilter = curry2(
|
|
78
|
+
(
|
|
79
|
+
cond: (v: any, k: string | number) => boolean,
|
|
80
|
+
data: any[] | AnyObject
|
|
81
|
+
) => {
|
|
82
|
+
const isArr = isArray(data)
|
|
83
|
+
for(let k in data) {
|
|
84
|
+
if(!cond(data[k], k)) {
|
|
85
|
+
if(isArr) {
|
|
86
|
+
data.splice(k, 1)
|
|
87
|
+
} else {
|
|
88
|
+
// TODO: handle Maps and Sets ?
|
|
89
|
+
delete data[k]
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return data
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
/** @deprecated */
|
|
97
|
+
export const qindexOf = curry2(
|
|
98
|
+
(x: any, xs: any[]) => xs.indexOf(x)
|
|
98
99
|
)
|