Coming from Ramda

Map Ramda functions to @vinicunca/perkakas, with notes where the APIs differ.

Each heading is a Ramda function. The Perkakas equivalent is checked against @vinicunca/perkakas v1.17.1. Names that Remeda documents but Perkakas does not ship are called out. In-page links such as #reverse jump to that Ramda section.

add

Ramda add → add.

addIndex

No direct Perkakas helper. Use the notes below, or native JavaScript.

Not provided by Perkakas.

You don't need addIndex In Perkakas because all functions that iterate over arrays or objects have their callbacks in the format that addIndex returns by default. If you still have a use-case that isn't possible via Perkakas please open an issue at the Perkakas GitHub project.

// Ramda
addIndex(map)((val, idx) => `${idx}-${val}`, DATA);

// Perkakas
map(DATA, (val, idx) => `${idx}-${val}`);

allPass

Ramda allPass → allPass.

always

Ramda always → constant.

anyPass

Ramda anyPass → anyPass.

append

Ramda append → concat.

Not provided by Perkakas.

  • You can replicate this function via the native JS spread ... operator or via the Perkakas concat function (by wrapping the operand with an array).
  • There might be cases where building an append function could be more efficient than using the suggested alternatives, but we believe they are extremely rare. If you want to suggest adding it reach out to us at the Perkakas GitHub project.
// Ramda
append(operand, DATA);

// Or curried
const addsAbc = append(operand);

// Perkakas
concat(DATA, [operand]);

// Or in a pipe
pipe(DATA, concat([operand]));

// Native
[...DATA, operand];

const addsAbc = <T extends ReadonlyArray<unknown>>(data: T) => [...data, operand];

assoc

Ramda assoc → set.

assocPath

Ramda assocPath → setPath.

chain

Ramda chain → flatMap.

clamp

Ramda clamp → clamp.

clone

Ramda clone → clone.

complement

Ramda complement → isNot.

  • Unlike Ramda's complement, isNot preserves type predicates: negating a type-guard returns a type-guard which excludes the guarded type, so the result of filter stays narrowed.
  • Ramda's complement preserves the arity of the function it wraps, and the result stays curried. isNot only takes a single-parameter predicate and passes just the first argument through; wrap multi-parameter functions with the native logical NOT operator ! instead.
  • Ramda's complement negates the truthiness of any return value, whereas isNot requires a predicate that returns a boolean. Compose with isTruthy to get the Ramda semantics.

Predicates

// Ramda
complement(predicate);

// Perkakas
isNot(predicate);

Filtering

// Ramda
filter(complement(is(String)), DATA);

// Perkakas
filter(DATA, isNot(isString));

Multiple parameters

// Ramda
complement(isGreaterThan);

// Native
(a: number, b: number) => !isGreaterThan(a, b);

Non-boolean predicates

// Ramda
complement(getLength);

// Perkakas
isNot(piped(getLength, isTruthy));

// Or directly via Native JS:
(data: string) => !getLength(data);

concat

Ramda concat → concat.

cond

Ramda cond → conditional.

countBy

Ramda countBy → countBy.

dec

Ramda dec → subtract.

Use subtract with an operand of 1.

// Ramda
dec(value);

// Perkakas
subtract(value, 1);

defaultTo

Ramda defaultTo → defaultTo.

  • Number.NaN is not considered nullish and would not result in returning the default value. Use when with the built-in Number.isNaN and a constant for the fallback value.
  • Unlike in Perkakas, Ramda allows the fallback value to be of any type, even those that are incompatible with the data type. It also allows the data type to be non-nullish; for those cases use the built-in Nullish coalescing operator ?? directly, or use when with isNullish and constant.

Nullish

const DATA: number | undefined | null;

// Ramda
R.defaultTo(456)(DATA);

// Perkakas
defaultTo(DATA, 456);

NaN

const DATA = Number.NaN;

// Ramda
R.defaultTo(10)(DATA);

// Perkakas
when(DATA, Number.isNaN, constant(10));

Both

const DATA: number | null | undefined;

// Ramda
R.defaultTo(10)(DATA);

// Perkakas
when(
  DATA,
  (x) => x === undefined || x === null || Number.isNaN(x),
  constant(10),
);

Non-matching fallback

const DATA: string | null | undefined;

// Ramda
R.defaultTo(123)(DATA);

// Perkakas
when(DATA, isNullish, constant(123));

// or natively
DATA ?? 123;

difference

Ramda difference → difference.

differenceWith

Ramda differenceWith → differenceWith.

divide

Ramda divide → divide.

drop

Ramda drop → drop.

dropLast

Ramda dropLast → dropLast.

dropLastWhile

Ramda dropLastWhile → dropLastWhile.

dropWhile

Ramda dropWhile → dropWhile.

equals

Ramda equals → isDeepEqual.

evolve

Ramda evolve → evolve.

F

Ramda F → constant.

Use constant with the constant false. Notice that in Ramda you use F itself as the function, but in Perkakas constant is a factory that creates the replacement function.

// Ramda
F;

// Perkakas
constant(false);

filter

Ramda filter → filter.

find

Ramda find → find.

findIndex

Ramda findIndex → findIndex.

findLast

Ramda findLast → findLast.

findLastIndex

Ramda findLastIndex → findLastIndex.

flatten

Ramda flatten → flat.

Unlike flatten in Ramda, the Perkakas flat function is always bound by the depth param. To replicate the Ramda behavior use a high, const value. Infinity and Number.MAX_INTEGER are not consts and would result in inefficient typing.

// Ramda
flatten(DATA);

// Perkakas
flat(DATA, 100); // ✅
flat(DATA, Infinity); // ❌

forEach

Ramda forEach → forEach.

forEachObjIndexed

Ramda forEachObjIndexed → forEachObj.

fromPairs

Ramda fromPairs → fromEntries.

groupBy

Ramda groupBy → groupBy.

has

Ramda has → hasProp.

hasIn

Ramda hasIn → hasProp.

Own properties

// Ramda
hasIn('a', obj);

// Perkakas
hasProp(obj, 'a');

Inherited properties

// Ramda
hasIn('toString', {}); // => true

// Perkakas
hasProp({}, 'toString'); // => false

Ramda head → first.

  • For strings use sliceString with 0 and 1 as arguments instead.

Arrays

// Ramda
head([1, 2, 3]);

// Perkakas
first([1, 2, 3]);

Strings

// Ramda
head('abc');

// Perkakas
sliceString('abc', 0, 1);

identity

Ramda identity → identity.

In Perkakas the identity function is a factory that creates an identity function; it needs to be called to be used.

// Ramda
map(identity);

// Perkakas
map(identity());

ifElse

Ramda ifElse → when.

  • Perkakas supports both if-like statements, and if-else-like statements (which is what Ramda's ifElse function supports); The former is done by using a predicate function and a mapper function, and the latter is done by wrapping both mappers with an object.
  • To support extra arguments Ramda requires one of the functions provided to provide full typing to all params, in Perkakas this isn't needed as the extra arguments would be inferred from the call site.

if-else

// Ramda
ifElse(predicate, onTrue, onFalse)(data);

// Perkakas
when(data, predicate, { onTrue, onFalse });

// Or in a pipe
pipe(data, when(predicate, { onTrue, onFalse }));

if

ifElse(predicate, onTrue, identity)(data);

// Perkakas
when(data, predicate, onTrue);

// Or in a pipe
pipe(data, when(predicate, onTrue));

extra args

// Ramda
const mapper = ifElse(
  (x: string | undefined, index: number) => x === undefined,
  (_, index) => `item_${index}`,
  identity,
);
map(data, mapper);

// Perkakas
map(
  data,
  when(
    (x) => x === undefined,
    (_, index) => `item_${index}`,
  ),
);

inc

Ramda inc → add.

Use add with an operand of 1.

// Ramda
inc(value);

// Perkakas
add(value, 1);

includes

Ramda includes → isIncludedIn.

Arrays

// Ramda
includes(1, [1, 2, 3]);

// Perkakas
isIncludedIn(1, [1, 2, 3]);

Strings

const DATA = 'Hello, World!';

// Perkakas
includes('lo', DATA);

// Native
DATA.includes('lo');

Object items

const DATA = [{ name: 'Fred' }];

// Ramda
includes({ name: 'Fred' }, DATA);

// Perkakas
DATA.some(isDeepEqual({ name: 'Fred' }));

Array items

const DATA = [[42]];

// Ramda
includes([42], DATA);

// Perkakas
DATA.some(isDeepEqual([42]));

indexBy

Ramda indexBy → indexBy.

init

Ramda init → dropLast.

  • Equivalent to dropLast with an argument of 1.
  • On strings use sliceString with 0 and -1 as arguments instead.

Arrays

// Ramda
init([1, 2, 3]);

// Perkakas
dropLast([1, 2, 3], 1);

Strings

// Ramda
init('abc');

// Perkakas
sliceString('abc', 0, -1);

innerJoin

Ramda innerJoin → intersectionWith.

intersection

Ramda intersection → intersection.

invertObj

Ramda invertObj → invert.

isEmpty

Ramda isEmpty → isEmptyish.

isNil

Ramda isNil → isNullish.

isNotNil

Ramda isNotNil → isNonNullish.

join

Ramda join → join.

keys

Ramda keys → keys.

last

Ramda last → last.

For strings use sliceString with -1 as an argument instead.

Arrays

// Ramda
last([1, 2, 3]);

// Perkakas
last([1, 2, 3]);

Strings

// Ramda
last('abc');

// Perkakas
sliceString('abc', -1);

length

Ramda length → length.

map

Ramda map → map.

mapAccum

Ramda mapAccum → mapWithFeedback.

Perkakas's mapWithFeedback has some differences from Ramda's mapAccum, but could be used to achieve the same results:

  • The mapper function only returns a single value for both the accumulator and the value (like reduce does). mapWithFeedback would not work if you need these to have different values.
  • Only the accumulated array is returned instead of a tuple. The final result of the computation would always be the last element in this list, and could be retrieved using last.
// Ramda
const result = mapAccum((a, b) => [a + b, a + b], 0, ['1', '2', '3', '4']);

// Perkakas
const temp = mapWithFeedback(['1', '2', '3', '4'], (a, b) => a + b, 0);
const result = [last(temp), temp];

mapObjIndexed

Ramda mapObjIndexed → mapValues.

max

No direct Perkakas helper. Use the notes below, or native JavaScript.

Not provided by Perkakas.

The Ramda max function takes exactly 2 arguments. It is easily replicated using native JS operators.

// Ramda
max(a, b);

// Curried
const maxA = max(a);

// Native
a > b ? a : b;

const maxA = (b: number) => (a > b ? a : b);

maxBy

Ramda maxBy → firstBy.

The Perkakas firstBy returns what would be the first item in an array if it was sorted by the order criteria (without actually sorting the array). Ramda's maxBy could be rebuilt using firstBy by taking the mapping function in descending order, and wrapping the 2 arguments with an array.

// Ramda
maxBy(mapperFunc, a, b);

// Perkakas
firstBy([a, b], [mapperFunc, 'desc']);

mean

Ramda mean → mean.

median

Ramda median → median.

mergeAll

Ramda mergeAll → mergeAll.

mergeDeepRight

Ramda mergeDeepRight → mergeDeep.

mergeRight

Ramda mergeRight → merge.

min

No direct Perkakas helper. Use the notes below, or native JavaScript.

Not provided by Perkakas.

The Ramda max function takes exactly 2 arguments. It is easily replicated using native JS operators.

// Ramda
min(a, b);

// Curried
const minA = min(a);

// Native
a < b ? a : b;

const minA = (b: number) => (a < b ? a : b);

minBy

Ramda minBy → firstBy.

The Perkakas firstBy returns what would be the first item in an array if it was sorted by the order criteria (without actually sorting the array). Ramda's minBy could be rebuilt using firstBy by taking the mapping function in, and wrapping the 2 arguments with an array.

// Ramda
minBy(mapperFunc, a, b);

// Perkakas
firstBy([a, b], mapperFunc);

multiply

Ramda multiply → multiply.

negate

Ramda negate → multiply.

Use multiply with an operand of -1.

// Ramda
negate(value);

// Perkakas
multiply(value, -1);

not

No direct Perkakas helper. Use the notes below, or native JavaScript.

Not provided by Perkakas.

  • Use the native logical NOT operator !.
  • Ramda's not is a function, so it can be passed around point-free. The native operator can't; wrap it in an arrow function.

Values

// Ramda
not(value);

// Native
!value;

Point-free

// Ramda
map(not, DATA);

// Perkakas
map(DATA, (value) => !value);

nth

No direct Perkakas helper. Use the notes below, or native JavaScript.

Not provided by Perkakas.

  • For index 0 use first.
  • For index -1 use last.
  • For arbitrary non-negative indices use the native JS data[n].
  • Or use Array.prototype.at for any index.
// Ramda
nth(0, DATA);

// Perkakas
first(DATA);

// Ramda
nth(1, DATA);

// Native
DATA[1];
DATA.at(1);

// Ramda
nth(-1, DATA);

// Perkakas
last(DATA);

// Ramda
nth(-2, DATA);

// Native
DATA.at(-2);

objOf

Ramda objOf → objOf.

omit

Ramda omit → omit.

once

Ramda once → once.

partial

Ramda partial → partialBind.

Perkakas's partialBind takes a variadic list of arguments instead of an array.

function greet(greeting, firstName, lastName) {
  return `${greeting} ${firstName} ${lastName}`;
}

// Ramda
partial(greet, ['hi', 'john']);

// Perkakas
partialBind(greet, 'hi', 'john');

partialRight

Ramda partialRight → partialLastBind.

Perkakas's partialLastBind takes a variadic list of arguments instead of an array.

function greet(greeting, firstName, lastName) {
  return `${greeting} ${firstName} ${lastName}`;
}

// Ramda
partialRight(greet, ['john', 'doe']);

// Perkakas
partialLastBind(greet, 'john', 'doe');

partition

Ramda partition → partition.

path

Ramda path → prop.

pathOr

Ramda pathOr → prop.

Compose prop with defaultTo.

// Ramda
R.pathOr('N/A', ['a', 'b'], { a: { b: 2 } });

// Perkakas
defaultTo(prop({ a: { b: 2 } }, 'a', 'b'), 'N/A');

paths

Ramda paths → prop.

Compose paths using map and prop:

const DATA = { a: { b: 2 }, p: [{ q: 3 }] };
const PATHS = [
  ['a', 'b'],
  ['p', 0, 'q'],
] as const;

// Ramda
R.paths(PATHS, DATA);

// Perkakas
map(PATHS, (path) => prop(DATA, ...path));

pick

Ramda pick → pick.

pickBy

Ramda pickBy → pickBy.

pipe

Ramda pipe → pipe.

pluck

Ramda pluck → map.

Not provided by Perkakas.

  • pluck(data, k) is equivalent to map(data, prop(k)).
  • When data is an object (and not an array) use mapValues instead.

Arrays

const DATA = [{ val: 'hello' }, { val: 'world' }];

// Ramda
R.pluck('val', DATA); // => ["hello", "world"];

// Perkakas
map(DATA, prop('val'));

Objects

const DATA = { a: { val: 'hello' }, b: { val: 'world' } };

// Ramda
R.pluck('val', DATA); // => { a: "hello", b: "world" };

// Perkakas
mapValues(DATA, prop('val'));

product

Ramda product → product.

prop

Ramda prop → prop.

range

Ramda range → range.

Perkakas curries functions by stripping the first parameter. This means that unlike in Ramda, a curried call to range would result in a function that has a pre-set end value, and not a pre-set start value; curried calls need their start and end parameters swapped!

Simple

// Ramda
R.range(10, 20);
R.range(start, end);

// Perkakas
range(10, 20);
range(start, end);

Curried

// Ramda
R.range(10)(20);
R.range(start)(end);

// Perkakas
range(20)(10);
range(end)(start);

reduce

Ramda reduce → reduce.

reject

Ramda reject → filter.

Wrap the callback with isNot.

// Ramda
reject(predicate, DATA);

// Perkakas
filter(DATA, isNot(predicate));

// Or in a pipe
pipe(DATA, filter(isNot(predicate)));

remove

Ramda remove → splice.

reverse

Ramda reverse → reverse.

set

Ramda set → set.

sort

Ramda sort → sort.

sortBy

Ramda sortBy → sortBy.

sortWith

Ramda sortWith → sortBy.

Perkakas's sortBy also covers the use-case of sortWith using a simpler syntax to describe complex sorting logic; the function takes a variadic list of arguments instead of an array, and the sorting direction (ascending/descending) is determined by an optional tuple syntax for the operator.

const DATA = [
  {
    name: 'clara',
    age: 40,
  },
  {
    name: 'bob',
    age: 30,
  },
  {
    name: 'alice',
    age: 40,
  },
];

// Ramda
sortWith([descend(prop('age')), ascend(prop('name'))])(DATA);

// Perkakas
sortBy(DATA, [prop('age'), 'desc'], prop('name'));

// Or in a pipe
pipe(DATA, sortBy([prop('age'), 'desc'], prop('name')));

split

Ramda split → split.

splitAt

Ramda splitAt → splitAt.

splitWhen

Ramda splitWhen → splitWhen.

subtract

Ramda subtract → subtract.

sum

Ramda sum → sum.

swap

Ramda swap → swapIndices.

T

Ramda T → constant.

Use constant with the constant true. Notice that in Ramda you use T itself as the function, but in Perkakas constant is a factory that creates the replacement function.

// Ramda
T;

// Perkakas
constant(true);

tail

Ramda tail → drop.

  • Equivalent to drop with an argument of 1.
  • On strings use sliceString instead.

Arrays

// Ramda
tail([1, 2, 3]);

// Perkakas
drop([1, 2, 3], 1);

Strings

// Ramda
tail('abc');

// Perkakas
sliceString('abc', 1);

take

Ramda take → take.

takeLast

Ramda takeLast → takeLast.

takeLastWhile

Ramda takeLastWhile → takeLastWhile.

takeWhile

Ramda takeWhile → takeWhile.

tap

Ramda tap → tap.

times

Ramda times → times.

toLower

Ramda toLower → toLowerCase.

toPairs

Ramda toPairs → entries.

toUpper

Ramda toUpper → toUpperCase.

uniq

Ramda uniq → unique.

uniqBy

Ramda uniqBy → uniqueBy.

uniqWith

Ramda uniqWith → uniqueWith.

values

Ramda values → values.

when

Ramda when → when.

where

Ramda where → hasSubObject.

zip

Ramda zip → zip.

zipObj

No direct Perkakas helper. Use the notes below, or native JavaScript.

Not provided by Perkakas.

Compose zip and fromEntries:

// Ramda
zipObj(keys, values);

// Perkakas
fromEntries(zip(keys, values));

zipWith

Ramda zipWith → zipWith.