Skip to content
/ pine Public

Zero dependency Deno utility library with a FP bent

License

Notifications You must be signed in to change notification settings

AlexStory/pine

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

55 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pine 🍍

Utility library for deno with a FP bent.

You should be able to pull all functions straight from mod like import { take } from "https://deno.land/x/pine/mod.ts"

You can get the curried version of any function that takes more than one argument by importing it from mod.curried.ts instead.

I highly recommend looking at the test file for a function to see how to use it.

ex: import { take } from "https://deno.land/x/pine/mod.curried.ts"

stability

Most of the api should be pretty stable, but for now I would pin a version as I am planning to rewrite some of the function implementations, and add things like automatic currying.

functions implemented so far:

add

add(x: number, y: number): number

Returns the numbers added together

add(2, 3) == 5

all

all<T>(pred: (item: T) => boolean, list: T[]): boolean

Returns whether all items in list return true when applied to the function

all(x => x > 1, [2, 3, 4]) == true

any

any<T>(pred: (item: T) => boolean, list: T[]): boolean

Returns whether any item in the list returns true when applied to the function

any(x => x > 1, [0, 1, 2]) == true

chunkEvery

chunkEvery<T>(count: number, list: T[]): T[][]

Chunks the list by count excess are thrown away

chunkEvery(2, [1, 2, 3, 4, 5]) == [[1, 2], [3, 4]]

clamp

clamp(min: number, max: number, value: number): number

Returns a number bound between min and max

clamp(0, 10, 20) == 10

comp

comp<T, U, V>(first: (T) => U, second: (U) => V): (T) => V

Returns a function that is the same as if you took the output from first and then applied it to second

const inc = x => x + 1
const double = x => x * 2
const fun = comp(inc, double)
fun(2) === 6

contains

contains<T>(item: T, list: T[]): boolean

Returns whether an item is present in the list

contains(1, [1, 2, 3]) == true

curry

curry(func: Function): Function

Retuns a curried version of the function allowing you to partial apply it !! warning: curried functions lose their type

const curried = curry(add)
curried(1)(2) === 3

dec

dec(n: number): number

Returns one less than n

dec(3) == 2

enumerate

enumerate<T>(list: T[]): [number, T] []

Returns an array of tuples having the signature [index, item]

enumerate(['a', 'b', 'c']) == [[0, 'a'], [1, 'b'], [2, 'c']]

eq

eq<T>(x: T, y: T): Boolean

Returns wether two arguments are equal

eq(2, 2) === true

f

f(): boolean

Returns false

f() == false

filter

filter<T>(pred: (T) => bool, list: T[]): T[]

Returns all items in the list where T satisfies pred

filter(isEven, [1, 2, 3, 4]) == [2, 4]

first

first<T>(list: T[]): T[]

Returns all items in the array except the last one first([1, 2, 3]) == [1, 2]

flip

flip(fn: Function): Function

Takes a function with two parameters

Returns the function with the arguments reversed

fold

fold<T, U>(fn: (acc: U, x: T) => U, acc: U, list: T[]): U

Takes a reducer, an initial accumulator value, and a list of items. Applies the function on the accumulator, and each item of the list as it iterates through and returns the final accumulator.

fold(add, 0, [1, 2, 3]) == 6

frequencies

frequencies<T>(list: <T>): Map<T, number>

Returns a frequency table created from the list, in a Map data structure

frequencies([1, 1, 2, 2, 2], Map{ 1: 2, 2: 3})

gt

gt(x: number, y: number): boolean

Returns wether y is greater than x

gt(1, 2) === true

hasKey

hasKey(key: keyof any, obj: Object): boolean

Returns wether the object has the given key

hasKey("x", {x: 1}) == true

head

head<T>(list: T[]): T

Returns the first item in a list

head([1, 2, 3]) == 1

identity

identity<T>(item: T): T1

Returns the item passed in

identity(5) == 5

inc

inc(n: number): number

Returns one higher than n

inc(1) == 2

indexMap

indexMap<T, U>(fn: (i: number, item: T) => U, list: T[]): U

Runs a function for every item in the list supplying the index, and the item as arguments

indexMap((i, item) => i + item, [5, 5, 5]) == [5, 6, 7]

isEmpty

isEmpty<T>(list: T[]): boolean

Returns wether the given list is empty

isEmpty([]) == true

isEven

isEven(n: number): boolean

Returns wether the given number is even isEven(2) == true

isOdd

isOdd(n: number): boolean

Returns wether the given number is odd isOdd(3) == true

last

last<T>(list: T[]): T

Returns the last item in a list last([1, 3, 2]) == 2

length

length<T>(list: T[]): number

Returns the length of the list

length([1, 1, 1]) == 3

lt

lt(x: number, y: number): boolean

Returns wether y is less than x

lt(4, 1) === true

map

map<T, U>(fn: T => U, list: T[]): U

Applies a function to each item in a list, returning a new list of the results of each call

mapGet

mapGet<K, V>(key: K, map: Map<K, V>): V

Returns the value for the key key on the map. Throws an error if the key is not found

mapHas

mapHas<K, V>(key: K, map: Map<K, V>): boolean

Returns whether a map has the given key

mapSet

mapSet<K, V>(key: K, value: V, Map<K, V>): Map<K, V>

Returns a new map based off the one passed in with the key key set to value

max

max(x: number, y: number): number

Returns the larger of two numbers

max(2, 4) == 4

maxBy

maxBy<T>(fn: (item: T) => number, x: number, y: number): T

Returns then larger between x and y when applied to fn

const first = { x: 4 };
const second = { x: 5};
maxBy(o => o.x, first, second) == second

maximum

max(list: number[]): number

Returns the largest item in the list

maximum([1, 2, 3]) = 3

min

min(x: number, y: number): number

Returns the smaller of two numbers

min(2, 4) == 2

minBy

`minBy(fn: (item: T) => T, x: T, y: T): T

Returns the smaller of originals from applying the function to both items

const first = { x: 4 }
const second = { x: 5}
minBy(o => o.x, first, second) == first

minimum

minimum(list: number[]): number

Returns the smallest item in the list

minimum([1, 2, 3]) == 1

not

not(b: boolean): boolean

Returns the opposite of the applied boolean

not(true) == false

pipe

pipe(...fns: Array<(x: any) => any>): ((x: any) => any)

Pipes functions together chaining the output of each function into the next !! warning: currently pipe can't guarantee function typing at compile time

const addOne = (x) => x + 1
const double = (x) => x * 2
const addTwoThenDouble = pipe(addOne, addOne, double)
addTwoThenDouble(1) === 6

prop

prop(prop: string, obj: Record<string, unknown>): unknown

Returns the prop off of the object

prop('x', {x: 1}) === 1

range

range(start: number, stop: number): number[]

Returns an array of numbers from start to stop inclusive

range(1, 3) == [1, 2, 3]

reduce

reduce<T>(fn: (x: T, y: T) => T, list: T[]): T

Shorthand for call to fold where the initial value is the first item of the list, and iterates through the rest of the list

reduce(add, [1, 2, 3]) == 6

repeat

repeat<T>(count: number, item: T): T[]

Returns an array of count length with item repeated

`repeat(3, "apple") == ["apple", "apple", "apple"]

reverse

reverse<T>(list: T[]): T[]

Returns the list in the reversed order

reverse([1, 2, 3]) == [3, 2, 1]

scan

scan<T, U>(fn: (x: T) => U, init: U, list: T[]): U[]

Iterates over the list in the same way as fold, but saves all steps along the way.

scan(add, 0, [1, 2, 3]) == [0, 1, 3, 6]

sum

sum(list: number[]): number

Returns the sum of all numbers in list

sum([1, 2, 3]) === 6

sumby

sumBy<T>(fn: (item: T) => number, list: T[]): number

Returns the sum of applying fn to all items in list

const first = { x: 1};
const second = { x: 2};
const third = { x: 3 };
const list = [first, second, third];
sumBy(o => o.x, list) === 6

t

t(): boolean

Returns true t() == true

tail

tail<T>(list: T[]); T[]

Returns all items after the first in a list tail([1, 2, 3]) == [2, 3]

take

take<T>(count: number, list: T[]): T[]

Returns the first count items from a list

take(2, [1, 2, 3, 4, 5]) == [1, 2]

takeLast

takeLast<T>(count: number, list: T[]): T[]

Returns the last count items from a list

takeLast(2, [1, 2, 3, 4, 5]) == [4, 5]

takeWhile

takeWhile<T>(pred: (T) => boolean, list: T[]): T[]

Returns elements of the list until it first gets a false value from the predicate. Does not return the value that returned false

takeWhile(x => x < 2, [1, 1, 1, 3]) == [1, 1, 1]

zip

zip<T, U>(first: T[], second: U[]): [T, U][]

Zips two arrays together into an array of tuples. Extra items from the longer will be ignored

zip([1, 2, 3, 4], ["a", "b", "c"]) == [[1, "a"], [2, "b"], [3, "c"]]

TODO:

  • pipe/compose
  • more tests
  • automatic currying
  • Option/Result types
  • more tests
  • more tests
  • better way to handle type of functions

Contribute?

Want to send a pr? I'm pretty open. If you're adding a new function, it needs to do three things:

  • be in a new file
  • have a matching test file
  • export from mod