Skip to content

Commit 5f648af

Browse files
Merge pull request #25 from Jozty/dev-ch
add functions
2 parents b799838 + a27acf7 commit 5f648af

23 files changed

+464
-3
lines changed

allPass.ts

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import curryN from "./utils/curry_n.ts"
2+
import { Curry1, Func } from "./utils/types.ts"
3+
import { max } from './max.ts'
4+
import { pluck } from './pluck.ts'
5+
import { reduce } from './reduce.ts'
6+
7+
8+
function _allPass(preds: Array<any>) {
9+
let len = preds.length
10+
let fn = function(this: any) {
11+
for(let idx = 0; idx < len; idx++){
12+
if (!preds[idx].apply(this, arguments)) {
13+
return false
14+
}
15+
}
16+
return true
17+
}
18+
return curryN(reduce(max, 0, pluck('length', preds)), fn)
19+
}
20+
21+
/**
22+
* Takes a list of predicates and returns a predicate that returns true for a
23+
* given list of arguments if every one of the provided predicates is satisfied
24+
* by those arguments.
25+
*
26+
*/
27+
export const allPass: Curry1<Array<any>, Func> = curryN(1, _allPass)

and.ts

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import curryN from "./utils/curry_n.ts"
2+
import { Curry2 } from "./utils/types.ts"
3+
4+
function _and(a: any, b: any) {
5+
return a && b
6+
}
7+
8+
/**
9+
* Returns `true` if both arguments are `true`, `false` otherwise.
10+
*
11+
* Fae.and(true, true) //=> true
12+
* Fae.and(true, false) //=> false
13+
* Fae.and(false, true) //=> false
14+
* Fae.and(false, false) //=> false
15+
*/
16+
export const and: Curry2<any> = curryN(2, _and)

anyPass.ts

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import curryN from "./utils/curry_n.ts"
2+
import { Curry1, Func } from "./utils/types.ts"
3+
import { max } from './max.ts'
4+
import { pluck } from './pluck.ts'
5+
import { reduce } from './reduce.ts'
6+
7+
function _anyPass(preds: any) {
8+
let len = preds.length
9+
let fn = function(this: any) {
10+
for(let idx = 0; idx < len; idx++){
11+
if (preds[idx].apply(this, arguments)) {
12+
return true
13+
}
14+
}
15+
return false
16+
}
17+
return curryN(reduce(max, 0, pluck('length', preds)), fn)
18+
}
19+
20+
/**
21+
* Takes a list of predicates and returns a predicate that returns true for a
22+
* given list of arguments if at least one of the provided predicates is
23+
* satisfied by those arguments.
24+
*/
25+
export const anyPass: Curry1<any, Func> = curryN(1, _anyPass)

both.ts

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import curryN from "./utils/curry_n.ts"
2+
import { Func, Curry2 } from "./utils/types.ts"
3+
import { isFunction } from "./utils/is.ts"
4+
import { lift } from "./lift.ts"
5+
import { and } from "./and.ts"
6+
7+
function _both(f: Func, g: Func) {
8+
if(isFunction(f)){
9+
return function __both(this: any) {
10+
return f.apply(this, [...arguments]) && g.apply(this, [...arguments])
11+
}
12+
}
13+
else{
14+
lift(and)(f, g)
15+
}
16+
}
17+
/**
18+
* A function which calls the two provided functions and returns the `&&`
19+
* of the results.
20+
* It returns the result of the first function if it is false and the result
21+
* of the second function otherwise. Second function will not be invoked if the first returns a
22+
* false value.
23+
*
24+
*/
25+
export const both: Curry2<Func> = curryN(2, _both)

either.ts

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import curryN from "./utils/curry_n.ts"
2+
import { Func, Curry2 } from "./utils/types.ts"
3+
import { isFunction } from "./utils/is.ts"
4+
import { lift } from "./lift.ts"
5+
import { or } from "./or.ts"
6+
7+
function _either(f: Func, g: Func) {
8+
if(isFunction(f)){
9+
return function __either(this: any) {
10+
return f.apply(this, [...arguments]) || g.apply(this, [...arguments])
11+
}
12+
}
13+
else{
14+
lift(or)(f, g)
15+
}
16+
}
17+
18+
/**
19+
* A function wrapping calls to the two functions in an `||` operation,
20+
* returning the result of the first function if it is true and the result
21+
* of the second function otherwise. Second function will not be invoked if the first returns a
22+
* true value.
23+
*
24+
* const gt10 = x => x > 10
25+
* const even = x => (x & 1) === 0
26+
* const f = Fae.either(gt10, even)
27+
* f(101) //=> true
28+
* f(8) //=> true
29+
*
30+
*/
31+
export const either: Curry2<Func> = curryN(2, _either)

empty.ts

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Curry1 } from './utils/types.ts'
2+
import curryN from './utils/curry_n.ts'
3+
import { isArray, isString, isObject, isArguments } from './utils/is.ts'
4+
5+
function _empty(x: any) {
6+
if(x != null && typeof x.empty === 'function') return x.empty()
7+
8+
if(x != null && x.constructor != null && typeof x.constructor.empty === 'function') return x.constructor.empty()
9+
10+
if(isArray(x)) return []
11+
12+
if(isString(x)) return ''
13+
14+
if(isObject(x)) return {}
15+
16+
if(isArguments(x)) return (function() { return arguments }())
17+
}
18+
19+
20+
/**
21+
* Returns the empty value of its argument's type.
22+
* Dispatches to the `empty` method of the first argument, if present.
23+
*
24+
* Fae.empty([1, 2, 3]) //=> []
25+
* Fae.empty('unicorns') //=> ''
26+
* Fae.empty({x: 1, y: 2}) //=> {}
27+
*/
28+
export const empty: Curry1<any> = curryN(1, _empty)

isEmpty.ts

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { Curry1 } from './utils/types.ts'
2+
import curryN from './utils/curry_n.ts'
3+
import { empty } from './empty.ts'
4+
import { equals } from './equals.ts'
5+
6+
function _isEmpty(x: any) {
7+
return x != null && equals(x, empty(x))
8+
}
9+
10+
11+
/**
12+
* Returns `true` if the given value is its type's empty value, `false`
13+
* otherwise.
14+
*
15+
* Fae.isEmpty([1, 2, 3]) //=> false
16+
* Fae.isEmpty([]) //=> true
17+
* Fae.isEmpty('') //=> true
18+
* Fae.isEmpty(null) //=> false
19+
* Fae.isEmpty({}) //=> true
20+
*/
21+
export const isEmpty: Curry1<any, boolean> = curryN(1, _isEmpty)

mod.ts

+10
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,17 @@ export { add } from './add.ts'
1818
export { addIndex } from './addIndex.ts'
1919
export { adjust } from './adjust.ts'
2020
export { all } from './all.ts'
21+
export { allPass } from './allPass.ts'
2122
export { always } from './always.ts'
23+
export { and } from './and.ts'
2224
export { any } from './any.ts'
25+
export { anyPass } from './anyPass.ts'
2326
export { ap } from './ap.ts'
2427
export { aperture } from './aperture.ts'
2528
export { append } from './append.ts'
2629
export { assoc } from './assoc.ts'
2730
export { assocPath } from './assocPath.ts'
31+
export { both } from './both.ts'
2832
export { chain } from './chain.ts'
2933
export { clamp } from './clamp.ts'
3034
export { comparator } from './comparator.ts'
@@ -45,6 +49,8 @@ export { dropLastWhile } from './dropLastWhile.ts'
4549
export { dropRepeats } from './dropRepeats.ts'
4650
export { dropRepeatsWith } from './dropRepeatsWith.ts'
4751
export { dropWhile } from './dropWhile.ts'
52+
export { either } from './either.ts'
53+
export { empty } from './empty.ts'
4854
export { endsWith } from './endsWith.ts'
4955
export { eqProps } from './eqProps.ts'
5056
export { equals } from './equals.ts'
@@ -58,6 +64,7 @@ export { Pair, fromPairs } from './fromPairs.ts'
5864
export { identity } from './identity.ts'
5965
export { inc } from './inc.ts'
6066
export { insert } from './insert.ts'
67+
export { isEmpty } from './isEmpty.ts'
6168
export { join } from './join.ts'
6269
export {
6370
lens,
@@ -81,11 +88,13 @@ export { min } from './min.ts'
8188
export { multiply } from './multiply.ts'
8289
export { not } from './not.ts'
8390
export { nth } from './nth.ts'
91+
export { or } from './or.ts'
8492
export { over } from './over.ts'
8593
export { path } from './path.ts'
8694
export { pathOr } from './pathOr.ts'
8795
export { paths, Path } from './paths.ts'
8896
export { pipe } from './pipe.ts'
97+
export { pluck } from './pluck.ts'
8998
export { prepend } from './prepend.ts'
9099
export { prop } from './prop.ts'
91100
export { propEq } from './propEq.ts'
@@ -110,6 +119,7 @@ export { tap } from './tap.ts'
110119
export { transduce } from './transduce.ts'
111120
export { trim } from './trim.ts'
112121
export { typ } from './typ.ts'
122+
export { until } from './until.ts'
113123
export { update } from './update.ts'
114124
export { view } from './view.ts'
115125
export { when } from './when.ts'

or.ts

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import curryN from "./utils/curry_n.ts"
2+
import { Curry2 } from "./utils/types.ts"
3+
4+
function _or(a: any, b: any){
5+
return a || b
6+
}
7+
8+
/**
9+
* Returns `true` if one or both of its arguments are `true`. Returns `false`
10+
* if both arguments are `false`.
11+
*
12+
* Fae.or(true, true) //=> true
13+
* Fae.or(true, false) //=> true
14+
* Fae.or(false, true) //=> true
15+
* Fae.or(false, false) //=> false
16+
*/
17+
export const or: Curry2<any> = curryN(2, _or)

pluck.ts

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import curryN from "./utils/curry_n.ts"
2+
import { Functor, Curry2 } from "./utils/types.ts"
3+
import { map } from './map.ts'
4+
import { prop } from './prop.ts'
5+
6+
function _pluck(p: number | string, list: Array<any>) {
7+
return map(prop(p), list)
8+
}
9+
10+
/**
11+
* Returns a new list by plucking the same named property off all objects in
12+
* the list supplied.
13+
*
14+
* let getAges = Fae.pluck('age')
15+
* getAges([{name: 'shubham', age: 22}, {name: 'shivam', age: 23}]) //=> [22, 23]
16+
*
17+
* Fae.pluck(0, [[1, 2], [3, 4]]) //=> [1, 3]
18+
* Fae.pluck('val', {a: {val: 3}, b: {val: 5}}) //=> {a: 3, b: 5}
19+
*/
20+
export const pluck: Curry2<number | string, Array<any>, Array<any>> = curryN(2, _pluck)

specs/_describe.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export { expect } from 'https://deno.land/x/expect/expect.ts'
2-
export { assertStrictEq, AssertionError } from 'https://deno.land/std/testing/asserts.ts'
2+
export { assertStrictEquals, AssertionError } from 'https://deno.land/std/testing/asserts.ts'
33

44
interface It {
55
desc: string

specs/allPass.spec.ts

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { describe, it } from "./_describe.ts"
2+
import { allPass } from '../mod.ts'
3+
import { eq } from "./utils/utils.ts"
4+
5+
describe('allPass', () => {
6+
7+
let odd = (n: number) => (n & 1) == 1
8+
let lt20 = (n: number) => n < 20
9+
let gt5 = (n: number) => n > 5
10+
let plusEq = (w: number, x: number, y: number, z: number) => w + x === y + z
11+
12+
it('should report whether all predicates are satisfied by a given value', () => {
13+
let ok = allPass([odd, lt20, gt5])
14+
eq(ok(7), true)
15+
eq(ok(9), true)
16+
eq(ok(10), false)
17+
eq(ok(3), false)
18+
eq(ok(21), false)
19+
eq(allPass([odd, gt5, plusEq])(9, 9, 9, 9), true)
20+
eq(allPass([odd, gt5, plusEq])(9)(9)(9)(9), true)
21+
})
22+
23+
it('should return true on empty predicate list', () => {
24+
eq(allPass([])(3), true)
25+
})
26+
27+
})

specs/and.spec.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { describe, it } from "./_describe.ts"
2+
import { and } from '../mod.ts'
3+
import { eq } from "./utils/utils.ts"
4+
5+
describe('and', () => {
6+
7+
it('should compare two values properly', () => {
8+
eq(and(true, true), true)
9+
eq(and(true, false), false)
10+
eq(and(false, true), false)
11+
eq(and(false, false), false)
12+
eq(and(2, 1), 1)
13+
})
14+
15+
})

specs/anyPass.spec.ts

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { describe, it } from "./_describe.ts"
2+
import { anyPass } from '../mod.ts'
3+
import { eq } from "./utils/utils.ts"
4+
5+
describe('anyPass', () => {
6+
7+
let odd = (n: number) => (n & 1) == 1
8+
let gt20 = (n: number) => n > 20
9+
let lt5 = (n: number) => n < 5
10+
let plusEq = (w: number, x: number, y: number, z: number) => w + x === y + z
11+
12+
it('should report whether any predicates are satisfied by a given value', () => {
13+
let ok = anyPass([odd, gt20, lt5])
14+
eq(ok(7), true)
15+
eq(ok(9), true)
16+
eq(ok(10), false)
17+
eq(ok(18), false)
18+
eq(ok(3), true)
19+
eq(ok(22), true)
20+
eq(anyPass([odd, lt5, plusEq])(6, 7, 8, 9), false)
21+
eq(anyPass([odd, lt5, plusEq])(6)(7)(8)(9), false)
22+
})
23+
24+
it('should return false for an empty predicate list', () => {
25+
eq(anyPass([])(3), false)
26+
})
27+
28+
})

specs/both.spec.ts

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { describe, it } from "./_describe.ts"
2+
import { both } from '../mod.ts'
3+
import { eq } from "./utils/utils.ts"
4+
5+
describe('both', () => {
6+
7+
it('should combine two boolean-returning functions into one', () => {
8+
let even = (x: number) => (x & 1) == 0
9+
let gt10 = (x: number) => x > 10
10+
let f = both(even, gt10)
11+
eq(f(8), false)
12+
eq(f(13), false)
13+
eq(f(14), true)
14+
})
15+
16+
it('should accept functions that take multiple parameters', () => {
17+
let between = (a: number, b: number, c: number) => a < b && b < c
18+
let total20 = (a: number, b: number, c: number) => a + b + c === 20
19+
let f = both(between, total20)
20+
eq(f(4, 5, 11), true)
21+
eq(f(12, 2, 6), false)
22+
eq(f(5, 6, 15), false)
23+
})
24+
25+
})

0 commit comments

Comments
 (0)