Security News
The Unpaid Backbone of Open Source: Solo Maintainers Face Increasing Security Demands
Solo open source maintainers face burnout and security challenges, with 60% unpaid and 60% considering quitting.
Rambda is a lightweight and fast utility library that provides a variety of functions for functional programming in JavaScript. It is a smaller and faster alternative to Ramda, offering a similar API but with a focus on performance and simplicity.
Currying
Currying is a technique of evaluating functions with multiple arguments, one at a time. Rambda's `curry` function allows you to transform a function so that it can be called with fewer arguments than it expects, returning a new function that takes the remaining arguments.
const R = require('rambda');
const add = R.curry((a, b) => a + b);
const add5 = add(5);
console.log(add5(3)); // 8
Composition
Function composition is the process of combining two or more functions to produce a new function. Rambda's `compose` function allows you to create a pipeline of functions that are executed from right to left.
const R = require('rambda');
const add = (a, b) => a + b;
const multiply = (a, b) => a * b;
const addAndMultiply = R.compose(R.multiply(2), R.add(3));
console.log(addAndMultiply(4)); // 14
Cloning
Cloning is the process of creating a deep copy of an object. Rambda's `clone` function allows you to create a deep copy of an object, ensuring that changes to the new object do not affect the original object.
const R = require('rambda');
const obj = {a: 1, b: 2};
const clonedObj = R.clone(obj);
console.log(clonedObj); // {a: 1, b: 2}
Filtering
Filtering is the process of selecting a subset of items from a collection based on a predicate function. Rambda's `filter` function allows you to filter elements in an array or object based on a provided predicate.
const R = require('rambda');
const isEven = n => n % 2 === 0;
const numbers = [1, 2, 3, 4, 5, 6];
const evenNumbers = R.filter(isEven, numbers);
console.log(evenNumbers); // [2, 4, 6]
Mapping
Mapping is the process of transforming each item in a collection using a provided function. Rambda's `map` function allows you to apply a function to each element in an array or object, returning a new array or object with the transformed elements.
const R = require('rambda');
const double = n => n * 2;
const numbers = [1, 2, 3, 4, 5];
const doubledNumbers = R.map(double, numbers);
console.log(doubledNumbers); // [2, 4, 6, 8, 10]
Lodash is a popular utility library that provides a wide range of functions for common programming tasks. It is more feature-rich compared to Rambda but also larger in size. Lodash focuses on performance and ease of use, offering a comprehensive set of tools for working with arrays, objects, strings, and more.
Underscore is another utility library that provides a variety of functional programming helpers. It is similar to Lodash but with a smaller footprint and fewer features. Underscore offers a core set of functions for working with collections, arrays, objects, and functions, making it a good choice for projects that need a lightweight utility library.
Ramda is a functional programming library for JavaScript that emphasizes immutability and pure functions. It offers a similar API to Rambda but with a larger set of functions and a focus on functional programming principles. Ramda is more feature-rich but also larger in size compared to Rambda.
Faster alternative to Ramda in just 7kB
I admire Ramda as it is great library in what it does, but I used only small part of what it offers.
I wanted to optimize the size of my bundle, but already developed Ramda habits.
This lead me to the idea to recreate the funtionality of some Ramda methods and export that as library.
const R = require("rambda")
const result = R.compose(
R.filter(val => val>2),
R.flatten,
)([ [1], [2], [3], 4])
console.log(result) // => [3,4]
Use npm i rambda for Webpack and Node.js
For browser usage include in your HTML
https://cdnjs.cloudflare.com/ajax/libs/rambda/0.5.7/webVersion.js
Rambda shadows only small part of the Ramda's API.
A few things to note:
Rambda's methods should be compatible with most of the basic Ramda's methods. For more complex and Ramda specific methods(such as R.__), you should expect a mismatch.
Rambda is tested for compatability with Ramda.flip, as this method could be useful in some cases.
Rambda's equals doesn't protect against circular structures as Ramda.equals does
Rambda's map/filter works only for arrays, while Ramda's map/filter accept also objects
Rambda's type detect async functions. The returned value is "Async"
I haven't tested it fully, but the partial test shows that Ramda definitions can be used.
You need to replace declare module ramda
with declare module rambda
on line
10 and store the file as rambda.js in your flow-typed folder
add(a: Number, b: Number): Number
R.add(2, 3) //=> 5
adjust(replaceFn: Function, i:Number, arr:Array): Array
i
index in arr
with the result of replaceFn(arr[i])
R.adjust(a => a + 1, 0, [0, 100]) //=> [1, 100]
any(condition: Function, arr: Array): Boolean
arr
returns true, when passed to the condition
functionR.any(a => a * a > 8)([1, 2, 3]) //=> true
R.any(a => a * a > 10)([1, 2, 3]) //=> false
append(valueToAppend: any, arr: Array): Array
R.append('foo', ['bar', 'baz']) //=> ['foo', 'bar', 'baz']
contains(valueToFind: any, arr: Array): Boolean
Returns true if valueToFind
is part of arr
R.contains(2, [1, 2]) //=> true
R.contains(3, [1, 2]) //=> false
curry(fn: Function, a: Object, b: Object): Function
Returns function called with merged object of a
over b
.
It supports async functions.
Works only when as arguments are used on first call fn
and a
and on second call b
.
See the example below:
const fn = ({a, b, c}) => {
return (a * b) + c
}
const curried = R.curry(fn, {a: 2})
curried({b: 3, c: 10}) //=> 16
defaultTo(defaultArgument: T, inputArgument: any): T
Returns defaultArgument
if inputArgument
is undefined
or the type of inputArgument
is different of the type of defaultArgument
.
Returns inputArgument
in any other case.
R.defaultTo('foo', undefined) //=> 'foo'
R.defaultTo('foo')('bar') //=> 'bar'
R.defaultTo('foo')(1) //=> 'foo'
drop(howManyToDrop: Number, arrOrStr: Array|String): Array|String
Returns arrOrStr
with howManyToDrop
items dropped from the left
R.drop(1, ['foo', 'bar', 'baz']) //=> ['bar', 'baz']
R.drop(1, 'foo') //=> 'oo'
dropLast(howManyToDrop: Number, arrOrStr: Array|String): Array|String
Returns arrOrStr
with howManyToDrop
items dropped from the right
R.dropLast(1, ['foo', 'bar', 'baz']) //=> ['foo', 'bar']
R.dropLast(1, 'foo') //=> 'fo'
equals(a: any, b: any): Boolean
a
and b
Doesn't handles cyclical data structures
R.equals(1, 1) //=> true
R.equals({}, {}) //=> false
R.equals([1, 2, 3], [1, 2, 3]) //=> true
filter(filterFn: Function, arr: Array): Array
Filters arr
throw boolean returning filterFn
const filterFn = a => a % 2 === 0
R.filter(filterFn, [1, 2, 3, 4]) //=> [2, 4]
find(findFn: Function, arr: Array): T|undefined
Returns undefined
or the first element of arr
satisfying findFn
const findFn = a => R.type(a.foo) === "Number"
const arr = [{foo: "bar"}, {foo: 1}]
R.find(findFn, arr) //=> {foo: 1}
findIndex(findFn: Function, arr: Array): Number
Returns -1
or the index of the first element of arr
satisfying findFn
const findFn = a => R.type(a.foo) === "Number"
const arr = [{foo: "bar"}, {foo: 1}]
R.find(findFn, arr) //=> 1
flatten(arr: Array): Array
R.flatten([ 1, [ 2, [ 3 ] ] ]
//=> [ 1, 2, 3 ]
head(arrOrStr: Array|String): any
arrOrStr
R.head([1, 2, 3]) //=> 1
R.head('foo') //=> 'f'
indexOf(valueToFind: any, arr: Array): Number
Returns -1
or the index of the first element of arr
equal of valueToFind
R.indexOf(1, [1, 2]) //=> 0
init(arrOrStr: Array|String): Array|String
arrOrStr
R.init([1, 2, 3]) //=> [1, 2]
R.init('foo') //=> 'fo'
join(separator: String, arr: Array): String
R.join('-', [1, 2, 3]) //=> '1-2-3'
last(arrOrStr: Array|String): any
arrOrStr
R.last(['foo', 'bar', 'baz']) //=> 'baz'
R.last('foo') //=> 'o'
length(arrOrStr: Array|String): Number
R.length([1, 2, 3]) //=> 3
map(mapFn: Function, arr: Array): Array
Returns the result of looping through arr
with mapFn
const mapFn = x => x * 2;
R.map(mapFn, [1, 2, 3]) //=> [2, 4, 6]
map(regExpression: Regex, str: String): Array
R.match(/([a-z]a)/g, 'bananas') //=> ['ba', 'na', 'na']
merge(a: Object, b: Object)
Returns result of Object.assign({}, a, b)
R.merge({ 'foo': 0, 'bar': 1 }, { 'foo': 7 })
//=> { 'foo': 7, 'bar': 1 }
omit(propsToOmit: Array, obj: Object): Object
obj
with omitting propsToOmit
R.omit(['a', 'd'], {a: 1, b: 2, c: 3}) //=> {b: 2, c: 3}
path(pathToSearch: Array, obj: Object): any
pathToSearch
in object obj
R.path(['a', 'b'], {a: {b: 2}}) //=> 2
R.path(['a', 'c'], {a: {b: 2}}) //=> undefined
pick(propsToPick: Array, obj: Object): Object
obj
containing only propsToPick
propertiesR.pick(['a', 'c'], {a: 1, b: 2}) //=> {a: 1}
pluck(prop: String, arr: Array): Array
- Returns list of the values of property
prop
taken from the objects inarr
R.pluck('a')([{a: 1}, {a: 2}]) //=> [1, 2]
prepend
prepend(valueToPrepend: any, arr: Array): Array
R.prepend('foo', ['bar', 'baz']) //=> ['foo', 'bar', 'baz']
prop(propToFind: String, obj: Object): any
Returns
undefined
or the value of propertypropToFind
inobj
R.prop('x', {x: 100}) //=> 100 R.prop('x', {}) //=> undefined
propEq
propEq(propToFind: String, valueToMatch: any, obj: Object): Boolean
Returns true if
obj
has propertypropToFind
and its value is equal tovalueToMatch
const propToFind = "foo" const valueToMatch = 0 R.propEq(propToFind, valueToMatch)({foo: 0}) //=> true R.propEq(propToFind, valueToMatch)({foo: 1}) //=> false
range
range(start: Number, end: Number): Array
- Returns a array of numbers from
start
(inclusive) toend
(exclusive)
R.range(0, 2) //=> [0, 1]
repeat
repeat(valueToRepeat: T, num: Number): Array
R.repeat('foo', 2) //=> ['foo', 'foo']
replace
replace(strOrRegex: String|Regex, replacer: String, str: String): String
Replace
strOrRegex
found instr
withreplacer
R.replace('foo', 'bar', 'foo foo') //=> 'bar foo' R.replace(/foo/, 'bar', 'foo foo') //=> 'bar foo' R.replace(/foo/g, 'bar', 'foo foo') //=> 'bar bar'
sort
sort(sortFn: Function, arr: Array): Array
Returns copy of
arr
sorted bysortFn
sortFn
must returnNumber
const sortFn = (a, b) => a - b R.sort(sortFn, [3, 1, 2]) //=> [1, 2, 3]
sortBy
Returns copy of
arr
sorted bysortFn
sortFn
must return value for comparison
const sortFn = obj => obj.foo R.sortBy(sortFn, [ {foo: 1}, {foo: 0} ]) //=> [{foo: 0}, {foo: 1}]
split
split(separator: String, str: String): Array
R.split('-', 'a-b-c') //=> ['a', 'b', 'c']
splitEvery
splitEvery(sliceLength: Number, arrOrString: Array|String): Array
- Splits
arrOrStr
into slices ofsliceLength
R.splitEvery(2, [1, 2, 3]) //=> [[1, 2], [3]] R.splitEvery(3, 'foobar') //=> ['foo', 'bar']
subtract
subtract(a: Number, b: Number): Number
Returns
a
minusb
R.subtract(3, 1) //=> 2
tail
tail(arrOrStr: Array|String): Array|String
- Returns all but the first element of
arrOrStr
R.tail([1, 2, 3]) //=> [2, 3] R.tail('foo') //=> 'oo'
take
take(num: Number, arrOrStr: Array|String): Array|String
- Returns the first
num
elements ofarrOrStr
R.take(1, ['foo', 'bar']) //=> ['foo'] R.take(2, ['foo']) //=> 'fo'
takeLast
takeLast(num: Number, arrOrStr: Array|String): Array|String
- Returns the last
num
elements ofarrOrStr
R.takeLast(1, ['foo', 'bar']) //=> ['bar'] R.takeLast(2, ['foo']) //=> 'oo'
test
test(regExpression: Regex, str: String): Boolean
- Determines whether
str
matchesregExpression
R.test(/^f/, 'foo') //=> true R.test(/^f/, 'bar') //=> false
toLower
toLower(str: String): String
R.toLower('FOO') //=> 'foo'
toUpper
toUpper(str: String): String
R.toUpper('foo') //=> 'FOO'
trim
trim(str: String): String
R.trim(' foo ') //=> 'foo'
type
type(a: any): String
R.type(() => {}) //=> "Function" R.type(async () => {}) //=> "Async" R.type([]) //=> "Array" R.type({}) //=> "Object" R.type('s') //=> "String" R.type(1) //=> "Number" R.type(false) //=> "Boolean" R.type(null) //=> "Null" R.type(/[A-z]/) //=> "RegExp"
uniq
uniq(arr: Array): Array
- Returns a new array containing only one copy of each element in
arr
R.uniq([1, 1, 2, 1]) //=> [1, 2] R.uniq([1, '1']) //=> [1, '1']
update
update(i: Number, replaceValue: any, arr: Array): Array
- Returns a new copy of the
arr
with the element ati
index replaced withreplaceValue
R.update(0, "foo", ['bar', 'baz']) //=> ['foo', baz]
values
values(obj: Object): Array
- Returns array with of all values in
obj
R.values({a: 1, b: 2}) //=> [1, 2]
Projects using Rambda
Articles about Rambda
FAQs
Lightweight and faster alternative to Ramda with included TS definitions
The npm package rambda receives a total of 914,797 weekly downloads. As such, rambda popularity was classified as popular.
We found that rambda demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Solo open source maintainers face burnout and security challenges, with 60% unpaid and 60% considering quitting.
Security News
License exceptions modify the terms of open source licenses, impacting how software can be used, modified, and distributed. Developers should be aware of the legal implications of these exceptions.
Security News
A developer is accusing Tencent of violating the GPL by modifying a Python utility and changing its license to BSD, highlighting the importance of copyleft compliance.