Skip to content

Commit

Permalink
Merge pull request #25 from Jozty/dev-ch
Browse files Browse the repository at this point in the history
add functions
  • Loading branch information
singla-shivam authored Jun 10, 2020
2 parents b799838 + a27acf7 commit 5f648af
Show file tree
Hide file tree
Showing 23 changed files with 464 additions and 3 deletions.
27 changes: 27 additions & 0 deletions allPass.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import curryN from "./utils/curry_n.ts"
import { Curry1, Func } from "./utils/types.ts"
import { max } from './max.ts'
import { pluck } from './pluck.ts'
import { reduce } from './reduce.ts'


function _allPass(preds: Array<any>) {
let len = preds.length
let fn = function(this: any) {
for(let idx = 0; idx < len; idx++){
if (!preds[idx].apply(this, arguments)) {
return false
}
}
return true
}
return curryN(reduce(max, 0, pluck('length', preds)), fn)
}

/**
* Takes a list of predicates and returns a predicate that returns true for a
* given list of arguments if every one of the provided predicates is satisfied
* by those arguments.
*
*/
export const allPass: Curry1<Array<any>, Func> = curryN(1, _allPass)
16 changes: 16 additions & 0 deletions and.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import curryN from "./utils/curry_n.ts"
import { Curry2 } from "./utils/types.ts"

function _and(a: any, b: any) {
return a && b
}

/**
* Returns `true` if both arguments are `true`, `false` otherwise.
*
* Fae.and(true, true) //=> true
* Fae.and(true, false) //=> false
* Fae.and(false, true) //=> false
* Fae.and(false, false) //=> false
*/
export const and: Curry2<any> = curryN(2, _and)
25 changes: 25 additions & 0 deletions anyPass.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import curryN from "./utils/curry_n.ts"
import { Curry1, Func } from "./utils/types.ts"
import { max } from './max.ts'
import { pluck } from './pluck.ts'
import { reduce } from './reduce.ts'

function _anyPass(preds: any) {
let len = preds.length
let fn = function(this: any) {
for(let idx = 0; idx < len; idx++){
if (preds[idx].apply(this, arguments)) {
return true
}
}
return false
}
return curryN(reduce(max, 0, pluck('length', preds)), fn)
}

/**
* Takes a list of predicates and returns a predicate that returns true for a
* given list of arguments if at least one of the provided predicates is
* satisfied by those arguments.
*/
export const anyPass: Curry1<any, Func> = curryN(1, _anyPass)
25 changes: 25 additions & 0 deletions both.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import curryN from "./utils/curry_n.ts"
import { Func, Curry2 } from "./utils/types.ts"
import { isFunction } from "./utils/is.ts"
import { lift } from "./lift.ts"
import { and } from "./and.ts"

function _both(f: Func, g: Func) {
if(isFunction(f)){
return function __both(this: any) {
return f.apply(this, [...arguments]) && g.apply(this, [...arguments])
}
}
else{
lift(and)(f, g)
}
}
/**
* A function which calls the two provided functions and returns the `&&`
* of the results.
* It returns the result of the first function if it is false and the result
* of the second function otherwise. Second function will not be invoked if the first returns a
* false value.
*
*/
export const both: Curry2<Func> = curryN(2, _both)
31 changes: 31 additions & 0 deletions either.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import curryN from "./utils/curry_n.ts"
import { Func, Curry2 } from "./utils/types.ts"
import { isFunction } from "./utils/is.ts"
import { lift } from "./lift.ts"
import { or } from "./or.ts"

function _either(f: Func, g: Func) {
if(isFunction(f)){
return function __either(this: any) {
return f.apply(this, [...arguments]) || g.apply(this, [...arguments])
}
}
else{
lift(or)(f, g)
}
}

/**
* A function wrapping calls to the two functions in an `||` operation,
* returning the result of the first function if it is true and the result
* of the second function otherwise. Second function will not be invoked if the first returns a
* true value.
*
* const gt10 = x => x > 10
* const even = x => (x & 1) === 0
* const f = Fae.either(gt10, even)
* f(101) //=> true
* f(8) //=> true
*
*/
export const either: Curry2<Func> = curryN(2, _either)
28 changes: 28 additions & 0 deletions empty.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Curry1 } from './utils/types.ts'
import curryN from './utils/curry_n.ts'
import { isArray, isString, isObject, isArguments } from './utils/is.ts'

function _empty(x: any) {
if(x != null && typeof x.empty === 'function') return x.empty()

if(x != null && x.constructor != null && typeof x.constructor.empty === 'function') return x.constructor.empty()

if(isArray(x)) return []

if(isString(x)) return ''

if(isObject(x)) return {}

if(isArguments(x)) return (function() { return arguments }())
}


/**
* Returns the empty value of its argument's type.
* Dispatches to the `empty` method of the first argument, if present.
*
* Fae.empty([1, 2, 3]) //=> []
* Fae.empty('unicorns') //=> ''
* Fae.empty({x: 1, y: 2}) //=> {}
*/
export const empty: Curry1<any> = curryN(1, _empty)
21 changes: 21 additions & 0 deletions isEmpty.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Curry1 } from './utils/types.ts'
import curryN from './utils/curry_n.ts'
import { empty } from './empty.ts'
import { equals } from './equals.ts'

function _isEmpty(x: any) {
return x != null && equals(x, empty(x))
}


/**
* Returns `true` if the given value is its type's empty value, `false`
* otherwise.
*
* Fae.isEmpty([1, 2, 3]) //=> false
* Fae.isEmpty([]) //=> true
* Fae.isEmpty('') //=> true
* Fae.isEmpty(null) //=> false
* Fae.isEmpty({}) //=> true
*/
export const isEmpty: Curry1<any, boolean> = curryN(1, _isEmpty)
10 changes: 10 additions & 0 deletions mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@ export { add } from './add.ts'
export { addIndex } from './addIndex.ts'
export { adjust } from './adjust.ts'
export { all } from './all.ts'
export { allPass } from './allPass.ts'
export { always } from './always.ts'
export { and } from './and.ts'
export { any } from './any.ts'
export { anyPass } from './anyPass.ts'
export { ap } from './ap.ts'
export { aperture } from './aperture.ts'
export { append } from './append.ts'
export { assoc } from './assoc.ts'
export { assocPath } from './assocPath.ts'
export { both } from './both.ts'
export { chain } from './chain.ts'
export { clamp } from './clamp.ts'
export { comparator } from './comparator.ts'
Expand All @@ -45,6 +49,8 @@ export { dropLastWhile } from './dropLastWhile.ts'
export { dropRepeats } from './dropRepeats.ts'
export { dropRepeatsWith } from './dropRepeatsWith.ts'
export { dropWhile } from './dropWhile.ts'
export { either } from './either.ts'
export { empty } from './empty.ts'
export { endsWith } from './endsWith.ts'
export { eqProps } from './eqProps.ts'
export { equals } from './equals.ts'
Expand All @@ -58,6 +64,7 @@ export { Pair, fromPairs } from './fromPairs.ts'
export { identity } from './identity.ts'
export { inc } from './inc.ts'
export { insert } from './insert.ts'
export { isEmpty } from './isEmpty.ts'
export { join } from './join.ts'
export {
lens,
Expand All @@ -81,11 +88,13 @@ export { min } from './min.ts'
export { multiply } from './multiply.ts'
export { not } from './not.ts'
export { nth } from './nth.ts'
export { or } from './or.ts'
export { over } from './over.ts'
export { path } from './path.ts'
export { pathOr } from './pathOr.ts'
export { paths, Path } from './paths.ts'
export { pipe } from './pipe.ts'
export { pluck } from './pluck.ts'
export { prepend } from './prepend.ts'
export { prop } from './prop.ts'
export { propEq } from './propEq.ts'
Expand All @@ -110,6 +119,7 @@ export { tap } from './tap.ts'
export { transduce } from './transduce.ts'
export { trim } from './trim.ts'
export { typ } from './typ.ts'
export { until } from './until.ts'
export { update } from './update.ts'
export { view } from './view.ts'
export { when } from './when.ts'
Expand Down
17 changes: 17 additions & 0 deletions or.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import curryN from "./utils/curry_n.ts"
import { Curry2 } from "./utils/types.ts"

function _or(a: any, b: any){
return a || b
}

/**
* Returns `true` if one or both of its arguments are `true`. Returns `false`
* if both arguments are `false`.
*
* Fae.or(true, true) //=> true
* Fae.or(true, false) //=> true
* Fae.or(false, true) //=> true
* Fae.or(false, false) //=> false
*/
export const or: Curry2<any> = curryN(2, _or)
20 changes: 20 additions & 0 deletions pluck.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import curryN from "./utils/curry_n.ts"
import { Functor, Curry2 } from "./utils/types.ts"
import { map } from './map.ts'
import { prop } from './prop.ts'

function _pluck(p: number | string, list: Array<any>) {
return map(prop(p), list)
}

/**
* Returns a new list by plucking the same named property off all objects in
* the list supplied.
*
* let getAges = Fae.pluck('age')
* getAges([{name: 'shubham', age: 22}, {name: 'shivam', age: 23}]) //=> [22, 23]
*
* Fae.pluck(0, [[1, 2], [3, 4]]) //=> [1, 3]
* Fae.pluck('val', {a: {val: 3}, b: {val: 5}}) //=> {a: 3, b: 5}
*/
export const pluck: Curry2<number | string, Array<any>, Array<any>> = curryN(2, _pluck)
2 changes: 1 addition & 1 deletion specs/_describe.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export { expect } from 'https://deno.land/x/expect/expect.ts'
export { assertStrictEq, AssertionError } from 'https://deno.land/std/testing/asserts.ts'
export { assertStrictEquals, AssertionError } from 'https://deno.land/std/testing/asserts.ts'

interface It {
desc: string
Expand Down
27 changes: 27 additions & 0 deletions specs/allPass.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { describe, it } from "./_describe.ts"
import { allPass } from '../mod.ts'
import { eq } from "./utils/utils.ts"

describe('allPass', () => {

let odd = (n: number) => (n & 1) == 1
let lt20 = (n: number) => n < 20
let gt5 = (n: number) => n > 5
let plusEq = (w: number, x: number, y: number, z: number) => w + x === y + z

it('should report whether all predicates are satisfied by a given value', () => {
let ok = allPass([odd, lt20, gt5])
eq(ok(7), true)
eq(ok(9), true)
eq(ok(10), false)
eq(ok(3), false)
eq(ok(21), false)
eq(allPass([odd, gt5, plusEq])(9, 9, 9, 9), true)
eq(allPass([odd, gt5, plusEq])(9)(9)(9)(9), true)
})

it('should return true on empty predicate list', () => {
eq(allPass([])(3), true)
})

})
15 changes: 15 additions & 0 deletions specs/and.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { describe, it } from "./_describe.ts"
import { and } from '../mod.ts'
import { eq } from "./utils/utils.ts"

describe('and', () => {

it('should compare two values properly', () => {
eq(and(true, true), true)
eq(and(true, false), false)
eq(and(false, true), false)
eq(and(false, false), false)
eq(and(2, 1), 1)
})

})
28 changes: 28 additions & 0 deletions specs/anyPass.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { describe, it } from "./_describe.ts"
import { anyPass } from '../mod.ts'
import { eq } from "./utils/utils.ts"

describe('anyPass', () => {

let odd = (n: number) => (n & 1) == 1
let gt20 = (n: number) => n > 20
let lt5 = (n: number) => n < 5
let plusEq = (w: number, x: number, y: number, z: number) => w + x === y + z

it('should report whether any predicates are satisfied by a given value', () => {
let ok = anyPass([odd, gt20, lt5])
eq(ok(7), true)
eq(ok(9), true)
eq(ok(10), false)
eq(ok(18), false)
eq(ok(3), true)
eq(ok(22), true)
eq(anyPass([odd, lt5, plusEq])(6, 7, 8, 9), false)
eq(anyPass([odd, lt5, plusEq])(6)(7)(8)(9), false)
})

it('should return false for an empty predicate list', () => {
eq(anyPass([])(3), false)
})

})
25 changes: 25 additions & 0 deletions specs/both.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { describe, it } from "./_describe.ts"
import { both } from '../mod.ts'
import { eq } from "./utils/utils.ts"

describe('both', () => {

it('should combine two boolean-returning functions into one', () => {
let even = (x: number) => (x & 1) == 0
let gt10 = (x: number) => x > 10
let f = both(even, gt10)
eq(f(8), false)
eq(f(13), false)
eq(f(14), true)
})

it('should accept functions that take multiple parameters', () => {
let between = (a: number, b: number, c: number) => a < b && b < c
let total20 = (a: number, b: number, c: number) => a + b + c === 20
let f = both(between, total20)
eq(f(4, 5, 11), true)
eq(f(12, 2, 6), false)
eq(f(5, 6, 15), false)
})

})
Loading

0 comments on commit 5f648af

Please sign in to comment.