New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@ebflat9/fp

Package Overview
Dependencies
Maintainers
1
Versions
160
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ebflat9/fp - npm Package Compare versions

Comparing version 1.1.17 to 1.1.19

18

index.js

@@ -69,6 +69,5 @@ import {

match,
maybe,
memoize,
multipy,
multipyRight,
multiply,
multiplyRight,
not,

@@ -83,3 +82,2 @@ once,

pluck,
pop,
pow,

@@ -89,3 +87,2 @@ prepend,

props,
push,
range,

@@ -99,3 +96,2 @@ reduceAsync,

setPropM,
shift,
some,

@@ -119,3 +115,2 @@ sortBy,

unary,
unshift,
zipMap,

@@ -268,7 +263,6 @@ } from './src/combinators.js'

Maybe,
maybe,
memoize,
memoizeIter,
multipy,
multipyRight,
multiply,
multiplyRight,
not,

@@ -287,3 +281,2 @@ Nothing,

pluck,
pop,
pow,

@@ -295,3 +288,2 @@ Prepend,

provided,
push,
range,

@@ -310,3 +302,2 @@ reactivize,

setPropM,
shift,
some,

@@ -337,3 +328,2 @@ sortBy,

unless,
unshift,
untilWith,

@@ -340,0 +330,0 @@ wrapWith,

{
"name": "@ebflat9/fp",
"version": "1.1.17",
"version": "1.1.19",
"description": "my fp utils",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -1,4 +0,12 @@

# My lil functional programming collection
# fp
Just a few functions I don't like re-writing. I am slowly adding tests, run with
`npm run test`.
My little functional programming library. Just a few functions I don't like
re-writing. I am slowly adding tests, run with `npm run test` and you should see
82 test passing.
Features:
- Many utility functions, such as `compose`, `pipe`, and `curry`.
- Some ADTs such as `Maybe`, `Result`, and `IO`
- A simple reactive library for `Observable`, including methods like `map`,
`filter`, and `reduce`.

@@ -1,8 +0,21 @@

// identity x returns x
/**
* Identity
* @param {any} x
* @return {any} x
*/
export const identity = x => x
// constant () => a
/**
* Constant
* @param {any} a
* @returns {any} a
*/
export const constant = a => b => a
// arity functions
/**
* Arity
* @param {function} fn
* @param {number} n - desired arity
* @returns {function} arity - Function fn with new arity
*/
export const arity = (fn, n) =>

@@ -12,7 +25,30 @@ function arity(...args) {

}
/**
* Unary
* @param {function} fn
* @returns {function} arity - Function with arity of 1
*/
export const unary = fn => arity(fn, 1)
/**
* Binary
* @param {function} fn
* @returns {function} arity - Function with arity of 2
*/
export const binary = fn => arity(fn, 2)
/**
* Ternary
* @param {function} fn
* @returns {function} arity - Function with arity of 3
*/
export const ternary = fn => arity(fn, 3)
// partial application
/**
* Call First
* @param {function} fn - Function to partially apply
* @param {any} larg - Leftmost argument
* @returns {function} callFirst - Function fn partially applied with larg
*/
export const callFirst = (fn, larg) =>

@@ -22,2 +58,9 @@ function callFirst(...args) {

}
/**
* Call Last
* @param {function} fn - Function to partially apply
* @param {any} rarg - Rightmost argument
* @returns {function} callLast - Function fn partially applied with rarg
*/
export const callLast = (fn, rarg) =>

@@ -28,19 +71,14 @@ function callLast(...args) {

// de-methodize
/**
* Demethodize
* @param {method} method - Method to demethodize
* @returns {function} method bound to use as regular function
*/
export const demethodize = Function.prototype.bind.bind(Function.prototype.call)
// typeof functions
const isTypeOf = a => b => typeof b === a
export const isNumber = isTypeOf('number')
export const isBoolean = isTypeOf('boolean')
export const isNull = x => x === null
export const isString = isTypeOf('string')
export const isObject = x => x !== null && typeof x === 'object'
export const isArray = a => Array.isArray(a)
export const isInstanceOf = a => b => b instanceof a
export const isFunction = f => f && typeof f === 'function'
export const isSet = s => s instanceof Set
export const isMap = m => m instanceof Map
// Len gets the length argument a
/**
* Len - provides a simple way to get the length/size of something
* @param {any} a
* @returns {number} {undefined} The length or size of the argument
*/
export const len = a =>

@@ -60,6 +98,24 @@ isString(a) || isArray(a) || isFunction(a)

}
/**
* Compose
* @param {function} Any number of functions fns to compose
* @returns {function} A function composed of fns
*/
export const compose = (...fns) => fns.reduce(compose2)
/**
* Pipe
* @param {function} fns to pipe
* @returns {function} A function pipe of fns
*/
export const pipe = (...fns) => fns.reduceRight(compose2)
// Autocurry
/**
* Curry
* @param {function} fn - Function to curry
* @returns {function} Partially applied function, or result of calling
* function fn if arguments are greater than or equal to total arity of
* function fn.
*/
export const curry = fn =>

@@ -76,8 +132,44 @@ function curryInner(...args1) {

// run a side effect with tap
/**
* Typeof Functions
* Provides several functions to test whether x is of type y
*/
const isTypeOf = a => b => typeof b === a
export const isNumber = isTypeOf('number')
export const isBoolean = isTypeOf('boolean')
export const isNull = x => x === null
export const isString = isTypeOf('string')
export const isObject = x => x !== null && typeof x === 'object'
export const isArray = a => Array.isArray(a)
export const isInstanceOf = curry((a, b) => b instanceof a)
export const isFunction = f => f && typeof f === 'function'
export const isSet = s => s instanceof Set
export const isMap = m => m instanceof Map
/**
* Tap
* @param {function} fn - Side effect to run
* @param {any} x - Value to return
*/
export const tap = curry((fn, x) => (fn(x), x))
// not and invert
/**
* Not
* @param {function} f - Function to negate
* @param {any} a - Argument for function f
*/
export const not = curry((f, a) => !f(a))
/**
* Invert
* @param {function} f - Function to reverse the sign of result
* @param {any} a - Argument for function f
*/
export const invert = curry((f, a) => -f(a))
/**
* Flip2
* @param {function} f - Function to flip arguments
* @returns {function} flip - Function f with arguments a and b flipped
*/
export const flip2 = f =>

@@ -87,2 +179,9 @@ curry(function flip(a, b) {

})
/**
* Flip3
* @param {function} f - Function to flip arguments
* @returns {function} flip - Function f with
* arguments a, b, c flipped to b, c, a.
*/
export const flip3 = f =>

@@ -93,4 +192,15 @@ curry(function flip(a, b, c) {

// Logging
/**
* Tee - Logs argument and returns it
* @param {any}
* @returns {any}
*/
export const tee = tap(console.log.bind(console))
/**
* Log
* @param {function} fn - Function to log
* @param {function} logger - Logging function
* @returns {function} log - Function fn with enhanced logging
*/
export const log = (fn, logger = console.log.bind(console)) =>

@@ -104,11 +214,32 @@ function log(...args) {

// creates a Transducer function
/**
* Transduce
* @param {array} arr - Array to reduce
* @param {array} fns - Array of functions to apply to arr
* @param {function} reducer - Reducer function to apply to arr
* @param {any} initial - Initial value to pass to reducer
*/
export const transduce = curry((arr, fns, reducer, initial) =>
arr.reduce(compose(...fns)(reducer), initial)
)
// Transducers
/**
* MapTR
* @param {function} fn - Create a transducer from map function
* @returns {function}
*/
export const mapTR = fn => reducer => (acc, val) => reducer(acc, fn(val))
/**
* filterTR
* @param {function} fn - Create a transducer from a filter function
* @returns {function}
*/
export const filterTR = fn => reducer => (acc, val) => fn(val) ? reducer(acc, val) : acc
// prop & props get object properties
/**
* Prop
* @param {string} name - Property name
* @param {object} a - Object to get property in
*/
export const prop = curry(

@@ -118,2 +249,10 @@ (name, a) =>

)
/**
* Send
* @param {string} name - Property name
* @param {any} args - Arguments to send to instance method
* @returns {function} send - Function send takes an instance and calls
* instance#name with args
*/
export const send =

@@ -123,2 +262,10 @@ (name, ...args) =>

instance[name].apply(instance, args)
/**
* Bound
* @param {name} name - Property name
* @param {any} args - Arguments to send to bound method
* @returns {function} {any} Returns bound method or bound method called with
* args
*/
export const bound = (name, ...args) =>

@@ -128,9 +275,40 @@ args === []

: instance => Function.prototype.bind.apply(instance[name], [instance].concat(args))
/**
* SetPropM
* @param {name} name - Property name
* @param {value} value - New value to set
* @param {object} a - Object to mutate with new value
* @returns {object} a
*/
export const setPropM = curry((name, value, a) =>
a && name in a ? ((a[name] = value), a) : a
)
/**
* SetProp
* @param {name} name - Property name
* @param {value} value - New value to set
* @param {object} a - Object to set value in
* @returns {object} Copy of a with new value set
*/
export const setProp = curry((name, value, a) =>
a && name in a ? { ...a, [name]: value } : { ...a }
)
/**
* Props
* @param {array} names - Array of property names
* @param {object} a - Object to get property names from
* @returns {array} Array of values
*/
export const props = curry((names, a) => names.map(n => prop(n, a)))
/**
* Invoke
* @param {function} fn - Function to invoke in new context
* @param {any} args - Argument for function fn
* @returns {function} invoke - Function which takes instance and calls fn with
* args in context of instance
*/
export const invoke =

@@ -141,2 +319,9 @@ (fn, ...args) =>

/**
* DeepProp
* @param {string} {array} path - A path of properties or an Array of
* properties to get
* @param {object} a - Object to get properties from
* @returns {any} Value of property access
*/
export const deepProp = curry((path, a) => {

@@ -148,2 +333,7 @@ if (!Array.isArray(path)) path = path.split('.')

/**
* Stringifying functions
* Provides helper functions to stringify and parse JSON, along with numbers
* and strings
*/
export const toJSON = x => JSON.stringify(x)

@@ -162,3 +352,6 @@ export const fromJSON = x => JSON.parse(x)

// map, filter, reduce
/**
* Monad-related functions
* Provides functions to help when working with Monads, such as Array
*/
export const forEach = curry((f, M) => M.forEach(f))

@@ -176,4 +369,2 @@ export const map = curry((f, M) => M.map(f))

}
// compose monads
export const composeM2 = (f, g) =>

@@ -184,3 +375,6 @@ function innerComposeM2(...args) {

export const composeM = (...Ms) => Ms.reduce(composeM2)
export const liftA2 = curry((fn, a1, a2) => a1.map(fn).ap(a2))
export const liftA3 = curry((fn, a1, a2, a3) => a1.map(fn).ap(a2).ap(a3))
export const liftA4 = curry((fn, a1, a2, a3, a4) => a1.map(fn).ap(a2).ap(a3).ap(a4))
export const apply = curry((fn, F) => map.call(F, fn))
export const composeAsync2 = (f, g) =>

@@ -190,7 +384,2 @@ async function innerComposeAsync(...args) {

}
export const liftA2 = curry((fn, a1, a2) => a1.map(fn).ap(a2))
export const liftA3 = curry((fn, a1, a2, a3) => a1.map(fn).ap(a2).ap(a3))
export const liftA4 = curry((fn, a1, a2, a3, a4) => a1.map(fn).ap(a2).ap(a3).ap(a4))
export const apply = curry((fn, F) => map.call(F, fn))
export const composeAsync = (...fns) => fns.reduce(composeAsync2)

@@ -203,4 +392,2 @@ export const pipeAsync = (...fns) => fns.reduceRight(composeAsync2)

await mapAsync(f, a).then(bools => a.filter((_, i) => Boolean(bools[i])))
// flat
export const flat = M => M.flat()

@@ -211,3 +398,6 @@ export const flatMap = curry((f, M) => M.flatMap(f))

// math functions
/**
* Math functions
* Provides a set of functions for common math operations
*/
export const eq = curry((a, b) => a === b)

@@ -218,4 +408,4 @@ export const add = curry((x, y) => x + y)

export const subtractRight = curry((x, y) => y - x)
export const multipy = curry((x, y) => x * y)
export const multipyRight = curry((x, y) => y * x)
export const multiply = curry((x, y) => x * y)
export const multiplyRight = curry((x, y) => y * x)
export const divide = curry((x, y) => x / y)

@@ -227,3 +417,6 @@ export const divideRight = curry((x, y) => y / x)

// array functions
/**
* Array functions
* Provides a set of functions for common array operations
*/
export const head = a => a[0]

@@ -236,6 +429,2 @@ export const last = a => a[a.length - 1]

export const average = ns => sum(...ns) / ns.length
export const shift = arr => [arr[0], arr.slice(1)]
export const pop = arr => [arr.slice(0, -1), arr[arr.length - 1]]
export const unshift = curry((arr, v) => [v].concat(arr))
export const push = curry((arr, v) => arr.concat(v))
export const partition = (arr, a, b) =>

@@ -263,2 +452,8 @@ arr.reduce(

/**
* TryCatch
* @param {function} f - Try function, may throw
* @param {function} g - Catch function, to catch error
* @returns {any} Calls g if function f throws
*/
export const tryCatch = curry((f, g) => {

@@ -272,10 +467,10 @@ try {

export const maybe = fn =>
function maybe(...args) {
return args.reduce((acc, cv) => acc && cv != null, true)
? fn.apply(this, args)
: void 0
}
// range
/**
* Range
* @param {number} start
* @param {number} end
* @param {number} step
* @returns {array} result - An array of numbers from start to end, spaced by
* step
*/
export const range = (start, end, step = start < end ? 1 : -1) => {

@@ -292,3 +487,8 @@ let index = -1

// once only runs a function once, then returns cached result
/**
* Once
* @param {function} fn - Function to run only once
* @returns {function} once - Function fn will be called once, and thereafter
* will return the cached result of the call
*/
export function once(fn) {

@@ -302,3 +502,7 @@ let done = false

// memoize a function
/**
* Memoize
* @param {function} fn - Function to memoize
* @returns {function} memorize - Memoized function fn
*/
export function memoize(fn) {

@@ -315,3 +519,8 @@ const cache = Object.create(null)

// debounce
/**
* Debounce
* @param {number} delay - Amount of time to debounce
* @returns {function} debounce - Function which takes an argument fn, which is
* a function to debounce
*/
export const debounce = delay => {

@@ -325,3 +534,8 @@ let pending = false

// accumulate
/**
* Accumulate
* @param {number} delay - Amount of time to delay result
* @returns {function} accumulate - Function which takes argument fn,
* a function that will be called with all accumulated events after delay
*/
export const accumulate = delay => {

@@ -343,3 +557,9 @@ const stack = []

// Object functions
/**
* FunctionalMixin
* @param {object} behaviour - Desired mixin behaviour
* @param {object} sharedBehaviour - Desired behaviour to add to prototype
* @returns {function} mixin - Function which takes argument target, which is
* the object to mix behaviour into
*/
export const FunctionalMixin = (behaviour, sharedBehaviour = {}) => {

@@ -434,2 +654,7 @@ const instanceKeys = Reflect.ownKeys(behaviour)

/**
* DeepFreeze
* @param {object} obj - Object to deep freeze
* @returns {object} obj - Object that was deep frozen
*/
export const deepFreeze = obj => {

@@ -443,2 +668,7 @@ if (obj && typeof obj === 'object' && !Object.isFrozen(obj)) {

/**
* DeepCopy
* @param {object} obj - Object to deep copy
* @returns {object} aux - Copy of Object obj
*/
export const deepCopy = obj => {

@@ -453,2 +683,8 @@ let aux = obj

Object.deepFreeze = Object.deepFreeze || deepFreeze
/**
* Immutate
* @param {object} Object to seal and deep freeze
* @returns {object} Object that is sealed and deep frozen
*/
export const immutable = compose(Object.seal, Object.deepFreeze)
import * as combinators from '../src/combinators.js'
import { describe, it } from 'mocha'
import { strict as assert } from 'assert'
import { AssertionError } from 'assert/strict'

@@ -366,2 +367,244 @@ describe('Combinators', function () {

})
describe('padStart', function () {
it('should pad the start of a string', function () {
assert.equal(combinators.padStart(1, 3, ' '), ' 1')
assert.equal(combinators.padStart('', 5, 'hi'), 'hihih')
})
})
describe('padEnd', function () {
it('should pad the end of a string', function () {
assert.equal(combinators.padEnd(1, 3, ' '), '1 ')
assert.equal(combinators.padEnd('', 3, 'a'), 'aaa')
})
})
describe('forEach', function () {
it('should call M#forEach', function () {
combinators.forEach(num => assert.equal(num, 1))([1, 1, 1, 1])
})
})
describe('map', function () {
it('should call M#map', function () {
const square = combinators.map(num => num * num)([1, 2, 3])
assert.deepEqual(square, [1, 4, 9])
})
})
describe('filter', function () {
it('should call M#filter', function () {
const evens = combinators.filter(n => n % 2 === 0)([1, 2, 3, 4, 5])
assert.deepEqual(evens, [2, 4])
})
})
describe('reduce', function () {
it('should call M#reduce', function () {
const result = combinators.reduce((acc, cv) => acc + cv, 0)([1, 2, 3, 4, 5])
assert.equal(result, 15)
})
it('should call M#reduceRight', function () {
const result = combinators.reduceRight((acc, cv) => acc + cv, 0)([1, 2, 3, 4, 5])
assert.equal(result, 15)
})
})
describe('pluck', function () {
it('should plunk object keys', function () {
const arr = [{ name: 'bob' }, { name: 'tim' }]
assert.deepEqual(combinators.pluck('name')(arr), ['bob', 'tim'])
})
})
describe('deepMap', function () {
it('should deeply map nested arrays', function () {
const arr = [[1], [[3], [4, [5]]]]
assert.deepEqual(combinators.deepMap(x => x * x)(arr), [[1], [[9], [16, [25]]]])
})
})
describe('composeM2', function () {
it('should compose two monads', function () {
const fn = x => [x]
assert.deepEqual(combinators.composeM2(fn, fn)('hi'), ['hi'])
})
})
describe('composeAsync2', function () {
it('should compose two async functions', function (done) {
const a = x => new Promise(resolve => setTimeout(() => resolve(x), 0))
const b = x => new Promise(resolve => setTimeout(() => resolve(x), 1))
const c = async x => await combinators.composeAsync2(a, b)
;(async () => assert.equal(await c(5), 5), done())()
})
})
describe('math functions', function () {
it('should perform strict equality test', function () {
assert.equal(combinators.eq(1, 1), true)
assert.equal(combinators.eq({}, {}), false)
})
it('should add numbers', function () {
assert.equal(combinators.add(5)(6), 11)
assert.equal(combinators.addRight(5)(6), 11)
})
it('should subtract numbers', function () {
assert.equal(combinators.subtract(5)(4), 1)
assert.equal(combinators.subtract(4)(5), -1)
assert.equal(combinators.subtractRight(4)(5), 1)
assert.equal(combinators.subtractRight(5)(4), -1)
})
it('should multiply numbers', function () {
assert.equal(combinators.multiply(3)(3), 9)
assert.equal(combinators.multiplyRight(5)(3), 15)
})
it('should divide numbers', function () {
assert.equal(combinators.divide(5)(2), 2.5)
assert.equal(combinators.divide(2)(2), 1)
assert.equal(combinators.divide(2)(0), Infinity)
})
})
describe('roundTo', function () {
it('should round to N places', function () {
assert.equal(combinators.roundTo(2)(5.234), 5.23)
})
})
describe('pow', function () {
it('should multiply base by itself exponent times', function () {
assert.equal(combinators.pow(10, 2), 100)
assert.equal(combinators.pow(2, 10), 1024)
})
})
describe('array functions', function () {
it('should take the head of an array', function () {
assert.equal(combinators.head([1, 2, 3]), 1)
})
it('should take the last of an array', function () {
assert.equal(combinators.last([1, 2, 3]), 3)
})
it('should call A#every', function () {
assert.equal(combinators.every(x => x > 1)([2, 3, 4]), true)
})
it('should call A#some', function () {
assert.equal(combinators.some(x => x > 2)([1, 2, 3]), true)
})
it('should call A#find', function () {
const arr = [{ name: 'bob' }, { name: 'tim' }]
assert.equal(combinators.find(x => x.name === 'tim')(arr), arr[1])
})
it('should sum all arguments', function () {
assert.equal(combinators.sum(1, 2, 3, 4, 5), 15)
})
it('should average array', function () {
assert.equal(combinators.average([1, 2, 3]), 2)
})
it('should partition an array based on two functions', function () {
const odd = x => x % 2 !== 0
const even = x => !odd(x)
assert.deepEqual(combinators.partition([1, 2, 3, 4], even, odd), [
[2, 4],
[1, 3],
])
})
})
describe('zipMap', function () {
it('should zip up iterables and map', function () {
assert.deepEqual(
combinators.zipMap((...args) => args.map(x => x * x), [1, 2, 3], [4, 5, 6]),
[
[1, 16],
[4, 25],
[9, 36],
]
)
})
})
describe('sortBy', function () {
it('should sortBy function f without mutating array', function () {
const arr = [1, 2, 3]
const sorter = (a, b) => b - a
assert.deepEqual(combinators.sortBy(sorter)(arr), [3, 2, 1])
assert.notEqual(combinators.sortBy(sorter)(arr), arr)
})
})
describe('match', function () {
it('should match a regexp to a string', function () {
const re = new RegExp('\\s+')
const str = ' '
assert.equal(combinators.match(re, str), true)
})
})
describe('replace', function () {
it('should replace a match with replacer', function () {
assert.equal(combinators.replace('hi', 'hello')('hi world'), 'hello world')
})
})
describe('split', function () {
it('should split by sep', function () {
assert.deepEqual(combinators.split('|', 'hi|there'), ['hi', 'there'])
})
})
describe('tryCatch', function () {
it('should call catcher function if try function throws', function () {
let result
combinators.tryCatch(
() => {
throw new Error('testing')
},
err => (result = err.message)
)
assert.equal(result, 'testing')
// try one without throwing error
combinators.tryCatch(
() => (result = 'hello'),
() => {}
)
assert.equal(result, 'hello')
})
})
describe('range', function () {
it('should eagerly provide a range of numbers', function () {
const nums = combinators.range(1, 10)
assert.deepEqual(nums, [1, 2, 3, 4, 5, 6, 7, 8, 9])
})
it('should count down if negative step', function () {
const nums = combinators.range(9, 0, -1)
assert.deepEqual(nums, [9, 8, 7, 6, 5, 4, 3, 2, 1])
})
})
describe('once', function () {
it('should call function only once', function () {
let result = 1
const x = combinators.once(n => (result += n))
x(5)
x(4)
assert.equal(result, 6)
assert.equal(x(), 6)
})
})
describe('immutate', function () {
it('should not allow changing properties', function () {
const obj = combinators.immutable({ greeting: 'hi' })
assert.throws(() => (obj.greeting = 'hello'))
})
it('should not allow extending object', function () {
const obj = combinators.immutable({ greeting: 'hi' })
assert.throws(() => (obj.method = () => {}))
})
})
})

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc