UNPKG

408 kBMarkdownView Raw
1# Rambda
2
3`Rambda` is smaller and faster alternative to the popular functional programming library **Ramda**. - [Documentation](https://selfrefactor.github.io/rambda/#/)
4
5[![CircleCI](https://circleci.com/gh/selfrefactor/rambda/tree/master.svg?style=svg)](https://circleci.com/gh/selfrefactor/rambda/tree/master)
6[![codecov](https://codecov.io/gh/selfrefactor/rambda/branch/master/graph/badge.svg)](https://codecov.io/gh/selfrefactor/rambda)
7![Commit activity](https://img.shields.io/github/commit-activity/y/selfrefactor/rambda)
8![All contributors](https://img.shields.io/github/contributors/selfrefactor/rambda)
9![Library size](https://img.shields.io/bundlephobia/minzip/rambda)
10
11## ❯ Example use
12
13```javascript
14import { compose, map, filter } from 'rambda'
15
16const result = compose(
17 map(x => x * 2),
18 filter(x => x > 2)
19)([1, 2, 3, 4])
20// => [6, 8]
21```
22
23You can test this example in <a href="https://rambda.now.sh?const%20result%20%3D%20R.compose(%0A%20%20R.map(x%20%3D%3E%20x%20*%202)%2C%0A%20%20R.filter(x%20%3D%3E%20x%20%3E%202)%0A)(%5B1%2C%202%2C%203%2C%204%5D)%0A%0A%2F%2F%20%3D%3E%20%5B6%2C%208%5D">Rambda's REPL</a>
24
25* [Differences between Rambda and Ramda](#differences-between-rambda-and-ramda)
26* [API](#api)
27* [Changelog](#-changelog)
28
29[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#-example-use)
30
31## ❯ Rambda's advantages
32
33### Typescript included
34
35Typescript definitions are included in the library, in comparison to **Ramda**, where you need to additionally install `@types/ramda`.
36
37Still, you need to be aware that functional programming features in `Typescript` are in development, which means that using **R.compose/R.pipe** can be problematic.
38
39Important - Rambda version `7.0.0`(or higher) requires Typescript version `4.2.2`(or higher).
40
41> Alternative TS definitions are available as `rambda/immutable`. These are Rambda definitions linted with ESLint `functional/prefer-readonly-type` plugin.
42
43### Smaller size
44
45The size of a library affects not only the build bundle size but also the dev bundle size and build time. This is important advantage, expecially for big projects.
46
47### Tree-shaking
48
49Currently **Rambda** is more tree-shakable than **Ramda** - proven in the following [repo](https://github.com/selfrefactor/rambda-tree-shaking).
50
51The repo holds two `Angular9` applications: one with small example code of *Ramda* and the other - same code but with *Rambda* as import library.
52
53The test shows that **Rambda** bundle size is **2 MB** less than its **Ramda** counterpart.
54
55There is also [Webpack/Rollup/Parcel/Esbuild tree-shaking example including several libraries](https://github.com/mischnic/tree-shaking-example) including `Ramda`, `Rambda` and `Rambdax`.
56
57> actually tree-shaking is the initial reason for creation of `Rambda`
58
59### Dot notation for `R.path`, `R.paths`, `R.assocPath` and `R.lensPath`
60
61Standard usage of `R.path` is `R.path(['a', 'b'], {a: {b: 1} })`.
62
63In **Rambda** you have the choice to use dot notation(which is arguably more readable):
64
65```
66R.path('a.b', {a: {b: 1} })
67```
68
69### Comma notation for `R.pick` and `R.omit`
70
71Similar to dot notation, but the separator is comma(`,`) instead of dot(`.`).
72
73```
74R.pick('a,b', {a: 1 , b: 2, c: 3} })
75// No space allowed between properties
76```
77
78### Speed
79
80**Rambda** is generally more performant than `Ramda` as the [benchmarks](#-benchmarks) can prove that.
81
82### Support
83
84Most of the valid issues are fixed within 2-3 days.
85
86Closing the issue is usually accompanied by publishing a new patch version of `Rambda` to NPM.
87
88[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#-rambdas-advantages)
89
90## ❯ Missing Ramda methods
91
92<details>
93<summary>
94 Click to see the full list of 85 Ramda methods not implemented in Rambda
95</summary>
96
97- __
98- addIndex
99- ap
100- aperture
101- applyTo
102- ascend
103- binary
104- call
105- comparator
106- composeK
107- composeP
108- composeWith
109- construct
110- constructN
111- contains
112- countBy
113- descend
114- differenceWith
115- dissocPath
116- empty
117- eqBy
118- forEachObjIndexed
119- gt
120- gte
121- hasIn
122- innerJoin
123- insert
124- insertAll
125- into
126- invert
127- invertObj
128- invoker
129- juxt
130- keysIn
131- lift
132- liftN
133- lt
134- lte
135- mapAccum
136- mapAccumRight
137- memoizeWith
138- mergeDeepLeft
139- mergeDeepWith
140- mergeDeepWithKey
141- mergeRight
142- mergeWith
143- mergeWithKey
144- nAry
145- nthArg
146- o
147- otherwise
148- pair
149- partialRight
150- pathSatisfies
151- pickBy
152- pipeK
153- pipeP
154- pipeWith
155- project
156- propSatisfies
157- reduceBy
158- reduceRight
159- reduceWhile
160- reduced
161- remove
162- scan
163- sequence
164- sortWith
165- symmetricDifferenceWith
166- andThen
167- toPairsIn
168- transduce
169- traverse
170- unary
171- uncurryN
172- unfold
173- unionWith
174- uniqBy
175- unnest
176- until
177- useWith
178- valuesIn
179- xprod
180- thunkify
181- default
182
183</details>
184
185[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#-missing-ramda-methods)
186
187## ❯ Install
188
189- **yarn add rambda**
190
191- For UMD usage either use `./dist/rambda.umd.js` or the following CDN link:
192
193```
194https://unpkg.com/rambda@CURRENT_VERSION/dist/rambda.umd.js
195```
196
197- with deno
198
199```
200import {compose, add} from 'https://raw.githubusercontent.com/selfrefactor/rambda/master/dist/rambda.esm.js'
201```
202
203[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#-install)
204
205## Differences between Rambda and Ramda
206
207- Rambda's **type** detects async functions and unresolved `Promises`. The returned values are `'Async'` and `'Promise'`.
208
209- Rambda's **type** handles *NaN* input, in which case it returns `NaN`.
210
211- Rambda's **forEach** can iterate over objects not only arrays.
212
213- Rambda's **map**, **filter**, **partition** when they iterate over objects, they pass property and input object as predicate's argument.
214
215- Rambda's **filter** returns empty array with bad input(`null` or `undefined`), while Ramda throws.
216
217- Ramda's **clamp** work with strings, while Rambda's method work only with numbers.
218
219- Ramda's **indexOf/lastIndexOf** work with strings and lists, while Rambda's method work only with lists as iterable input.
220
221- Error handling, when wrong inputs are provided, may not be the same. This difference will be better documented once all brute force tests are completed.
222
223- Typescript definitions between `rambda` and `@types/ramda` may vary.
224
225> If you need more **Ramda** methods in **Rambda**, you may either submit a `PR` or check the extended version of **Rambda** - [Rambdax](https://github.com/selfrefactor/rambdax). In case of the former, you may want to consult with [Rambda contribution guidelines.](CONTRIBUTING.md)
226
227[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#-differences-between-rambda-and-ramda)
228
229## ❯ Benchmarks
230
231<details>
232
233<summary>
234Click to expand all benchmark results
235
236There are methods which are benchmarked only with `Ramda` and `Rambda`(i.e. no `Lodash`).
237
238Note that some of these methods, are called with and without curring. This is done in order to give more detailed performance feedback.
239
240The benchmarks results are produced from latest versions of *Rambda*, *Lodash*(4.17.21) and *Ramda*(0.27.1).
241
242</summary>
243
244method | Rambda | Ramda | Lodash
245--- |--- | --- | ---
246 *add* | 🚀 Fastest | 21.52% slower | 82.15% slower
247 *adjust* | 8.48% slower | 🚀 Fastest | 🔳
248 *all* | 🚀 Fastest | 1.81% slower | 🔳
249 *allPass* | 🚀 Fastest | 91.09% slower | 🔳
250 *allPass* | 🚀 Fastest | 98.56% slower | 🔳
251 *and* | 🚀 Fastest | 89.09% slower | 🔳
252 *any* | 🚀 Fastest | 92.87% slower | 45.82% slower
253 *anyPass* | 🚀 Fastest | 98.25% slower | 🔳
254 *append* | 🚀 Fastest | 2.07% slower | 🔳
255 *applySpec* | 🚀 Fastest | 80.43% slower | 🔳
256 *assoc* | 72.32% slower | 60.08% slower | 🚀 Fastest
257 *clone* | 🚀 Fastest | 91.86% slower | 86.48% slower
258 *compose* | 🚀 Fastest | 32.45% slower | 13.68% slower
259 *converge* | 78.63% slower | 🚀 Fastest | 🔳
260 *curry* | 🚀 Fastest | 28.86% slower | 🔳
261 *curryN* | 🚀 Fastest | 41.05% slower | 🔳
262 *defaultTo* | 🚀 Fastest | 48.91% slower | 🔳
263 *drop* | 🚀 Fastest | 82.35% slower | 🔳
264 *dropLast* | 🚀 Fastest | 86.74% slower | 🔳
265 *equals* | 58.37% slower | 96.73% slower | 🚀 Fastest
266 *filter* | 6.7% slower | 72.03% slower | 🚀 Fastest
267 *find* | 🚀 Fastest | 85.14% slower | 42.65% slower
268 *findIndex* | 🚀 Fastest | 86.48% slower | 72.27% slower
269 *flatten* | 🚀 Fastest | 95.26% slower | 10.27% slower
270 *ifElse* | 🚀 Fastest | 58.56% slower | 🔳
271 *includes* | 🚀 Fastest | 84.63% slower | 🔳
272 *indexOf* | 🚀 Fastest | 76.63% slower | 🔳
273 *indexOf* | 🚀 Fastest | 82.2% slower | 🔳
274 *init* | 🚀 Fastest | 92.24% slower | 13.3% slower
275 *is* | 🚀 Fastest | 57.69% slower | 🔳
276 *isEmpty* | 🚀 Fastest | 97.14% slower | 54.99% slower
277 *last* | 🚀 Fastest | 93.43% slower | 5.28% slower
278 *lastIndexOf* | 🚀 Fastest | 85.19% slower | 🔳
279 *map* | 🚀 Fastest | 86.6% slower | 11.73% slower
280 *match* | 🚀 Fastest | 44.83% slower | 🔳
281 *merge* | 🚀 Fastest | 12.21% slower | 55.76% slower
282 *none* | 🚀 Fastest | 96.48% slower | 🔳
283 *objOf* | 🚀 Fastest | 38.05% slower | 🔳
284 *omit* | 🚀 Fastest | 69.95% slower | 97.34% slower
285 *over* | 🚀 Fastest | 56.23% slower | 🔳
286 *path* | 37.81% slower | 77.81% slower | 🚀 Fastest
287 *pick* | 🚀 Fastest | 19.07% slower | 80.2% slower
288 *pipe* | 0.87% slower | 🚀 Fastest | 🔳
289 *prop* | 🚀 Fastest | 87.95% slower | 🔳
290 *propEq* | 🚀 Fastest | 91.92% slower | 🔳
291 *range* | 🚀 Fastest | 61.8% slower | 57.44% slower
292 *reduce* | 60.48% slower | 77.1% slower | 🚀 Fastest
293 *repeat* | 48.57% slower | 68.98% slower | 🚀 Fastest
294 *replace* | 33.45% slower | 33.99% slower | 🚀 Fastest
295 *set* | 🚀 Fastest | 50.35% slower | 🔳
296 *sort* | 🚀 Fastest | 40.23% slower | 🔳
297 *sortBy* | 🚀 Fastest | 25.29% slower | 56.88% slower
298 *split* | 🚀 Fastest | 55.37% slower | 17.64% slower
299 *splitEvery* | 🚀 Fastest | 71.98% slower | 🔳
300 *take* | 🚀 Fastest | 91.96% slower | 4.72% slower
301 *takeLast* | 🚀 Fastest | 93.39% slower | 19.22% slower
302 *test* | 🚀 Fastest | 82.34% slower | 🔳
303 *type* | 🚀 Fastest | 48.6% slower | 🔳
304 *uniq* | 🚀 Fastest | 90.24% slower | 🔳
305 *uniqWith* | 25.38% slower | 🚀 Fastest | 🔳
306 *uniqWith* | 14.23% slower | 🚀 Fastest | 🔳
307 *update* | 🚀 Fastest | 52.35% slower | 🔳
308 *view* | 🚀 Fastest | 76.15% slower | 🔳
309
310</details>
311
312[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#-benchmarks)
313
314## ❯ Used by
315
316- [WatermelonDB](https://github.com/Nozbe/WatermelonDB)
317
318- [Walmart Canada](https://www.walmart.ca) reported by [w-b-dev](https://github.com/w-b-dev)
319
320- [VSCode Slack intergration](https://github.com/verydanny/vcslack)
321
322- [Webpack PostCSS](https://github.com/sectsect/webpack-postcss)
323
324- [MobX-State-Tree decorators](https://github.com/farwayer/mst-decorators)
325
326- [Rewrite of the Betaflight configurator](https://github.com/freshollie/fresh-configurator)
327
328- [MineFlayer plugin](https://github.com/G07cha/MineflayerArmorManager)
329
330[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#-used-by)
331
332## API
333
334### add
335
336```typescript
337
338add(a: number, b: number): number
339```
340
341It adds `a` and `b`.
342
343<details>
344
345<summary>All Typescript definitions</summary>
346
347```typescript
348add(a: number, b: number): number;
349add(a: number): (b: number) => number;
350```
351
352</details>
353
354<details>
355
356<summary><strong>R.add</strong> source</summary>
357
358```javascript
359export function add(a, b) {
360 if (arguments.length === 1) return _b => add(a, _b)
361
362 return Number(a) + Number(b)
363}
364```
365
366</details>
367
368<details>
369
370<summary><strong>Tests</strong></summary>
371
372```javascript
373import {add} from './add'
374import {add as addRamda} from 'ramda'
375import {compareCombinations} from './_internals/testUtils'
376
377test('with number', () => {
378 expect(add(2, 3)).toEqual(5)
379 expect(add(7)(10)).toEqual(17)
380})
381
382test('string is bad input', () => {
383 expect(add('foo', 'bar')).toBeNaN()
384})
385
386test('ramda specs', () => {
387 expect(add('1', '2')).toEqual(3)
388 expect(add(1, '2')).toEqual(3)
389 expect(add(true, false)).toEqual(1)
390 expect(add(null, null)).toEqual(0)
391 expect(add(undefined, undefined)).toEqual(NaN)
392 expect(add(new Date(1), new Date(2))).toEqual(3)
393})
394
395const possibleInputs = [
396 /foo/,
397 'foo',
398 true,
399 3,
400 NaN,
401 4,
402 [],
403 Promise.resolve(1),
404]
405
406describe('brute force', () => {
407 compareCombinations({
408 fn: add,
409 fnRamda: addRamda,
410 firstInput: possibleInputs,
411 secondInput: possibleInputs,
412 callback: errorsCounters => {
413 expect(errorsCounters).toMatchInlineSnapshot(`
414 Object {
415 "ERRORS_MESSAGE_MISMATCH": 0,
416 "ERRORS_TYPE_MISMATCH": 0,
417 "RESULTS_MISMATCH": 0,
418 "SHOULD_NOT_THROW": 0,
419 "SHOULD_THROW": 0,
420 "TOTAL_TESTS": 64,
421 }
422 `)
423 },
424 })
425})
426```
427
428</details>
429
430<details>
431
432<summary><strong>Typescript</strong> test</summary>
433
434```typescript
435import {add} from 'rambda'
436
437describe('R.add', () => {
438 it('happy', () => {
439 const result = add(4, 1)
440
441 result // $ExpectType number
442 })
443 it('curried', () => {
444 const result = add(4)(1)
445
446 result // $ExpectType number
447 })
448})
449```
450
451</details>
452
453<details>
454
455<summary>Rambda is fastest. Ramda is 21.52% slower and Lodash is 82.15% slower</summary>
456
457```text
458const R = require('../../dist/rambda.js')
459
460const add = [
461 {
462 label: 'Rambda',
463 fn: () => {
464 R.add(1, 1)
465 },
466 },
467 {
468 label: 'Ramda',
469 fn: () => {
470 Ramda.add(1, 1)
471 },
472 },
473 {
474 label: 'Lodash',
475 fn: () => {
476 _.add(1, 1)
477 },
478 },
479]
480```
481
482</details>
483
484[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#add)
485
486### adjust
487
488```typescript
489
490adjust<T>(index: number, replaceFn: (x: T) => T, list: T[]): T[]
491```
492
493It replaces `index` in array `list` with the result of `replaceFn(list[i])`.
494
495<details>
496
497<summary>All Typescript definitions</summary>
498
499```typescript
500adjust<T>(index: number, replaceFn: (x: T) => T, list: T[]): T[];
501adjust<T>(index: number, replaceFn: (x: T) => T): (list: T[]) => T[];
502```
503
504</details>
505
506<details>
507
508<summary><strong>R.adjust</strong> source</summary>
509
510```javascript
511import {curry} from './curry'
512import {cloneList} from './_internals/cloneList'
513
514function adjustFn(index, replaceFn, list) {
515 const actualIndex = index < 0 ? list.length + index : index
516 if (index >= list.length || actualIndex < 0) return list
517
518 const clone = cloneList(list)
519 clone[actualIndex] = replaceFn(clone[actualIndex])
520
521 return clone
522}
523
524export const adjust = curry(adjustFn)
525```
526
527</details>
528
529<details>
530
531<summary><strong>Tests</strong></summary>
532
533```javascript
534import {add} from './add'
535import {adjust} from './adjust'
536import {pipe} from './pipe'
537
538const list = [0, 1, 2]
539const expected = [0, 11, 2]
540
541test('happy', () => {})
542
543test('happy', () => {
544 expect(adjust(1, add(10), list)).toEqual(expected)
545})
546
547test('with curring type 1 1 1', () => {
548 expect(adjust(1)(add(10))(list)).toEqual(expected)
549})
550
551test('with curring type 1 2', () => {
552 expect(adjust(1)(add(10), list)).toEqual(expected)
553})
554
555test('with curring type 2 1', () => {
556 expect(adjust(1, add(10))(list)).toEqual(expected)
557})
558
559test('with negative index', () => {
560 expect(adjust(-2, add(10), list)).toEqual(expected)
561})
562
563test('when index is out of bounds', () => {
564 const list = [0, 1, 2, 3]
565 expect(adjust(4, add(1), list)).toEqual(list)
566 expect(adjust(-5, add(1), list)).toEqual(list)
567})
568```
569
570</details>
571
572<details>
573
574<summary>Rambda is slower than Ramda with 8.48%</summary>
575
576```text
577const R = require('../../dist/rambda.js')
578
579const list = [0, 1, 2]
580const fn = x => x + 1
581const index = 1
582
583const adjust = [
584 {
585 label: 'Rambda',
586 fn: () => {
587 R.adjust(index, fn, list)
588 R.adjust(index, fn)(list)
589 },
590 },
591 {
592 label: 'Ramda',
593 fn: () => {
594 Ramda.adjust(index, fn, list)
595 Ramda.adjust(index, fn)(list)
596 },
597 },
598]
599```
600
601</details>
602
603[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#adjust)
604
605### all
606
607```typescript
608
609all<T>(predicate: (x: T) => boolean, list: T[]): boolean
610```
611
612It returns `true`, if all members of array `list` returns `true`, when applied as argument to `predicate` function.
613
614<details>
615
616<summary>All Typescript definitions</summary>
617
618```typescript
619all<T>(predicate: (x: T) => boolean, list: T[]): boolean;
620all<T>(predicate: (x: T) => boolean): (list: T[]) => boolean;
621```
622
623</details>
624
625<details>
626
627<summary><strong>R.all</strong> source</summary>
628
629```javascript
630export function all(predicate, list) {
631 if (arguments.length === 1) return _list => all(predicate, _list)
632
633 for (let i = 0; i < list.length; i++) {
634 if (!predicate(list[i])) return false
635 }
636
637 return true
638}
639```
640
641</details>
642
643<details>
644
645<summary><strong>Tests</strong></summary>
646
647```javascript
648import {all} from './all'
649
650const list = [0, 1, 2, 3, 4]
651
652test('when true', () => {
653 const fn = x => x > -1
654
655 expect(all(fn)(list)).toBeTrue()
656})
657
658test('when false', () => {
659 const fn = x => x > 2
660
661 expect(all(fn, list)).toBeFalse()
662})
663```
664
665</details>
666
667<details>
668
669<summary><strong>Typescript</strong> test</summary>
670
671```typescript
672import {all} from 'rambda'
673
674describe('all', () => {
675 it('happy', () => {
676 const result = all(
677 x => {
678 x // $ExpectType number
679 return x > 0
680 },
681 [1, 2, 3]
682 )
683 result // $ExpectType boolean
684 })
685 it('curried needs a type', () => {
686 const result = all<number>(x => {
687 x // $ExpectType number
688 return x > 0
689 })([1, 2, 3])
690 result // $ExpectType boolean
691 })
692})
693```
694
695</details>
696
697<details>
698
699<summary>Rambda is faster than Ramda with 1.81%</summary>
700
701```text
702const R = require('../../dist/rambda.js')
703
704const {
705 uniqListOfObjects,
706 uniqListOfStrings,
707 rangeOfNumbers,
708 uniqListOfLists,
709} = require('./_utils.js')
710
711const limit = 100
712
713const modes = [
714 [uniqListOfObjects(limit), x => Object.keys(x).length > 2],
715 [uniqListOfStrings(limit), x => x.length > 0],
716 [uniqListOfLists(limit), x => x.length > 0],
717 [rangeOfNumbers(limit), x => x > -1],
718]
719
720const applyBenchmark = (fn, input) => {
721 return fn(input[1], input[0])
722}
723
724const tests = [
725 {
726 label: 'Rambda',
727 fn: R.all,
728 },
729 {
730 label: 'Ramda',
731 fn: Ramda.all,
732 },
733]
734```
735
736</details>
737
738[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#all)
739
740### allPass
741
742```typescript
743
744allPass<T>(predicates: ((x: T) => boolean)[]): (input: T) => boolean
745```
746
747It returns `true`, if all functions of `predicates` return `true`, when `input` is their argument.
748
749<details>
750
751<summary>All Typescript definitions</summary>
752
753```typescript
754allPass<T>(predicates: ((x: T) => boolean)[]): (input: T) => boolean;
755```
756
757</details>
758
759<details>
760
761<summary><strong>R.allPass</strong> source</summary>
762
763```javascript
764export function allPass(predicates) {
765 return (...input) => {
766 let counter = 0
767 while (counter < predicates.length) {
768 if (!predicates[counter](...input)) {
769 return false
770 }
771 counter++
772 }
773
774 return true
775 }
776}
777```
778
779</details>
780
781<details>
782
783<summary><strong>Tests</strong></summary>
784
785```javascript
786import {allPass} from './allPass'
787
788test('happy', () => {
789 const rules = [x => typeof x === 'number', x => x > 10, x => x * 7 < 100]
790
791 expect(allPass(rules)(11)).toBeTrue()
792
793 expect(allPass(rules)(undefined)).toBeFalse()
794})
795
796test('when returns true', () => {
797 const conditionArr = [val => val.a === 1, val => val.b === 2]
798
799 expect(
800 allPass(conditionArr)({
801 a: 1,
802 b: 2,
803 })
804 ).toBeTrue()
805})
806
807test('when returns false', () => {
808 const conditionArr = [val => val.a === 1, val => val.b === 3]
809
810 expect(
811 allPass(conditionArr)({
812 a: 1,
813 b: 2,
814 })
815 ).toBeFalse()
816})
817
818test('works with multiple inputs', () => {
819 var fn = function (w, x, y, z) {
820 return w + x === y + z
821 }
822 expect(allPass([fn])(3, 3, 3, 3)).toBeTrue()
823})
824```
825
826</details>
827
828<details>
829
830<summary><strong>Typescript</strong> test</summary>
831
832```typescript
833import {allPass} from 'rambda'
834
835describe('allPass', () => {
836 it('happy', () => {
837 const x = allPass<number>([
838 y => {
839 y // $ExpectType number
840 return typeof y === 'number'
841 },
842 y => {
843 return y > 0
844 },
845 ])(11)
846
847 x // $ExpectType boolean
848 })
849})
850```
851
852</details>
853
854<details>
855
856<summary>Rambda is faster than Ramda with 91.09%</summary>
857
858```text
859const R = require('../../dist/rambda.js')
860
861const {random} = require('rambdax')
862
863const limit = 100
864const min = 10
865const max = 1200
866function createListOfFunctions(fn, fnLimit) {
867 return Array(fnLimit)
868 .fill(null)
869 .map(() => fn())
870}
871
872const modes = [
873 [
874 {foo: 1500},
875 createListOfFunctions(
876 () => x => Number(x.foo) > random(min, max),
877 limit
878 ),
879 ],
880 [
881 '1500',
882 createListOfFunctions(() => x => Number(x) > random(min, max), limit),
883 ],
884 [
885 [1, 2, 1500],
886 createListOfFunctions(() => x => x[2] > random(min, max), limit),
887 ],
888 [1500, createListOfFunctions(() => x => x > random(min, max), limit)],
889]
890
891const applyBenchmark = (fn, input) => {
892 return fn(input[1])(input[0])
893}
894const tests = [
895 {
896 label: 'Rambda',
897 fn: R.allPass,
898 },
899 {
900 label: 'Ramda',
901 fn: Ramda.allPass,
902 },
903]
904```
905
906</details>
907
908[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#allPass)
909
910### always
911
912```typescript
913
914always<T>(x: T): (...args: unknown[]) => T
915```
916
917It returns function that always returns `x`.
918
919<details>
920
921<summary>All Typescript definitions</summary>
922
923```typescript
924always<T>(x: T): (...args: unknown[]) => T;
925```
926
927</details>
928
929<details>
930
931<summary><strong>R.always</strong> source</summary>
932
933```javascript
934export function always(x) {
935 return () => x
936}
937```
938
939</details>
940
941<details>
942
943<summary><strong>Tests</strong></summary>
944
945```javascript
946import {always} from './always'
947import {F} from './F'
948
949test('happy', () => {
950 const fn = always(7)
951
952 expect(fn()).toEqual(7)
953 expect(fn()).toEqual(7)
954})
955
956test('f', () => {
957 const fn = always(F())
958
959 expect(fn()).toBeFalse()
960 expect(fn()).toBeFalse()
961})
962```
963
964</details>
965
966<details>
967
968<summary><strong>Typescript</strong> test</summary>
969
970```typescript
971import {always} from 'rambda'
972
973describe('R.always', () => {
974 it('happy', () => {
975 const fn = always('foo')
976 fn // $ExpectType (...args: unknown[]) => string
977 const result = fn()
978 result // $ExpectType string
979 })
980})
981```
982
983</details>
984
985[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#always)
986
987### and
988
989```typescript
990
991and<T, U>(x: T, y: U): T | U
992```
993
994Logical AND
995
996<details>
997
998<summary>All Typescript definitions</summary>
999
1000```typescript
1001and<T, U>(x: T, y: U): T | U;
1002and<T>(x: T): <U>(y: U) => T | U;
1003```
1004
1005</details>
1006
1007<details>
1008
1009<summary><strong>R.and</strong> source</summary>
1010
1011```javascript
1012export function and(a, b) {
1013 if (arguments.length === 1) return _b => and(a, _b)
1014
1015 return a && b
1016}
1017```
1018
1019</details>
1020
1021<details>
1022
1023<summary><strong>Tests</strong></summary>
1024
1025```javascript
1026import {and} from './and'
1027
1028test('happy', () => {
1029 expect(and(1, 'foo')).toBe('foo')
1030 expect(and(true, true)).toBeTrue()
1031 expect(and(true)(true)).toBeTrue()
1032 expect(and(true, false)).toBeFalse()
1033 expect(and(false, true)).toBeFalse()
1034 expect(and(false, false)).toBeFalse()
1035})
1036```
1037
1038</details>
1039
1040<details>
1041
1042<summary><strong>Typescript</strong> test</summary>
1043
1044```typescript
1045import {and} from 'rambda'
1046
1047describe('R.and', () => {
1048 it('happy', () => {
1049 const result = and(true, false)
1050 result // $ExpectType boolean
1051 })
1052 it('curried', () => {
1053 const result = and('foo')(1)
1054 result // $ExpectType string | 1
1055 })
1056})
1057```
1058
1059</details>
1060
1061<details>
1062
1063<summary>Rambda is faster than Ramda with 89.09%</summary>
1064
1065```text
1066const R = require('../../dist/rambda.js')
1067
1068const and = [
1069 {
1070 label: 'Rambda',
1071 fn: () => {
1072 R.and(true, true)
1073 },
1074 },
1075 {
1076 label: 'Ramda',
1077 fn: () => {
1078 Ramda.and(true, true)
1079 },
1080 },
1081]
1082```
1083
1084</details>
1085
1086[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#and)
1087
1088### any
1089
1090```typescript
1091
1092any<T>(predicate: (x: T) => boolean, list: T[]): boolean
1093```
1094
1095It returns `true`, if at least one member of `list` returns true, when passed to a `predicate` function.
1096
1097<details>
1098
1099<summary>All Typescript definitions</summary>
1100
1101```typescript
1102any<T>(predicate: (x: T) => boolean, list: T[]): boolean;
1103any<T>(predicate: (x: T) => boolean): (list: T[]) => boolean;
1104```
1105
1106</details>
1107
1108<details>
1109
1110<summary><strong>R.any</strong> source</summary>
1111
1112```javascript
1113export function any(predicate, list) {
1114 if (arguments.length === 1) return _list => any(predicate, _list)
1115
1116 let counter = 0
1117 while (counter < list.length) {
1118 if (predicate(list[counter], counter)) {
1119 return true
1120 }
1121 counter++
1122 }
1123
1124 return false
1125}
1126```
1127
1128</details>
1129
1130<details>
1131
1132<summary><strong>Tests</strong></summary>
1133
1134```javascript
1135import {any} from './any'
1136
1137const list = [1, 2, 3]
1138
1139test('happy', () => {
1140 expect(any(x => x < 0, list)).toBeFalse()
1141})
1142
1143test('with curry', () => {
1144 expect(any(x => x > 2)(list)).toBeTrue()
1145})
1146```
1147
1148</details>
1149
1150<details>
1151
1152<summary><strong>Typescript</strong> test</summary>
1153
1154```typescript
1155import {any} from 'rambda'
1156
1157describe('R.any', () => {
1158 it('happy', () => {
1159 const result = any(
1160 x => {
1161 x // $ExpectType number
1162 return x > 2
1163 },
1164 [1, 2, 3]
1165 )
1166 result // $ExpectType boolean
1167 })
1168
1169 it('when curried needs a type', () => {
1170 const result = any<number>(x => {
1171 x // $ExpectType number
1172 return x > 2
1173 })([1, 2, 3])
1174 result // $ExpectType boolean
1175 })
1176})
1177```
1178
1179</details>
1180
1181<details>
1182
1183<summary>Rambda is fastest. Ramda is 92.87% slower and Lodash is 45.82% slower</summary>
1184
1185```text
1186const R = require('../../dist/rambda.js')
1187
1188const input = [1, 2, 3, 4]
1189const fn = val => val > 2
1190
1191const any = [
1192 {
1193 label: 'Rambda',
1194 fn: () => {
1195 R.any(fn, input)
1196 },
1197 },
1198 {
1199 label: 'Ramda',
1200 fn: () => {
1201 Ramda.any(fn, input)
1202 },
1203 },
1204 {
1205 label: 'Lodash.some',
1206 fn: () => {
1207 _.some(input, fn)
1208 },
1209 },
1210]
1211```
1212
1213</details>
1214
1215[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#any)
1216
1217### anyPass
1218
1219```typescript
1220
1221anyPass<T>(predicates: SafePred<T>[]): SafePred<T>
1222```
1223
1224It accepts list of `predicates` and returns a function. This function with its `input` will return `true`, if any of `predicates` returns `true` for this `input`.
1225
1226<details>
1227
1228<summary>All Typescript definitions</summary>
1229
1230```typescript
1231anyPass<T>(predicates: SafePred<T>[]): SafePred<T>;
1232```
1233
1234</details>
1235
1236<details>
1237
1238<summary><strong>R.anyPass</strong> source</summary>
1239
1240```javascript
1241export function anyPass(predicates) {
1242 return (...input) => {
1243 let counter = 0
1244 while (counter < predicates.length) {
1245 if (predicates[counter](...input)) {
1246 return true
1247 }
1248 counter++
1249 }
1250
1251 return false
1252 }
1253}
1254```
1255
1256</details>
1257
1258<details>
1259
1260<summary><strong>Tests</strong></summary>
1261
1262```javascript
1263import {anyPass} from './anyPass'
1264
1265test('happy', () => {
1266 const rules = [x => typeof x === 'string', x => x > 10]
1267 const predicate = anyPass(rules)
1268 expect(predicate('foo')).toBeTrue()
1269 expect(predicate(6)).toBeFalse()
1270})
1271
1272test('happy', () => {
1273 const rules = [x => typeof x === 'string', x => x > 10]
1274
1275 expect(anyPass(rules)(11)).toBeTrue()
1276
1277 expect(anyPass(rules)(undefined)).toBeFalse()
1278})
1279
1280const obj = {
1281 a: 1,
1282 b: 2,
1283}
1284
1285test('when returns true', () => {
1286 const conditionArr = [val => val.a === 1, val => val.a === 2]
1287
1288 expect(anyPass(conditionArr)(obj)).toBeTrue()
1289})
1290
1291test('when returns false + curry', () => {
1292 const conditionArr = [val => val.a === 2, val => val.b === 3]
1293
1294 expect(anyPass(conditionArr)(obj)).toBeFalse()
1295})
1296
1297test('with empty predicates list', () => {
1298 expect(anyPass([])(3)).toEqual(false)
1299})
1300
1301test('works with multiple inputs', () => {
1302 var fn = function (w, x, y, z) {
1303 console.log(w, x, y, z)
1304 return w + x === y + z
1305 }
1306 expect(anyPass([fn])(3, 3, 3, 3)).toBeTrue()
1307})
1308```
1309
1310</details>
1311
1312<details>
1313
1314<summary><strong>Typescript</strong> test</summary>
1315
1316```typescript
1317import {anyPass} from 'rambda'
1318
1319describe('anyPass', () => {
1320 it('happy', () => {
1321 const x = anyPass<number>([
1322 y => {
1323 y // $ExpectType number
1324 return typeof y === 'number'
1325 },
1326 y => {
1327 return y > 0
1328 },
1329 ])(11)
1330
1331 x // $ExpectType boolean
1332 })
1333})
1334```
1335
1336</details>
1337
1338<details>
1339
1340<summary>Rambda is faster than Ramda with 98.25%</summary>
1341
1342```text
1343const R = require('../../dist/rambda.js')
1344
1345const rules = [x => typeof x === 'boolean', x => x > 20, x => x * 7 < 100]
1346
1347const anyPass = [
1348 {
1349 label: 'Rambda',
1350 fn: () => {
1351 R.anyPass(rules)(11)
1352 },
1353 },
1354 {
1355 label: 'Ramda',
1356 fn: () => {
1357 Ramda.anyPass(rules)(11)
1358 },
1359 },
1360]
1361```
1362
1363</details>
1364
1365[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#anyPass)
1366
1367### append
1368
1369```typescript
1370
1371append<T>(x: T, list: T[]): T[]
1372```
1373
1374It adds element `x` at the end of `list`.
1375
1376<details>
1377
1378<summary>All Typescript definitions</summary>
1379
1380```typescript
1381append<T>(x: T, list: T[]): T[];
1382append<T>(x: T): <T>(list: T[]) => T[];
1383```
1384
1385</details>
1386
1387<details>
1388
1389<summary><strong>R.append</strong> source</summary>
1390
1391```javascript
1392import {cloneList} from './_internals/cloneList'
1393
1394export function append(x, input) {
1395 if (arguments.length === 1) return _input => append(x, _input)
1396
1397 if (typeof input === 'string') return input.split('').concat(x)
1398
1399 const clone = cloneList(input)
1400 clone.push(x)
1401
1402 return clone
1403}
1404```
1405
1406</details>
1407
1408<details>
1409
1410<summary><strong>Tests</strong></summary>
1411
1412```javascript
1413import {append} from './append'
1414
1415test('happy', () => {
1416 expect(append('tests', ['write', 'more'])).toEqual([
1417 'write',
1418 'more',
1419 'tests',
1420 ])
1421})
1422
1423test('append to empty array', () => {
1424 expect(append('tests')([])).toEqual(['tests'])
1425})
1426
1427test('with strings', () => {
1428 expect(append('o', 'fo')).toEqual(['f', 'o', 'o'])
1429})
1430```
1431
1432</details>
1433
1434<details>
1435
1436<summary><strong>Typescript</strong> test</summary>
1437
1438```typescript
1439import {append} from 'rambda'
1440
1441const list = [1, 2, 3]
1442
1443describe('R.append', () => {
1444 it('happy', () => {
1445 const result = append(4, list)
1446
1447 result // $ExpectType number[]
1448 })
1449 it('curried', () => {
1450 const result = append(4)(list)
1451
1452 result // $ExpectType number[]
1453 })
1454})
1455```
1456
1457</details>
1458
1459<details>
1460
1461<summary>Rambda is faster than Ramda with 2.07%</summary>
1462
1463```text
1464const R = require('../../dist/rambda.js')
1465
1466const append = [
1467 {
1468 label: 'Rambda',
1469 fn: () => {
1470 R.append(0)([1, 2, 3, 4])
1471 R.append('bar')('foo')
1472 },
1473 },
1474 {
1475 label: 'Ramda',
1476 fn: () => {
1477 Ramda.append(0)([1, 2, 3, 4])
1478 Ramda.append('bar')('foo')
1479 },
1480 },
1481]
1482```
1483
1484</details>
1485
1486[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#append)
1487
1488### apply
1489
1490```typescript
1491
1492apply<T = any>(fn: (...args: any[]) => T, args: any[]): T
1493```
1494
1495It applies function `fn` to the list of arguments.
1496
1497This is useful for creating a fixed-arity function from a variadic function. `fn` should be a bound function if context is significant.
1498
1499<details>
1500
1501<summary>All Typescript definitions</summary>
1502
1503```typescript
1504apply<T = any>(fn: (...args: any[]) => T, args: any[]): T;
1505apply<T = any>(fn: (...args: any[]) => T): (args: any[]) => T;
1506```
1507
1508</details>
1509
1510<details>
1511
1512<summary><strong>R.apply</strong> source</summary>
1513
1514```javascript
1515export function apply(fn, args) {
1516 if (arguments.length === 1) {
1517 return _args => apply(fn, _args)
1518 }
1519
1520 return fn.apply(this, args)
1521}
1522```
1523
1524</details>
1525
1526<details>
1527
1528<summary><strong>Tests</strong></summary>
1529
1530```javascript
1531import {apply} from './apply'
1532import {bind} from './bind'
1533import {identity} from './identity'
1534
1535test('happy', () => {
1536 expect(apply(identity, [1, 2, 3])).toEqual(1)
1537})
1538
1539test('applies function to argument list', function () {
1540 expect(apply(Math.max, [1, 2, 3, -99, 42, 6, 7])).toEqual(42)
1541})
1542
1543test('provides no way to specify context', function () {
1544 const obj = {
1545 method: function () {
1546 return this === obj
1547 },
1548 }
1549 expect(apply(obj.method, [])).toEqual(false)
1550 expect(apply(bind(obj.method, obj), [])).toEqual(true)
1551})
1552```
1553
1554</details>
1555
1556<details>
1557
1558<summary><strong>Typescript</strong> test</summary>
1559
1560```typescript
1561import {apply, identity} from 'rambda'
1562
1563describe('R.apply', () => {
1564 it('happy', () => {
1565 const result = apply<number>(identity, [1, 2, 3])
1566
1567 result // $ExpectType number
1568 })
1569 it('curried', () => {
1570 const fn = apply<number>(identity)
1571 const result = fn([1, 2, 3])
1572
1573 result // $ExpectType number
1574 })
1575})
1576```
1577
1578</details>
1579
1580[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#apply)
1581
1582### applySpec
1583
1584```typescript
1585
1586applySpec<Spec extends Record<string, (...args: any[]) => any>>(
1587 spec: Spec
1588): (
1589 ...args: Parameters<ValueOfRecord<Spec>>
1590) => { [Key in keyof Spec]: ReturnType<Spec[Key]> }
1591```
1592
1593<details>
1594
1595<summary>All Typescript definitions</summary>
1596
1597```typescript
1598applySpec<Spec extends Record<string, (...args: any[]) => any>>(
1599 spec: Spec
1600): (
1601 ...args: Parameters<ValueOfRecord<Spec>>
1602) => { [Key in keyof Spec]: ReturnType<Spec[Key]> };
1603applySpec<T>(spec: any): (...args: any[]) => T;
1604```
1605
1606</details>
1607
1608<details>
1609
1610<summary><strong>R.applySpec</strong> source</summary>
1611
1612```javascript
1613import {_isArray} from './_internals/_isArray'
1614
1615// recursively traverse the given spec object to find the highest arity function
1616function __findHighestArity(spec, max = 0) {
1617 for (const key in spec) {
1618 if (spec.hasOwnProperty(key) === false || key === 'constructor') continue
1619
1620 if (typeof spec[key] === 'object') {
1621 max = Math.max(max, __findHighestArity(spec[key]))
1622 }
1623
1624 if (typeof spec[key] === 'function') {
1625 max = Math.max(max, spec[key].length)
1626 }
1627 }
1628
1629 return max
1630}
1631
1632function __filterUndefined() {
1633 const defined = []
1634 let i = 0
1635 const l = arguments.length
1636 while (i < l) {
1637 if (typeof arguments[i] === 'undefined') break
1638 defined[i] = arguments[i]
1639 i++
1640 }
1641
1642 return defined
1643}
1644
1645function __applySpecWithArity(spec, arity, cache) {
1646 const remaining = arity - cache.length
1647
1648 if (remaining === 1)
1649 return x =>
1650 __applySpecWithArity(spec, arity, __filterUndefined(...cache, x))
1651 if (remaining === 2)
1652 return (x, y) =>
1653 __applySpecWithArity(spec, arity, __filterUndefined(...cache, x, y))
1654 if (remaining === 3)
1655 return (x, y, z) =>
1656 __applySpecWithArity(spec, arity, __filterUndefined(...cache, x, y, z))
1657 if (remaining === 4)
1658 return (x, y, z, a) =>
1659 __applySpecWithArity(
1660 spec,
1661 arity,
1662 __filterUndefined(...cache, x, y, z, a)
1663 )
1664 if (remaining > 4)
1665 return (...args) =>
1666 __applySpecWithArity(spec, arity, __filterUndefined(...cache, ...args))
1667
1668 // handle spec as Array
1669 if (_isArray(spec)) {
1670 const ret = []
1671 let i = 0
1672 const l = spec.length
1673 for (; i < l; i++) {
1674 // handle recursive spec inside array
1675 if (typeof spec[i] === 'object' || _isArray(spec[i])) {
1676 ret[i] = __applySpecWithArity(spec[i], arity, cache)
1677 }
1678 // apply spec to the key
1679 if (typeof spec[i] === 'function') {
1680 ret[i] = spec[i](...cache)
1681 }
1682 }
1683
1684 return ret
1685 }
1686
1687 // handle spec as Object
1688 const ret = {}
1689 // apply callbacks to each property in the spec object
1690 for (const key in spec) {
1691 if (spec.hasOwnProperty(key) === false || key === 'constructor') continue
1692
1693 // apply the spec recursively
1694 if (typeof spec[key] === 'object') {
1695 ret[key] = __applySpecWithArity(spec[key], arity, cache)
1696 continue
1697 }
1698
1699 // apply spec to the key
1700 if (typeof spec[key] === 'function') {
1701 ret[key] = spec[key](...cache)
1702 }
1703 }
1704
1705 return ret
1706}
1707
1708export function applySpec(spec, ...args) {
1709 // get the highest arity spec function, cache the result and pass to __applySpecWithArity
1710 const arity = __findHighestArity(spec)
1711
1712 if (arity === 0) {
1713 return () => ({})
1714 }
1715 const toReturn = __applySpecWithArity(spec, arity, args)
1716
1717 return toReturn
1718}
1719```
1720
1721</details>
1722
1723<details>
1724
1725<summary><strong>Tests</strong></summary>
1726
1727```javascript
1728import {applySpec as applySpecRamda, nAry} from 'ramda'
1729import {add, always, compose, dec, inc, map, path, prop, T} from '../rambda'
1730import {applySpec} from './applySpec'
1731
1732test('different than Ramda when bad spec', () => {
1733 const result = applySpec({sum: {a: 1}})(1, 2)
1734 const ramdaResult = applySpecRamda({sum: {a: 1}})(1, 2)
1735 expect(result).toEqual({})
1736 expect(ramdaResult).toEqual({sum: {a: {}}})
1737})
1738
1739test('works with empty spec', () => {
1740 expect(applySpec({})()).toEqual({})
1741 expect(applySpec([])(1, 2)).toEqual({})
1742 expect(applySpec(null)(1, 2)).toEqual({})
1743})
1744
1745test('works with unary functions', () => {
1746 const result = applySpec({
1747 v: inc,
1748 u: dec,
1749 })(1)
1750 const expected = {
1751 v: 2,
1752 u: 0,
1753 }
1754 expect(result).toEqual(expected)
1755})
1756
1757test('works with binary functions', () => {
1758 const result = applySpec({sum: add})(1, 2)
1759 expect(result).toEqual({sum: 3})
1760})
1761
1762test('works with nested specs', () => {
1763 const result = applySpec({
1764 unnested: always(0),
1765 nested: {sum: add},
1766 })(1, 2)
1767 const expected = {
1768 unnested: 0,
1769 nested: {sum: 3},
1770 }
1771 expect(result).toEqual(expected)
1772})
1773
1774test('works with arrays of nested specs', () => {
1775 const result = applySpec({
1776 unnested: always(0),
1777 nested: [{sum: add}],
1778 })(1, 2)
1779
1780 expect(result).toEqual({
1781 unnested: 0,
1782 nested: [{sum: 3}],
1783 })
1784})
1785
1786test('works with arrays of spec objects', () => {
1787 const result = applySpec([{sum: add}])(1, 2)
1788
1789 expect(result).toEqual([{sum: 3}])
1790})
1791
1792test('works with arrays of functions', () => {
1793 const result = applySpec([map(prop('a')), map(prop('b'))])([
1794 {
1795 a: 'a1',
1796 b: 'b1',
1797 },
1798 {
1799 a: 'a2',
1800 b: 'b2',
1801 },
1802 ])
1803 const expected = [
1804 ['a1', 'a2'],
1805 ['b1', 'b2'],
1806 ]
1807 expect(result).toEqual(expected)
1808})
1809
1810test('works with a spec defining a map key', () => {
1811 expect(applySpec({map: prop('a')})({a: 1})).toEqual({map: 1})
1812})
1813
1814test('cannot retains the highest arity', () => {
1815 const f = applySpec({
1816 f1: nAry(2, T),
1817 f2: nAry(5, T),
1818 })
1819 const fRamda = applySpecRamda({
1820 f1: nAry(2, T),
1821 f2: nAry(5, T),
1822 })
1823 expect(f.length).toBe(0)
1824 expect(fRamda.length).toBe(5)
1825})
1826
1827test('returns a curried function', () => {
1828 expect(applySpec({sum: add})(1)(2)).toEqual({sum: 3})
1829})
1830
1831// Additional tests
1832// ============================================
1833test('arity', () => {
1834 const spec = {
1835 one: x1 => x1,
1836 two: (x1, x2) => x1 + x2,
1837 three: (x1, x2, x3) => x1 + x2 + x3,
1838 }
1839 expect(applySpec(spec, 1, 2, 3)).toEqual({
1840 one: 1,
1841 two: 3,
1842 three: 6,
1843 })
1844})
1845
1846test('arity over 5 arguments', () => {
1847 const spec = {
1848 one: x1 => x1,
1849 two: (x1, x2) => x1 + x2,
1850 three: (x1, x2, x3) => x1 + x2 + x3,
1851 four: (x1, x2, x3, x4) => x1 + x2 + x3 + x4,
1852 five: (x1, x2, x3, x4, x5) => x1 + x2 + x3 + x4 + x5,
1853 }
1854 expect(applySpec(spec, 1, 2, 3, 4, 5)).toEqual({
1855 one: 1,
1856 two: 3,
1857 three: 6,
1858 four: 10,
1859 five: 15,
1860 })
1861})
1862
1863test('curried', () => {
1864 const spec = {
1865 one: x1 => x1,
1866 two: (x1, x2) => x1 + x2,
1867 three: (x1, x2, x3) => x1 + x2 + x3,
1868 }
1869 expect(applySpec(spec)(1)(2)(3)).toEqual({
1870 one: 1,
1871 two: 3,
1872 three: 6,
1873 })
1874})
1875
1876test('curried over 5 arguments', () => {
1877 const spec = {
1878 one: x1 => x1,
1879 two: (x1, x2) => x1 + x2,
1880 three: (x1, x2, x3) => x1 + x2 + x3,
1881 four: (x1, x2, x3, x4) => x1 + x2 + x3 + x4,
1882 five: (x1, x2, x3, x4, x5) => x1 + x2 + x3 + x4 + x5,
1883 }
1884 expect(applySpec(spec)(1)(2)(3)(4)(5)).toEqual({
1885 one: 1,
1886 two: 3,
1887 three: 6,
1888 four: 10,
1889 five: 15,
1890 })
1891})
1892
1893test('undefined property', () => {
1894 const spec = {prop: path(['property', 'doesnt', 'exist'])}
1895 expect(applySpec(spec, {})).toEqual({prop: undefined})
1896})
1897
1898test('restructure json object', () => {
1899 const spec = {
1900 id: path('user.id'),
1901 name: path('user.firstname'),
1902 profile: path('user.profile'),
1903 doesntExist: path('user.profile.doesntExist'),
1904 info: {views: compose(inc, prop('views'))},
1905 type: always('playa'),
1906 }
1907
1908 const data = {
1909 user: {
1910 id: 1337,
1911 firstname: 'john',
1912 lastname: 'shaft',
1913 profile: 'shaft69',
1914 },
1915 views: 42,
1916 }
1917
1918 expect(applySpec(spec, data)).toEqual({
1919 id: 1337,
1920 name: 'john',
1921 profile: 'shaft69',
1922 doesntExist: undefined,
1923 info: {views: 43},
1924 type: 'playa',
1925 })
1926})
1927```
1928
1929</details>
1930
1931<details>
1932
1933<summary><strong>Typescript</strong> test</summary>
1934
1935```typescript
1936import {multiply, applySpec, inc, dec, add} from 'rambda'
1937
1938describe('applySpec', () => {
1939 it('ramda 1', () => {
1940 const result = applySpec({
1941 v: inc,
1942 u: dec,
1943 })(1)
1944 result // $ExpectType { v: number; u: number; }
1945 })
1946 it('ramda 1', () => {
1947 interface Output {
1948 sum: number,
1949 multiplied: number,
1950 }
1951 const result = applySpec<Output>({
1952 sum: add,
1953 multiplied: multiply,
1954 })(1, 2)
1955
1956 result // $ExpectType Output
1957 })
1958})
1959```
1960
1961</details>
1962
1963<details>
1964
1965<summary>Rambda is faster than Ramda with 80.43%</summary>
1966
1967```text
1968const R = require('../../dist/rambda.js')
1969
1970const curryN = [
1971 {
1972 label: 'Rambda',
1973 fn: () => {
1974 const data = {
1975 a: {
1976 b: {c: 1},
1977 d: 2,
1978 },
1979 }
1980 const spec = {
1981 c: R.path(['a', 'b', 'c']),
1982 d: R.path(['a', 'd']),
1983 }
1984 R.applySpec(spec, data)
1985 },
1986 },
1987 {
1988 label: 'Ramda',
1989 fn: () => {
1990 const data = {
1991 a: {
1992 b: {c: 1},
1993 d: 2,
1994 },
1995 }
1996 const spec = {
1997 c: Ramda.path(['a', 'b', 'c']),
1998 d: Ramda.path(['a', 'd']),
1999 }
2000 Ramda.applySpec(spec, data)
2001 },
2002 },
2003]
2004```
2005
2006</details>
2007
2008[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#applySpec)
2009
2010### assoc
2011
2012```typescript
2013
2014assoc<T, U, K extends string>(prop: K, val: T, obj: U): Record<K, T> & Omit<U, K>
2015```
2016
2017It makes a shallow clone of `obj` with setting or overriding the property `prop` with `newValue`.
2018
2019<details>
2020
2021<summary>All Typescript definitions</summary>
2022
2023```typescript
2024assoc<T, U, K extends string>(prop: K, val: T, obj: U): Record<K, T> & Omit<U, K>;
2025assoc<T, K extends string>(prop: K, val: T): <U>(obj: U) => Record<K, T> & Omit<U, K>;
2026assoc<K extends string>(prop: K): AssocPartialOne<K>;
2027```
2028
2029</details>
2030
2031<details>
2032
2033<summary><strong>R.assoc</strong> source</summary>
2034
2035```javascript
2036import {curry} from './curry'
2037
2038function assocFn(prop, newValue, obj) {
2039 return Object.assign({}, obj, {[prop]: newValue})
2040}
2041
2042export const assoc = curry(assocFn)
2043```
2044
2045</details>
2046
2047<details>
2048
2049<summary><strong>Tests</strong></summary>
2050
2051```javascript
2052import {assoc} from './assoc'
2053
2054test('adds a key to an empty object', () => {
2055 expect(assoc('a', 1, {})).toEqual({a: 1})
2056})
2057
2058test('adds a key to a non-empty object', () => {
2059 expect(assoc('b', 2, {a: 1})).toEqual({
2060 a: 1,
2061 b: 2,
2062 })
2063})
2064
2065test('adds a key to a non-empty object - curry case 1', () => {
2066 expect(assoc('b', 2)({a: 1})).toEqual({
2067 a: 1,
2068 b: 2,
2069 })
2070})
2071
2072test('adds a key to a non-empty object - curry case 2', () => {
2073 expect(assoc('b')(2, {a: 1})).toEqual({
2074 a: 1,
2075 b: 2,
2076 })
2077})
2078
2079test('adds a key to a non-empty object - curry case 3', () => {
2080 const result = assoc('b')(2)({a: 1})
2081
2082 expect(result).toEqual({
2083 a: 1,
2084 b: 2,
2085 })
2086})
2087
2088test('changes an existing key', () => {
2089 expect(assoc('a', 2, {a: 1})).toEqual({a: 2})
2090})
2091
2092test('undefined is considered an empty object', () => {
2093 expect(assoc('a', 1, undefined)).toEqual({a: 1})
2094})
2095
2096test('null is considered an empty object', () => {
2097 expect(assoc('a', 1, null)).toEqual({a: 1})
2098})
2099
2100test('value can be null', () => {
2101 expect(assoc('a', null, null)).toEqual({a: null})
2102})
2103
2104test('value can be undefined', () => {
2105 expect(assoc('a', undefined, null)).toEqual({a: undefined})
2106})
2107
2108test('assignment is shallow', () => {
2109 expect(assoc('a', {b: 2}, {a: {c: 3}})).toEqual({a: {b: 2}})
2110})
2111```
2112
2113</details>
2114
2115<details>
2116
2117<summary><strong>Typescript</strong> test</summary>
2118
2119```typescript
2120import {assoc} from 'rambda'
2121
2122const obj = {a: 1}
2123const newValue = 2
2124const newProp = 'b'
2125
2126describe('R.assoc', () => {
2127 it('happy', () => {
2128 const result = assoc(newProp, newValue, obj)
2129
2130 result.a // $ExpectType number
2131 result.b // $ExpectType number
2132 })
2133 it('curried 1', () => {
2134 const result = assoc(newProp, newValue)(obj)
2135
2136 result.a // $ExpectType number
2137 result.b // $ExpectType number
2138 })
2139 it('curried 2', () => {
2140 const result = assoc(newProp)(newValue)(obj)
2141
2142 result.a // $ExpectType number
2143 result.b // $ExpectType number
2144 })
2145})
2146```
2147
2148</details>
2149
2150<details>
2151
2152<summary>Lodash is fastest. Rambda is 72.32% slower and Ramda is 60.08% slower</summary>
2153
2154```text
2155const R = require('../../dist/rambda.js')
2156
2157const input = {
2158 a: 1,
2159 b: 2,
2160}
2161const key = 'c'
2162const value = 3
2163
2164const assoc = [
2165 {
2166 label: 'Rambda',
2167 fn: () => {
2168 R.assoc(key, value, input)
2169 },
2170 },
2171 {
2172 label: 'Ramda',
2173 fn: () => {
2174 Ramda.assoc(key, value, input)
2175 },
2176 },
2177 {
2178 label: 'Lodash.set',
2179 fn: () => {
2180 _.set(input, key, value)
2181 },
2182 },
2183]
2184```
2185
2186</details>
2187
2188[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#assoc)
2189
2190### assocPath
2191
2192```typescript
2193
2194assocPath<Output>(path: Path, newValue: any, obj: object): Output
2195```
2196
2197It makes a shallow clone of `obj` with setting or overriding with `newValue` the property found with `path`.
2198
2199<details>
2200
2201<summary>All Typescript definitions</summary>
2202
2203```typescript
2204assocPath<Output>(path: Path, newValue: any, obj: object): Output;
2205assocPath<Output>(path: Path, newValue: any): (obj: object) => Output;
2206assocPath<Output>(path: Path): (newValue: any) => (obj: object) => Output;
2207```
2208
2209</details>
2210
2211<details>
2212
2213<summary><strong>R.assocPath</strong> source</summary>
2214
2215```javascript
2216import {_isArray} from './_internals/_isArray'
2217import {_isInteger} from './_internals/_isInteger'
2218import {assoc} from './assoc'
2219import {curry} from './curry'
2220import {cloneList} from './_internals/cloneList'
2221
2222function assocPathFn(path, newValue, input) {
2223 const pathArrValue =
2224 typeof path === 'string'
2225 ? path.split('.').map(x => (_isInteger(Number(x)) ? Number(x) : x))
2226 : path
2227 if (pathArrValue.length === 0) {
2228 return newValue
2229 }
2230
2231 const index = pathArrValue[0]
2232 if (pathArrValue.length > 1) {
2233 const condition =
2234 typeof input !== 'object' ||
2235 input === null ||
2236 !input.hasOwnProperty(index)
2237
2238 const nextinput = condition
2239 ? _isInteger(pathArrValue[1])
2240 ? []
2241 : {}
2242 : input[index]
2243
2244 newValue = assocPathFn(
2245 Array.prototype.slice.call(pathArrValue, 1),
2246 newValue,
2247 nextinput
2248 )
2249 }
2250
2251 if (_isInteger(index) && _isArray(input)) {
2252 const arr = cloneList(input)
2253 arr[index] = newValue
2254
2255 return arr
2256 }
2257
2258 return assoc(index, newValue, input)
2259}
2260
2261export const assocPath = curry(assocPathFn)
2262```
2263
2264</details>
2265
2266<details>
2267
2268<summary><strong>Tests</strong></summary>
2269
2270```javascript
2271import {assocPath} from './assocPath'
2272
2273test('string can be used as path input', () => {
2274 const testObj = {
2275 a: [{b: 1}, {b: 2}],
2276 d: 3,
2277 }
2278 const result = assocPath('a.0.b', 10, testObj)
2279 const expected = {
2280 a: [{b: 10}, {b: 2}],
2281 d: 3,
2282 }
2283 expect(result).toEqual(expected)
2284})
2285
2286test('bug', () => {
2287 /*
2288 https://github.com/selfrefactor/rambda/issues/524
2289 */
2290 const state = {}
2291
2292 const withDateLike = assocPath(
2293 ['outerProp', '2020-03-10'],
2294 {prop: 2},
2295 state
2296 )
2297 const withNumber = assocPath(['outerProp', '5'], {prop: 2}, state)
2298
2299 const withDateLikeExpected = {outerProp: {'2020-03-10': {prop: 2}}}
2300 const withNumberExpected = {outerProp: {5: {prop: 2}}}
2301 expect(withDateLike).toEqual(withDateLikeExpected)
2302 expect(withNumber).toEqual(withNumberExpected)
2303})
2304
2305test('adds a key to an empty object', () => {
2306 expect(assocPath(['a'], 1, {})).toEqual({a: 1})
2307})
2308
2309test('adds a key to a non-empty object', () => {
2310 expect(assocPath('b', 2, {a: 1})).toEqual({
2311 a: 1,
2312 b: 2,
2313 })
2314})
2315
2316test('adds a nested key to a non-empty object', () => {
2317 expect(assocPath('b.c', 2, {a: 1})).toEqual({
2318 a: 1,
2319 b: {c: 2},
2320 })
2321})
2322
2323test('adds a nested key to a nested non-empty object - curry case 1', () => {
2324 expect(
2325 assocPath(
2326 'b.d',
2327 3
2328 )({
2329 a: 1,
2330 b: {c: 2},
2331 })
2332 ).toEqual({
2333 a: 1,
2334 b: {
2335 c: 2,
2336 d: 3,
2337 },
2338 })
2339})
2340
2341test('adds a key to a non-empty object - curry case 1', () => {
2342 expect(assocPath('b', 2)({a: 1})).toEqual({
2343 a: 1,
2344 b: 2,
2345 })
2346})
2347
2348test('adds a nested key to a non-empty object - curry case 1', () => {
2349 expect(assocPath('b.c', 2)({a: 1})).toEqual({
2350 a: 1,
2351 b: {c: 2},
2352 })
2353})
2354
2355test('adds a key to a non-empty object - curry case 2', () => {
2356 expect(assocPath('b')(2, {a: 1})).toEqual({
2357 a: 1,
2358 b: 2,
2359 })
2360})
2361
2362test('adds a key to a non-empty object - curry case 3', () => {
2363 const result = assocPath('b')(2)({a: 1})
2364
2365 expect(result).toEqual({
2366 a: 1,
2367 b: 2,
2368 })
2369})
2370
2371test('changes an existing key', () => {
2372 expect(assocPath('a', 2, {a: 1})).toEqual({a: 2})
2373})
2374
2375test('undefined is considered an empty object', () => {
2376 expect(assocPath('a', 1, undefined)).toEqual({a: 1})
2377})
2378
2379test('null is considered an empty object', () => {
2380 expect(assocPath('a', 1, null)).toEqual({a: 1})
2381})
2382
2383test('value can be null', () => {
2384 expect(assocPath('a', null, null)).toEqual({a: null})
2385})
2386
2387test('value can be undefined', () => {
2388 expect(assocPath('a', undefined, null)).toEqual({a: undefined})
2389})
2390
2391test('assignment is shallow', () => {
2392 expect(assocPath('a', {b: 2}, {a: {c: 3}})).toEqual({a: {b: 2}})
2393})
2394
2395test('empty array as path', () => {
2396 const result = assocPath([], 3, {
2397 a: 1,
2398 b: 2,
2399 })
2400 expect(result).toEqual(3)
2401})
2402
2403test('happy', () => {
2404 const expected = {foo: {bar: {baz: 42}}}
2405 const result = assocPath(['foo', 'bar', 'baz'], 42, {foo: null})
2406 expect(result).toEqual(expected)
2407})
2408```
2409
2410</details>
2411
2412<details>
2413
2414<summary><strong>Typescript</strong> test</summary>
2415
2416```typescript
2417import {assocPath} from 'rambda'
2418
2419interface Output {
2420 a: number,
2421 foo: {bar: number},
2422}
2423
2424describe('R.assocPath - user must explicitly set type of output', () => {
2425 it('with array as path input', () => {
2426 const result = assocPath<Output>(['foo', 'bar'], 2, {a: 1})
2427
2428 result // $ExpectType Output
2429 })
2430 it('with string as path input', () => {
2431 const result = assocPath<Output>('foo.bar', 2, {a: 1})
2432
2433 result // $ExpectType Output
2434 })
2435})
2436
2437describe('R.assocPath - curried', () => {
2438 it('with array as path input', () => {
2439 const result = assocPath<Output>(['foo', 'bar'], 2)({a: 1})
2440
2441 result // $ExpectType Output
2442 })
2443 it('with string as path input', () => {
2444 const result = assocPath<Output>('foo.bar', 2)({a: 1})
2445
2446 result // $ExpectType Output
2447 })
2448})
2449```
2450
2451</details>
2452
2453[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#assocPath)
2454
2455### bind
2456
2457```typescript
2458
2459bind<F extends (...args: any[]) => any, T>(fn: F, thisObj: T): (...args: Parameters<F>) => ReturnType<F>
2460```
2461
2462Creates a function that is bound to a context.
2463
2464<details>
2465
2466<summary>All Typescript definitions</summary>
2467
2468```typescript
2469bind<F extends (...args: any[]) => any, T>(fn: F, thisObj: T): (...args: Parameters<F>) => ReturnType<F>;
2470bind<F extends (...args: any[]) => any, T>(fn: F): (thisObj: T) => (...args: Parameters<F>) => ReturnType<F>;
2471```
2472
2473</details>
2474
2475<details>
2476
2477<summary><strong>R.bind</strong> source</summary>
2478
2479```javascript
2480import {curryN} from './curryN'
2481
2482export function bind(fn, thisObj) {
2483 if (arguments.length === 1) {
2484 return _thisObj => bind(fn, _thisObj)
2485 }
2486
2487 return curryN(fn.length, (...args) => fn.apply(thisObj, args))
2488}
2489```
2490
2491</details>
2492
2493<details>
2494
2495<summary><strong>Tests</strong></summary>
2496
2497```javascript
2498import {bind} from './bind'
2499
2500function Foo(x) {
2501 this.x = x
2502}
2503function add(x) {
2504 return this.x + x
2505}
2506function Bar(x, y) {
2507 this.x = x
2508 this.y = y
2509}
2510Bar.prototype = new Foo()
2511Bar.prototype.getX = function () {
2512 return 'prototype getX'
2513}
2514
2515test('returns a function', function () {
2516 expect(typeof bind(add)(Foo)).toEqual('function')
2517})
2518
2519test('returns a function bound to the specified context object', function () {
2520 const f = new Foo(12)
2521 function isFoo() {
2522 return this instanceof Foo
2523 }
2524 const isFooBound = bind(isFoo, f)
2525 expect(isFoo()).toEqual(false)
2526 expect(isFooBound()).toEqual(true)
2527})
2528
2529test('works with built-in types', function () {
2530 const abc = bind(String.prototype.toLowerCase, 'ABCDEFG')
2531 expect(typeof abc).toEqual('function')
2532 expect(abc()).toEqual('abcdefg')
2533})
2534
2535test('works with user-defined types', function () {
2536 const f = new Foo(12)
2537 function getX() {
2538 return this.x
2539 }
2540 const getXFooBound = bind(getX, f)
2541 expect(getXFooBound()).toEqual(12)
2542})
2543
2544test('works with plain objects', function () {
2545 const pojso = {
2546 x: 100,
2547 }
2548 function incThis() {
2549 return this.x + 1
2550 }
2551 const incPojso = bind(incThis, pojso)
2552 expect(typeof incPojso).toEqual('function')
2553 expect(incPojso()).toEqual(101)
2554})
2555
2556test('does not interfere with existing object methods', function () {
2557 const b = new Bar('a', 'b')
2558 function getX() {
2559 return this.x
2560 }
2561 const getXBarBound = bind(getX, b)
2562 expect(b.getX()).toEqual('prototype getX')
2563 expect(getXBarBound()).toEqual('a')
2564})
2565
2566test('preserves arity', function () {
2567 const f0 = function () {
2568 return 0
2569 }
2570 const f1 = function (a) {
2571 return a
2572 }
2573 const f2 = function (a, b) {
2574 return a + b
2575 }
2576 const f3 = function (a, b, c) {
2577 return a + b + c
2578 }
2579
2580 expect(bind(f0, {}).length).toEqual(0)
2581 expect(bind(f1, {}).length).toEqual(1)
2582 expect(bind(f2, {}).length).toEqual(2)
2583 expect(bind(f3, {}).length).toEqual(3)
2584})
2585```
2586
2587</details>
2588
2589<details>
2590
2591<summary><strong>Typescript</strong> test</summary>
2592
2593```typescript
2594import {bind} from 'rambda'
2595
2596class Foo {}
2597function isFoo<T = any>(this: T): boolean {
2598 return this instanceof Foo
2599}
2600
2601describe('R.bind', () => {
2602 it('happy', () => {
2603 const foo = new Foo()
2604 const result = bind(isFoo, foo)()
2605
2606 result // $ExpectType boolean
2607 })
2608})
2609```
2610
2611</details>
2612
2613[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#bind)
2614
2615### both
2616
2617```typescript
2618
2619both(pred1: Pred, pred2: Pred): Pred
2620```
2621
2622It returns a function with `input` argument.
2623
2624This function will return `true`, if both `firstCondition` and `secondCondition` return `true` when `input` is passed as their argument.
2625
2626<details>
2627
2628<summary>All Typescript definitions</summary>
2629
2630```typescript
2631both(pred1: Pred, pred2: Pred): Pred;
2632both<T>(pred1: Predicate<T>, pred2: Predicate<T>): Predicate<T>;
2633both<T>(pred1: Predicate<T>): (pred2: Predicate<T>) => Predicate<T>;
2634both(pred1: Pred): (pred2: Pred) => Pred;
2635```
2636
2637</details>
2638
2639<details>
2640
2641<summary><strong>R.both</strong> source</summary>
2642
2643```javascript
2644export function both(f, g) {
2645 if (arguments.length === 1) return _g => both(f, _g)
2646
2647 return (...input) => f(...input) && g(...input)
2648}
2649```
2650
2651</details>
2652
2653<details>
2654
2655<summary><strong>Tests</strong></summary>
2656
2657```javascript
2658import {both} from './both'
2659
2660const firstFn = val => val > 0
2661const secondFn = val => val < 10
2662
2663test('with curry', () => {
2664 expect(both(firstFn)(secondFn)(17)).toBeFalse()
2665})
2666
2667test('without curry', () => {
2668 expect(both(firstFn, secondFn)(7)).toBeTrue()
2669})
2670
2671test('with multiple inputs', () => {
2672 const between = function (a, b, c) {
2673 return a < b && b < c
2674 }
2675 const total20 = function (a, b, c) {
2676 return a + b + c === 20
2677 }
2678 const fn = both(between, total20)
2679 expect(fn(5, 7, 8)).toBeTrue()
2680})
2681
2682test('skip evaluation of the second expression', () => {
2683 let effect = 'not evaluated'
2684 const F = function () {
2685 return false
2686 }
2687 const Z = function () {
2688 effect = 'Z got evaluated'
2689 }
2690 both(F, Z)()
2691
2692 expect(effect).toBe('not evaluated')
2693})
2694```
2695
2696</details>
2697
2698<details>
2699
2700<summary><strong>Typescript</strong> test</summary>
2701
2702```typescript
2703import {both} from 'rambda'
2704
2705describe('R.both', () => {
2706 it('with passed type', () => {
2707 const fn = both<number>(
2708 x => x > 1,
2709 x => x % 2 === 0
2710 )
2711 fn // $ExpectType Predicate<number>
2712 const result = fn(2) // $ExpectType boolean
2713 result // $ExpectType boolean
2714 })
2715 it('with passed type - curried', () => {
2716 const fn = both<number>(x => x > 1)(x => x % 2 === 0)
2717 fn // $ExpectType Predicate<number>
2718 const result = fn(2)
2719 result // $ExpectType boolean
2720 })
2721 it('no type passed', () => {
2722 const fn = both(
2723 x => {
2724 x // $ExpectType any
2725 return x > 1
2726 },
2727 x => {
2728 x // $ExpectType any
2729 return x % 2 === 0
2730 }
2731 )
2732 const result = fn(2)
2733 result // $ExpectType boolean
2734 })
2735 it('no type passed - curried', () => {
2736 const fn = both((x: number) => {
2737 x // $ExpectType number
2738 return x > 1
2739 })((x: number) => {
2740 x // $ExpectType number
2741 return x % 2 === 0
2742 })
2743 const result = fn(2)
2744 result // $ExpectType boolean
2745 })
2746})
2747```
2748
2749</details>
2750
2751[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#both)
2752
2753### chain
2754
2755```typescript
2756
2757chain<T, U>(fn: (n: T) => U[], list: T[]): U[]
2758```
2759
2760The method is also known as `flatMap`.
2761
2762<details>
2763
2764<summary>All Typescript definitions</summary>
2765
2766```typescript
2767chain<T, U>(fn: (n: T) => U[], list: T[]): U[];
2768chain<T, U>(fn: (n: T) => U[]): (list: T[]) => U[];
2769```
2770
2771</details>
2772
2773<details>
2774
2775<summary><strong>R.chain</strong> source</summary>
2776
2777```javascript
2778export function chain(fn, list) {
2779 if (arguments.length === 1) {
2780 return _list => chain(fn, _list)
2781 }
2782
2783 return [].concat(...list.map(fn))
2784}
2785```
2786
2787</details>
2788
2789<details>
2790
2791<summary><strong>Tests</strong></summary>
2792
2793```javascript
2794import {chain} from './chain'
2795import {chain as chainRamda} from 'ramda'
2796
2797const duplicate = n => [n, n]
2798
2799test('happy', () => {
2800 const fn = x => [x * 2]
2801 const list = [1, 2, 3]
2802
2803 const result = chain(fn, list)
2804
2805 expect(result).toEqual([2, 4, 6])
2806})
2807
2808test('maps then flattens one level', () => {
2809 expect(chain(duplicate, [1, 2, 3])).toEqual([1, 1, 2, 2, 3, 3])
2810})
2811
2812test('maps then flattens one level - curry', () => {
2813 expect(chain(duplicate)([1, 2, 3])).toEqual([1, 1, 2, 2, 3, 3])
2814})
2815
2816test('flattens only one level', () => {
2817 const nest = n => [[n]]
2818 expect(chain(nest, [1, 2, 3])).toEqual([[1], [2], [3]])
2819})
2820
2821test('can compose', () => {
2822 function dec(x) {
2823 return [x - 1]
2824 }
2825 function times2(x) {
2826 return [x * 2]
2827 }
2828
2829 var mdouble = chain(times2)
2830 var mdec = chain(dec)
2831 expect(mdec(mdouble([10, 20, 30]))).toEqual([19, 39, 59])
2832})
2833
2834test('@types/ramda broken test', () => {
2835 const score = {
2836 maths: 90,
2837 physics: 80,
2838 }
2839
2840 const calculateTotal = score => {
2841 const {maths, physics} = score
2842 return maths + physics
2843 }
2844
2845 const assocTotalToScore = (total, score) => ({...score, total})
2846
2847 const calculateAndAssocTotalToScore = chainRamda(
2848 assocTotalToScore,
2849 calculateTotal
2850 )
2851 expect(() => calculateAndAssocTotalToScore(score)).toThrow()
2852})
2853```
2854
2855</details>
2856
2857<details>
2858
2859<summary><strong>Typescript</strong> test</summary>
2860
2861```typescript
2862import {chain} from 'rambda'
2863
2864const list = [1, 2, 3]
2865const fn = (x: number) => [`${x}`, `${x}`]
2866
2867describe('R.chain', () => {
2868 it('without passing type', () => {
2869 const result = chain(fn, list)
2870 result // $ExpectType string[]
2871
2872 const curriedResult = chain(fn)(list)
2873 curriedResult // $ExpectType string[]
2874 })
2875})
2876```
2877
2878</details>
2879
2880[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#chain)
2881
2882### clamp
2883
2884```typescript
2885
2886clamp(min: number, max: number, input: number): number
2887```
2888
2889Restrict a number `input` to be within `min` and `max` limits.
2890
2891If `input` is bigger than `max`, then the result is `max`.
2892
2893If `input` is smaller than `min`, then the result is `min`.
2894
2895<details>
2896
2897<summary>All Typescript definitions</summary>
2898
2899```typescript
2900clamp(min: number, max: number, input: number): number;
2901clamp(min: number, max: number): (input: number) => number;
2902```
2903
2904</details>
2905
2906<details>
2907
2908<summary><strong>R.clamp</strong> source</summary>
2909
2910```javascript
2911import {curry} from './curry'
2912
2913function clampFn(min, max, input) {
2914 if (min > max) {
2915 throw new Error(
2916 'min must not be greater than max in clamp(min, max, value)'
2917 )
2918 }
2919 if (input >= min && input <= max) return input
2920
2921 if (input > max) return max
2922 if (input < min) return min
2923}
2924
2925export const clamp = curry(clampFn)
2926```
2927
2928</details>
2929
2930<details>
2931
2932<summary><strong>Tests</strong></summary>
2933
2934```javascript
2935import {clamp} from './clamp'
2936
2937test('when min is greater than max', () => {
2938 expect(() => clamp(-5, -10, 5)).toThrowWithMessage(
2939 Error,
2940 'min must not be greater than max in clamp(min, max, value)'
2941 )
2942})
2943
2944test('rambda specs', () => {
2945 expect(clamp(1, 10, 0)).toEqual(1)
2946 expect(clamp(3, 12, 1)).toEqual(3)
2947 expect(clamp(-15, 3, -100)).toEqual(-15)
2948 expect(clamp(1, 10, 20)).toEqual(10)
2949 expect(clamp(3, 12, 23)).toEqual(12)
2950 expect(clamp(-15, 3, 16)).toEqual(3)
2951 expect(clamp(1, 10, 4)).toEqual(4)
2952 expect(clamp(3, 12, 6)).toEqual(6)
2953 expect(clamp(-15, 3, 0)).toEqual(0)
2954})
2955```
2956
2957</details>
2958
2959<details>
2960
2961<summary><strong>Typescript</strong> test</summary>
2962
2963```typescript
2964import {clamp} from 'rambda'
2965
2966describe('R.clamp', () => {
2967 it('happy', () => {
2968 const result = clamp(1, 10, 20)
2969 result // $ExpectType number
2970 })
2971})
2972```
2973
2974</details>
2975
2976[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#clamp)
2977
2978### clone
2979
2980```typescript
2981
2982clone<T>(input: T): T
2983```
2984
2985It creates a deep copy of the `input`, which may contain (nested) Arrays and Objects, Numbers, Strings, Booleans and Dates.
2986
2987<details>
2988
2989<summary>All Typescript definitions</summary>
2990
2991```typescript
2992clone<T>(input: T): T;
2993clone<T>(input: T[]): T[];
2994```
2995
2996</details>
2997
2998<details>
2999
3000<summary><strong>R.clone</strong> source</summary>
3001
3002```javascript
3003import {_isArray} from './_internals/_isArray'
3004
3005export function clone(input) {
3006 const out = _isArray(input) ? Array(input.length) : {}
3007 if (input && input.getTime) return new Date(input.getTime())
3008
3009 for (const key in input) {
3010 const v = input[key]
3011 out[key] =
3012 typeof v === 'object' && v !== null
3013 ? v.getTime
3014 ? new Date(v.getTime())
3015 : clone(v)
3016 : v
3017 }
3018
3019 return out
3020}
3021```
3022
3023</details>
3024
3025<details>
3026
3027<summary><strong>Tests</strong></summary>
3028
3029```javascript
3030import assert from 'assert'
3031
3032import {clone} from './clone'
3033import {equals} from './equals'
3034
3035test('with array', () => {
3036 const arr = [
3037 {
3038 b: 2,
3039 c: 'foo',
3040 d: [1, 2, 3],
3041 },
3042 1,
3043 new Date(),
3044 null,
3045 ]
3046 expect(clone(arr)).toEqual(arr)
3047})
3048
3049test('with object', () => {
3050 const obj = {
3051 a: 1,
3052 b: 2,
3053 c: 3,
3054 d: [1, 2, 3],
3055 e: new Date(),
3056 }
3057 expect(clone(obj)).toEqual(obj)
3058})
3059
3060test('with date', () => {
3061 const date = new Date(2014, 10, 14, 23, 59, 59, 999)
3062
3063 const cloned = clone(date)
3064 assert.notStrictEqual(date, cloned)
3065 expect(cloned).toEqual(new Date(2014, 10, 14, 23, 59, 59, 999))
3066
3067 expect(cloned.getDay()).toEqual(5)
3068})
3069
3070test('with R.equals', () => {
3071 const objects = [{a: 1}, {b: 2}]
3072
3073 const objectsClone = clone(objects)
3074
3075 const result = [
3076 equals(objects, objectsClone),
3077 equals(objects[0], objectsClone[0]),
3078 ]
3079 expect(result).toEqual([true, true])
3080})
3081```
3082
3083</details>
3084
3085<details>
3086
3087<summary><strong>Typescript</strong> test</summary>
3088
3089```typescript
3090import {clone} from 'rambda'
3091
3092describe('R.clone', () => {
3093 it('happy', () => {
3094 const obj = {a: 1, b: 2}
3095 const result = clone(obj)
3096 result // $ExpectType { a: number; b: number; }
3097 })
3098})
3099```
3100
3101</details>
3102
3103<details>
3104
3105<summary>Rambda is fastest. Ramda is 91.86% slower and Lodash is 86.48% slower</summary>
3106
3107```text
3108const R = require('../../dist/rambda.js')
3109
3110const input = {
3111 a: 1,
3112 b: 2,
3113}
3114
3115const clone = [
3116 {
3117 label: 'Rambda',
3118 fn: () => {
3119 R.clone(input)
3120 },
3121 },
3122 {
3123 label: 'Ramda',
3124 fn: () => {
3125 Ramda.clone(input)
3126 },
3127 },
3128 {
3129 label: 'Lodash.cloneDeep',
3130 fn: () => {
3131 _.cloneDeep(input)
3132 },
3133 },
3134]
3135```
3136
3137</details>
3138
3139[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#clone)
3140
3141### complement
3142
3143```typescript
3144
3145complement<T extends any[]>(predicate: (...args: T) => unknown): (...args: T) => boolean
3146```
3147
3148It returns `inverted` version of `origin` function that accept `input` as argument.
3149
3150The return value of `inverted` is the negative boolean value of `origin(input)`.
3151
3152<details>
3153
3154<summary>All Typescript definitions</summary>
3155
3156```typescript
3157complement<T extends any[]>(predicate: (...args: T) => unknown): (...args: T) => boolean;
3158```
3159
3160</details>
3161
3162<details>
3163
3164<summary><strong>R.complement</strong> source</summary>
3165
3166```javascript
3167export function complement(fn) {
3168 return (...input) => !fn(...input)
3169}
3170```
3171
3172</details>
3173
3174<details>
3175
3176<summary><strong>Tests</strong></summary>
3177
3178```javascript
3179import {complement} from './complement'
3180
3181test('happy', () => {
3182 const fn = complement(x => x.length === 0)
3183
3184 expect(fn([1, 2, 3])).toBeTrue()
3185})
3186
3187test('with multiple parameters', () => {
3188 const between = function (a, b, c) {
3189 return a < b && b < c
3190 }
3191 const f = complement(between)
3192 expect(f(4, 5, 11)).toEqual(false)
3193 expect(f(12, 2, 6)).toEqual(true)
3194})
3195```
3196
3197</details>
3198
3199<details>
3200
3201<summary><strong>Typescript</strong> test</summary>
3202
3203```typescript
3204import {complement, isNil} from 'rambda'
3205
3206describe('R.complement', () => {
3207 it('happy', () => {
3208 const fn = complement(isNil)
3209 const result = fn(null)
3210 result // $ExpectType boolean
3211 })
3212})
3213```
3214
3215</details>
3216
3217[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#complement)
3218
3219### compose
3220
3221It performs right-to-left function composition.
3222
3223[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#compose)
3224
3225### concat
3226
3227```typescript
3228
3229concat<T>(x: T[], y: T[]): T[]
3230```
3231
3232It returns a new string or array, which is the result of merging `x` and `y`.
3233
3234<details>
3235
3236<summary>All Typescript definitions</summary>
3237
3238```typescript
3239concat<T>(x: T[], y: T[]): T[];
3240concat<T>(x: T[]): (y: T[]) => T[];
3241concat(x: string, y: string): string;
3242concat(x: string): (y: string) => string;
3243```
3244
3245</details>
3246
3247<details>
3248
3249<summary><strong>R.concat</strong> source</summary>
3250
3251```javascript
3252export function concat(x, y) {
3253 if (arguments.length === 1) return _y => concat(x, _y)
3254
3255 return typeof x === 'string' ? `${x}${y}` : [...x, ...y]
3256}
3257```
3258
3259</details>
3260
3261<details>
3262
3263<summary><strong>Tests</strong></summary>
3264
3265```javascript
3266import {concat} from './concat'
3267
3268test('happy', () => {
3269 const arr1 = ['a', 'b', 'c']
3270 const arr2 = ['d', 'e', 'f']
3271
3272 const a = concat(arr1, arr2)
3273 const b = concat(arr1)(arr2)
3274 const expectedResult = ['a', 'b', 'c', 'd', 'e', 'f']
3275
3276 expect(a).toEqual(expectedResult)
3277 expect(b).toEqual(expectedResult)
3278})
3279
3280test('with strings', () => {
3281 expect(concat('ABC', 'DEF')).toEqual('ABCDEF')
3282})
3283```
3284
3285</details>
3286
3287<details>
3288
3289<summary><strong>Typescript</strong> test</summary>
3290
3291```typescript
3292import {concat} from 'rambda'
3293
3294const list1 = [1, 2, 3]
3295const list2 = [4, 5, 6]
3296
3297describe('R.concat', () => {
3298 it('happy', () => {
3299 const result = concat(list1, list2)
3300
3301 result // $ExpectType number[]
3302 })
3303 it('curried', () => {
3304 const result = concat(list1)(list2)
3305
3306 result // $ExpectType number[]
3307 })
3308})
3309```
3310
3311</details>
3312
3313[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#concat)
3314
3315### cond
3316
3317```typescript
3318
3319cond<T extends any[], R>(conditions: Array<CondPair<T, R>>): (...args: T) => R
3320```
3321
3322It takes list with `conditions` and returns a new function `fn` that expects `input` as argument.
3323
3324This function will start evaluating the `conditions` in order to find the first winner(order of conditions matter).
3325
3326The winner is this condition, which left side returns `true` when `input` is its argument. Then the evaluation of the right side of the winner will be the final result.
3327
3328If no winner is found, then `fn` returns `undefined`.
3329
3330<details>
3331
3332<summary>All Typescript definitions</summary>
3333
3334```typescript
3335cond<T extends any[], R>(conditions: Array<CondPair<T, R>>): (...args: T) => R;
3336```
3337
3338</details>
3339
3340<details>
3341
3342<summary><strong>R.cond</strong> source</summary>
3343
3344```javascript
3345export function cond(conditions) {
3346 return input => {
3347 let done = false
3348 let toReturn
3349 conditions.forEach(([predicate, resultClosure]) => {
3350 if (!done && predicate(input)) {
3351 done = true
3352 toReturn = resultClosure(input)
3353 }
3354 })
3355
3356 return toReturn
3357 }
3358}
3359```
3360
3361</details>
3362
3363<details>
3364
3365<summary><strong>Tests</strong></summary>
3366
3367```javascript
3368import {always} from './always'
3369import {cond} from './cond'
3370import {equals} from './equals'
3371import {T} from './T'
3372
3373test('returns a function', () => {
3374 expect(typeof cond([])).toEqual('function')
3375})
3376
3377test('returns a conditional function', () => {
3378 const fn = cond([
3379 [equals(0), always('water freezes at 0°C')],
3380 [equals(100), always('water boils at 100°C')],
3381 [
3382 T,
3383 function (temp) {
3384 return 'nothing special happens at ' + temp + '°C'
3385 },
3386 ],
3387 ])
3388 expect(fn(0)).toEqual('water freezes at 0°C')
3389 expect(fn(50)).toEqual('nothing special happens at 50°C')
3390 expect(fn(100)).toEqual('water boils at 100°C')
3391})
3392
3393test('no winner', () => {
3394 const fn = cond([
3395 [equals('foo'), always(1)],
3396 [equals('bar'), always(2)],
3397 ])
3398 expect(fn('quux')).toEqual(undefined)
3399})
3400
3401test('predicates are tested in order', () => {
3402 const fn = cond([
3403 [T, always('foo')],
3404 [T, always('bar')],
3405 [T, always('baz')],
3406 ])
3407 expect(fn()).toEqual('foo')
3408})
3409```
3410
3411</details>
3412
3413<details>
3414
3415<summary><strong>Typescript</strong> test</summary>
3416
3417```typescript
3418import {cond, always, equals} from 'rambda'
3419
3420describe('R.cond', () => {
3421 it('happy', () => {
3422 const fn = cond<number[], string>([
3423 [equals(0), always('water freezes at 0°C')],
3424 [equals(100), always('water boils at 100°C')],
3425 [
3426 () => true,
3427 function(temp) {
3428 temp // $ExpectType number
3429 return 'nothing special happens at ' + temp + '°C'
3430 },
3431 ],
3432 ])
3433
3434 const result = fn(0)
3435 result // $ExpectType string
3436 })
3437})
3438```
3439
3440</details>
3441
3442[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#cond)
3443
3444### converge
3445
3446Accepts a converging function and a list of branching functions and returns a new function. When invoked, this new function is applied to some arguments, each branching function is applied to those same arguments. The results of each branching function are passed as arguments to the converging function to produce the return value.
3447
3448[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#converge)
3449
3450### curry
3451
3452It expects a function as input and returns its curried version.
3453
3454[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#curry)
3455
3456### curryN
3457
3458It returns a curried equivalent of the provided function, with the specified arity.
3459
3460[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#curryN)
3461
3462### dec
3463
3464It decrements a number.
3465
3466[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#dec)
3467
3468### defaultTo
3469
3470```typescript
3471
3472defaultTo<T>(defaultValue: T, input: T | null | undefined): T
3473```
3474
3475It returns `defaultValue`, if all of `inputArguments` are `undefined`, `null` or `NaN`.
3476
3477Else, it returns the first truthy `inputArguments` instance(from left to right).
3478
3479<details>
3480
3481<summary>All Typescript definitions</summary>
3482
3483```typescript
3484defaultTo<T>(defaultValue: T, input: T | null | undefined): T;
3485defaultTo<T>(defaultValue: T): (input: T | null | undefined) => T;
3486```
3487
3488</details>
3489
3490<details>
3491
3492<summary><strong>R.defaultTo</strong> source</summary>
3493
3494```javascript
3495function isFalsy(input) {
3496 return (
3497 input === undefined || input === null || Number.isNaN(input) === true
3498 )
3499}
3500
3501export function defaultTo(defaultArgument, input) {
3502 if (arguments.length === 1) {
3503 return _input => defaultTo(defaultArgument, _input)
3504 }
3505
3506 return isFalsy(input) ? defaultArgument : input
3507}
3508```
3509
3510</details>
3511
3512<details>
3513
3514<summary><strong>Tests</strong></summary>
3515
3516```javascript
3517import {defaultTo} from './defaultTo'
3518
3519test('with undefined', () => {
3520 expect(defaultTo('foo')(undefined)).toEqual('foo')
3521})
3522
3523test('with null', () => {
3524 expect(defaultTo('foo')(null)).toEqual('foo')
3525})
3526
3527test('with NaN', () => {
3528 expect(defaultTo('foo')(NaN)).toEqual('foo')
3529})
3530
3531test('with empty string', () => {
3532 expect(defaultTo('foo', '')).toEqual('')
3533})
3534
3535test('with false', () => {
3536 expect(defaultTo('foo', false)).toEqual(false)
3537})
3538
3539test('when inputArgument passes initial check', () => {
3540 expect(defaultTo('foo', 'bar')).toEqual('bar')
3541})
3542```
3543
3544</details>
3545
3546<details>
3547
3548<summary><strong>Typescript</strong> test</summary>
3549
3550```typescript
3551import {defaultTo} from 'rambda'
3552
3553describe('R.defaultTo with Ramda spec', () => {
3554 it('happy', () => {
3555 const result = defaultTo('foo', '')
3556 result // $ExpectType "" | "foo"
3557 })
3558 it('with explicit type', () => {
3559 const result = defaultTo<string>('foo', null)
3560 result // $ExpectType string
3561 })
3562})
3563```
3564
3565</details>
3566
3567<details>
3568
3569<summary>Rambda is faster than Ramda with 48.91%</summary>
3570
3571```text
3572const R = require('../../dist/rambda.js')
3573
3574const input = [null, undefined, 5]
3575
3576const defaultTo = [
3577 {
3578 label: 'Rambda',
3579 fn: () => {
3580 R.defaultTo(3, input[0])
3581 },
3582 },
3583 {
3584 label: 'Ramda',
3585 fn: () => {
3586 Ramda.defaultTo(3, input[0])
3587 },
3588 },
3589 {
3590 label: 'Rambda with multiple arguments',
3591 fn: () => {
3592 R.defaultTo(3, ...input)
3593 },
3594 },
3595]
3596```
3597
3598</details>
3599
3600[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#defaultTo)
3601
3602### difference
3603
3604```typescript
3605
3606difference<T>(a: T[], b: T[]): T[]
3607```
3608
3609It returns the uniq set of all elements in the first list `a` not contained in the second list `b`.
3610
3611`R.equals` is used to determine equality.
3612
3613<details>
3614
3615<summary>All Typescript definitions</summary>
3616
3617```typescript
3618difference<T>(a: T[], b: T[]): T[];
3619difference<T>(a: T[]): (b: T[]) => T[];
3620```
3621
3622</details>
3623
3624<details>
3625
3626<summary><strong>R.difference</strong> source</summary>
3627
3628```javascript
3629import {includes} from './includes'
3630import {uniq} from './uniq'
3631
3632export function difference(a, b) {
3633 if (arguments.length === 1) return _b => difference(a, _b)
3634
3635 return uniq(a).filter(aInstance => !includes(aInstance, b))
3636}
3637```
3638
3639</details>
3640
3641<details>
3642
3643<summary><strong>Tests</strong></summary>
3644
3645```javascript
3646import {difference} from './difference'
3647import {difference as differenceRamda} from 'ramda'
3648
3649test('difference', () => {
3650 const a = [1, 2, 3, 4]
3651 const b = [3, 4, 5, 6]
3652 expect(difference(a)(b)).toEqual([1, 2])
3653
3654 expect(difference([], [])).toEqual([])
3655})
3656
3657test('difference with objects', () => {
3658 const a = [{id: 1}, {id: 2}, {id: 3}, {id: 4}]
3659 const b = [{id: 3}, {id: 4}, {id: 5}, {id: 6}]
3660 expect(difference(a, b)).toEqual([{id: 1}, {id: 2}])
3661})
3662
3663test('no duplicates in first list', () => {
3664 const M2 = [1, 2, 3, 4, 1, 2, 3, 4]
3665 const N2 = [3, 3, 4, 4, 5, 5, 6, 6]
3666 expect(difference(M2, N2)).toEqual([1, 2])
3667})
3668
3669test('should use R.equals', () => {
3670 expect(difference([1], [1]).length).toEqual(0)
3671 expect(differenceRamda([NaN], [NaN]).length).toEqual(0)
3672})
3673```
3674
3675</details>
3676
3677<details>
3678
3679<summary><strong>Typescript</strong> test</summary>
3680
3681```typescript
3682import {difference} from 'rambda'
3683
3684const list1 = [1, 2, 3]
3685const list2 = [1, 2, 4]
3686
3687describe('R.difference', () => {
3688 it('happy', () => {
3689 const result = difference(list1, list2)
3690
3691 result // $ExpectType number[]
3692 })
3693 it('curried', () => {
3694 const result = difference(list1)(list2)
3695
3696 result // $ExpectType number[]
3697 })
3698})
3699```
3700
3701</details>
3702
3703[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#difference)
3704
3705### dissoc
3706
3707It returns a new object that does not contain property `prop`.
3708
3709[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#dissoc)
3710
3711### divide
3712
3713[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#divide)
3714
3715### drop
3716
3717```typescript
3718
3719drop<T>(howMany: number, input: T[]): T[]
3720```
3721
3722It returns `howMany` items dropped from beginning of list or string `input`.
3723
3724<details>
3725
3726<summary>All Typescript definitions</summary>
3727
3728```typescript
3729drop<T>(howMany: number, input: T[]): T[];
3730drop(howMany: number, input: string): string;
3731drop<T>(howMany: number): {
3732 <T>(input: T[]): T[];
3733 (input: string): string;
3734};
3735```
3736
3737</details>
3738
3739<details>
3740
3741<summary><strong>R.drop</strong> source</summary>
3742
3743```javascript
3744export function drop(howManyToDrop, listOrString) {
3745 if (arguments.length === 1) return _list => drop(howManyToDrop, _list)
3746
3747 return listOrString.slice(howManyToDrop > 0 ? howManyToDrop : 0)
3748}
3749```
3750
3751</details>
3752
3753<details>
3754
3755<summary><strong>Tests</strong></summary>
3756
3757```javascript
3758import assert from 'assert'
3759
3760import {drop} from './drop'
3761
3762test('with array', () => {
3763 expect(drop(2)(['foo', 'bar', 'baz'])).toEqual(['baz'])
3764 expect(drop(3, ['foo', 'bar', 'baz'])).toEqual([])
3765 expect(drop(4, ['foo', 'bar', 'baz'])).toEqual([])
3766})
3767
3768test('with string', () => {
3769 expect(drop(3, 'rambda')).toEqual('bda')
3770})
3771
3772test('with non-positive count', () => {
3773 expect(drop(0, [1, 2, 3])).toEqual([1, 2, 3])
3774 expect(drop(-1, [1, 2, 3])).toEqual([1, 2, 3])
3775 expect(drop(-Infinity, [1, 2, 3])).toEqual([1, 2, 3])
3776})
3777
3778test('should return copy', () => {
3779 const xs = [1, 2, 3]
3780
3781 assert.notStrictEqual(drop(0, xs), xs)
3782 assert.notStrictEqual(drop(-1, xs), xs)
3783})
3784```
3785
3786</details>
3787
3788<details>
3789
3790<summary><strong>Typescript</strong> test</summary>
3791
3792```typescript
3793import {drop} from 'rambda'
3794
3795const list = [1, 2, 3, 4]
3796const str = 'foobar'
3797const howMany = 2
3798
3799describe('R.drop - array', () => {
3800 it('happy', () => {
3801 const result = drop(howMany, list)
3802 result // $ExpectType number[]
3803 })
3804 it('curried', () => {
3805 const result = drop(howMany)(list)
3806 result // $ExpectType number[]
3807 })
3808})
3809
3810describe('R.drop - string', () => {
3811 it('happy', () => {
3812 const result = drop(howMany, str)
3813 result // $ExpectType string
3814 })
3815 it('curried', () => {
3816 const result = drop(howMany)(str)
3817 result // $ExpectType string
3818 })
3819})
3820```
3821
3822</details>
3823
3824<details>
3825
3826<summary>Rambda is faster than Ramda with 82.35%</summary>
3827
3828```text
3829const R = require('../../dist/rambda.js')
3830
3831const input = [1, 2, 3, 4]
3832
3833const drop = [
3834 {
3835 label: 'Rambda',
3836 fn: () => {
3837 R.drop(3, input)
3838 },
3839 },
3840 {
3841 label: 'Ramda',
3842 fn: () => {
3843 Ramda.drop(3, input)
3844 },
3845 },
3846]
3847```
3848
3849</details>
3850
3851[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#drop)
3852
3853### dropLast
3854
3855```typescript
3856
3857dropLast<T>(howMany: number, input: T[]): T[]
3858```
3859
3860It returns `howMany` items dropped from the end of list or string `input`.
3861
3862<details>
3863
3864<summary>All Typescript definitions</summary>
3865
3866```typescript
3867dropLast<T>(howMany: number, input: T[]): T[];
3868dropLast(howMany: number, input: string): string;
3869dropLast<T>(howMany: number): {
3870 <T>(input: T[]): T[];
3871 (input: string): string;
3872};
3873```
3874
3875</details>
3876
3877<details>
3878
3879<summary><strong>R.dropLast</strong> source</summary>
3880
3881```javascript
3882export function dropLast(howManyToDrop, listOrString) {
3883 if (arguments.length === 1) {
3884 return _listOrString => dropLast(howManyToDrop, _listOrString)
3885 }
3886
3887 return howManyToDrop > 0
3888 ? listOrString.slice(0, -howManyToDrop)
3889 : listOrString.slice()
3890}
3891```
3892
3893</details>
3894
3895<details>
3896
3897<summary><strong>Tests</strong></summary>
3898
3899```javascript
3900import assert from 'assert'
3901
3902import {dropLast} from './dropLast'
3903
3904test('with array', () => {
3905 expect(dropLast(2)(['foo', 'bar', 'baz'])).toEqual(['foo'])
3906 expect(dropLast(3, ['foo', 'bar', 'baz'])).toEqual([])
3907 expect(dropLast(4, ['foo', 'bar', 'baz'])).toEqual([])
3908})
3909
3910test('with string', () => {
3911 expect(dropLast(3, 'rambda')).toEqual('ram')
3912})
3913
3914test('with non-positive count', () => {
3915 expect(dropLast(0, [1, 2, 3])).toEqual([1, 2, 3])
3916 expect(dropLast(-1, [1, 2, 3])).toEqual([1, 2, 3])
3917 expect(dropLast(-Infinity, [1, 2, 3])).toEqual([1, 2, 3])
3918})
3919
3920test('should return copy', () => {
3921 const xs = [1, 2, 3]
3922
3923 assert.notStrictEqual(dropLast(0, xs), xs)
3924 assert.notStrictEqual(dropLast(-1, xs), xs)
3925})
3926```
3927
3928</details>
3929
3930<details>
3931
3932<summary><strong>Typescript</strong> test</summary>
3933
3934```typescript
3935import {dropLast} from 'rambda'
3936
3937const list = [1, 2, 3, 4]
3938const str = 'foobar'
3939const howMany = 2
3940
3941describe('R.dropLast - array', () => {
3942 it('happy', () => {
3943 const result = dropLast(howMany, list)
3944 result // $ExpectType number[]
3945 })
3946 it('curried', () => {
3947 const result = dropLast(howMany)(list)
3948 result // $ExpectType number[]
3949 })
3950})
3951
3952describe('R.dropLast - string', () => {
3953 it('happy', () => {
3954 const result = dropLast(howMany, str)
3955 result // $ExpectType string
3956 })
3957 it('curried', () => {
3958 const result = dropLast(howMany)(str)
3959 result // $ExpectType string
3960 })
3961})
3962```
3963
3964</details>
3965
3966<details>
3967
3968<summary>Rambda is faster than Ramda with 86.74%</summary>
3969
3970```text
3971const R = require('../../dist/rambda.js')
3972
3973const input = [1, 2, 3, 4]
3974
3975const dropLast = [
3976 {
3977 label: 'Rambda',
3978 fn: () => {
3979 R.dropLast(3, input)
3980 },
3981 },
3982 {
3983 label: 'Ramda',
3984 fn: () => {
3985 Ramda.dropLast(3, input)
3986 },
3987 },
3988]
3989```
3990
3991</details>
3992
3993[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#dropLast)
3994
3995### dropLastWhile
3996
3997[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#dropLastWhile)
3998
3999### dropRepeats
4000
4001```typescript
4002
4003dropRepeats<T>(list: T[]): T[]
4004```
4005
4006It removes any successive duplicates according to `R.equals`.
4007
4008<details>
4009
4010<summary>All Typescript definitions</summary>
4011
4012```typescript
4013dropRepeats<T>(list: T[]): T[];
4014```
4015
4016</details>
4017
4018<details>
4019
4020<summary><strong>R.dropRepeats</strong> source</summary>
4021
4022```javascript
4023import {_isArray} from './_internals/_isArray'
4024import {equals} from './equals'
4025
4026export function dropRepeats(list) {
4027 if (!_isArray(list)) {
4028 throw new Error(`${list} is not a list`)
4029 }
4030
4031 const toReturn = []
4032
4033 list.reduce((prev, current) => {
4034 if (!equals(prev, current)) {
4035 toReturn.push(current)
4036 }
4037
4038 return current
4039 }, undefined)
4040
4041 return toReturn
4042}
4043```
4044
4045</details>
4046
4047<details>
4048
4049<summary><strong>Tests</strong></summary>
4050
4051```javascript
4052import {dropRepeats as dropRepeatsRamda} from 'ramda'
4053
4054import {compareCombinations} from './_internals/testUtils'
4055import {add} from './add'
4056import {dropRepeats} from './dropRepeats'
4057
4058const list = [1, 2, 2, 2, 3, 4, 4, 5, 5, 3, 2, 2, {a: 1}, {a: 1}]
4059const listClean = [1, 2, 3, 4, 5, 3, 2, {a: 1}]
4060
4061test('happy', () => {
4062 const result = dropRepeats(list)
4063 expect(result).toEqual(listClean)
4064})
4065
4066const possibleLists = [
4067 [add(1), async () => {}, [1], [1], [2], [2]],
4068 [add(1), add(1), add(2)],
4069 [],
4070 1,
4071 /foo/g,
4072 Promise.resolve(1),
4073]
4074
4075describe('brute force', () => {
4076 compareCombinations({
4077 firstInput: possibleLists,
4078 callback: errorsCounters => {
4079 expect(errorsCounters).toMatchInlineSnapshot(`
4080 Object {
4081 "ERRORS_MESSAGE_MISMATCH": 0,
4082 "ERRORS_TYPE_MISMATCH": 0,
4083 "RESULTS_MISMATCH": 1,
4084 "SHOULD_NOT_THROW": 3,
4085 "SHOULD_THROW": 0,
4086 "TOTAL_TESTS": 6,
4087 }
4088 `)
4089 },
4090 fn: dropRepeats,
4091 fnRamda: dropRepeatsRamda,
4092 })
4093})
4094```
4095
4096</details>
4097
4098<details>
4099
4100<summary><strong>Typescript</strong> test</summary>
4101
4102```typescript
4103import {dropRepeats} from 'rambda'
4104
4105describe('R.dropRepeats', () => {
4106 it('happy', () => {
4107 const result = dropRepeats([1, 2, 2, 3])
4108
4109 result // $ExpectType number[]
4110 })
4111})
4112```
4113
4114</details>
4115
4116[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#dropRepeats)
4117
4118### dropRepeatsWith
4119
4120[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#dropRepeatsWith)
4121
4122### dropWhile
4123
4124[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#dropWhile)
4125
4126### either
4127
4128```typescript
4129
4130either(firstPredicate: Pred, secondPredicate: Pred): Pred
4131```
4132
4133It returns a new `predicate` function from `firstPredicate` and `secondPredicate` inputs.
4134
4135This `predicate` function will return `true`, if any of the two input predicates return `true`.
4136
4137<details>
4138
4139<summary>All Typescript definitions</summary>
4140
4141```typescript
4142either(firstPredicate: Pred, secondPredicate: Pred): Pred;
4143either<T>(firstPredicate: Predicate<T>, secondPredicate: Predicate<T>): Predicate<T>;
4144either<T>(firstPredicate: Predicate<T>): (secondPredicate: Predicate<T>) => Predicate<T>;
4145either(firstPredicate: Pred): (secondPredicate: Pred) => Pred;
4146```
4147
4148</details>
4149
4150<details>
4151
4152<summary><strong>R.either</strong> source</summary>
4153
4154```javascript
4155export function either(firstPredicate, secondPredicate) {
4156 if (arguments.length === 1) {
4157 return _secondPredicate => either(firstPredicate, _secondPredicate)
4158 }
4159
4160 return (...input) =>
4161 Boolean(firstPredicate(...input) || secondPredicate(...input))
4162}
4163```
4164
4165</details>
4166
4167<details>
4168
4169<summary><strong>Tests</strong></summary>
4170
4171```javascript
4172import {either} from './either'
4173
4174test('with multiple inputs', () => {
4175 const between = function (a, b, c) {
4176 return a < b && b < c
4177 }
4178 const total20 = function (a, b, c) {
4179 return a + b + c === 20
4180 }
4181 const fn = either(between, total20)
4182 expect(fn(7, 8, 5)).toBeTrue()
4183})
4184
4185test('skip evaluation of the second expression', () => {
4186 let effect = 'not evaluated'
4187 const F = function () {
4188 return true
4189 }
4190 const Z = function () {
4191 effect = 'Z got evaluated'
4192 }
4193 either(F, Z)()
4194
4195 expect(effect).toBe('not evaluated')
4196})
4197
4198test('case 1', () => {
4199 const firstFn = val => val > 0
4200 const secondFn = val => val * 5 > 10
4201
4202 expect(either(firstFn, secondFn)(1)).toBeTrue()
4203})
4204
4205test('case 2', () => {
4206 const firstFn = val => val > 0
4207 const secondFn = val => val === -10
4208 const fn = either(firstFn)(secondFn)
4209
4210 expect(fn(-10)).toBeTrue()
4211})
4212```
4213
4214</details>
4215
4216<details>
4217
4218<summary><strong>Typescript</strong> test</summary>
4219
4220```typescript
4221import {either} from 'rambda'
4222
4223describe('R.either', () => {
4224 it('with passed type', () => {
4225 const fn = either<number>(
4226 x => x > 1,
4227 x => x % 2 === 0
4228 )
4229 fn // $ExpectType Predicate<number>
4230 const result = fn(2) // $ExpectType boolean
4231 result // $ExpectType boolean
4232 })
4233 it('with passed type - curried', () => {
4234 const fn = either<number>(x => x > 1)(x => x % 2 === 0)
4235 fn // $ExpectType Predicate<number>
4236 const result = fn(2)
4237 result // $ExpectType boolean
4238 })
4239 it('no type passed', () => {
4240 const fn = either(
4241 x => {
4242 x // $ExpectType any
4243 return x > 1
4244 },
4245 x => {
4246 x // $ExpectType any
4247 return x % 2 === 0
4248 }
4249 )
4250 const result = fn(2)
4251 result // $ExpectType boolean
4252 })
4253 it('no type passed - curried', () => {
4254 const fn = either((x: number) => {
4255 x // $ExpectType number
4256 return x > 1
4257 })((x: number) => {
4258 x // $ExpectType number
4259 return x % 2 === 0
4260 })
4261 const result = fn(2)
4262 result // $ExpectType boolean
4263 })
4264})
4265```
4266
4267</details>
4268
4269[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#either)
4270
4271### endsWith
4272
4273```typescript
4274
4275endsWith(target: string, iterable: string): boolean
4276```
4277
4278When iterable is a string, then it behaves as `String.prototype.endsWith`.
4279When iterable is a list, then it uses R.equals to determine if the target list ends in the same way as the given target.
4280
4281<details>
4282
4283<summary>All Typescript definitions</summary>
4284
4285```typescript
4286endsWith(target: string, iterable: string): boolean;
4287endsWith(target: string): (iterable: string) => boolean;
4288endsWith<T>(target: T[], list: T[]): boolean;
4289endsWith<T>(target: T[]): (list: T[]) => boolean;
4290```
4291
4292</details>
4293
4294<details>
4295
4296<summary><strong>R.endsWith</strong> source</summary>
4297
4298```javascript
4299import {equals} from './equals.js'
4300import {_isArray} from './_internals/_isArray.js'
4301
4302export function endsWith(target, iterable) {
4303 if (arguments.length === 1) return _iterable => endsWith(target, _iterable)
4304
4305 if (typeof iterable === 'string') {
4306 return iterable.endsWith(target)
4307 }
4308 if (!_isArray(target)) return false
4309
4310 const diff = iterable.length - target.length
4311 let correct = true
4312 const filtered = target.filter((x, index) => {
4313 if (!correct) return false
4314 const result = equals(x, iterable[index + diff])
4315 if (!result) correct = false
4316 return result
4317 })
4318
4319 return filtered.length === target.length
4320}
4321```
4322
4323</details>
4324
4325<details>
4326
4327<summary><strong>Tests</strong></summary>
4328
4329```javascript
4330import {endsWith} from './endsWith'
4331import {endsWith as endsWithRamda} from 'ramda'
4332import {compareCombinations} from './_internals/testUtils'
4333
4334test('with string', () => {
4335 expect(endsWith('bar', 'foo-bar')).toBeTrue()
4336 expect(endsWith('baz')('foo-bar')).toBeFalse()
4337})
4338
4339test('use R.equals with array', () => {
4340 const list = [{a: 1}, {a: 2}, {a: 3}]
4341 expect(endsWith({a: 3}, list)).toBeFalse(),
4342 expect(endsWith([{a: 3}], list)).toBeTrue()
4343 expect(endsWith([{a: 2}, {a: 3}], list)).toBeTrue()
4344 expect(endsWith(list, list)).toBeTrue()
4345 expect(endsWith([{a: 1}], list)).toBeFalse()
4346})
4347
4348export const possibleTargets = [
4349 NaN,
4350 [NaN],
4351 /foo/,
4352 [/foo/],
4353 Promise.resolve(1),
4354 [Promise.resolve(1)],
4355 Error('foo'),
4356 [Error('foo')],
4357]
4358
4359export const possibleIterables = [
4360 [Promise.resolve(1), Promise.resolve(2)],
4361 [/foo/, /bar/],
4362 [NaN],
4363 [Error('foo'), Error('bar')],
4364]
4365
4366describe('brute force', () => {
4367 compareCombinations({
4368 fn: endsWith,
4369 fnRamda: endsWithRamda,
4370 firstInput: possibleTargets,
4371 secondInput: possibleIterables,
4372 callback: errorsCounters => {
4373 expect(errorsCounters).toMatchInlineSnapshot(`
4374 Object {
4375 "ERRORS_MESSAGE_MISMATCH": 0,
4376 "ERRORS_TYPE_MISMATCH": 0,
4377 "RESULTS_MISMATCH": 0,
4378 "SHOULD_NOT_THROW": 0,
4379 "SHOULD_THROW": 0,
4380 "TOTAL_TESTS": 32,
4381 }
4382 `)
4383 },
4384 })
4385})
4386```
4387
4388</details>
4389
4390<details>
4391
4392<summary><strong>Typescript</strong> test</summary>
4393
4394```typescript
4395import {endsWith} from 'rambda'
4396
4397describe('R.endsWith - array as iterable', () => {
4398 const target = [{a: 2}]
4399 const iterable = [{a: 1}, {a: 2}]
4400 it('happy', () => {
4401 const result = endsWith(target, iterable)
4402
4403 result // $ExpectType boolean
4404 })
4405 it('curried', () => {
4406 const result = endsWith(target)(iterable)
4407
4408 result // $ExpectType boolean
4409 })
4410})
4411
4412describe('R.endsWith - string as iterable', () => {
4413 const target = 'bar'
4414 const iterable = 'foo bar'
4415 it('happy', () => {
4416 const result = endsWith(target, iterable)
4417
4418 result // $ExpectType boolean
4419 })
4420 it('curried', () => {
4421 const result = endsWith(target)(iterable)
4422
4423 result // $ExpectType boolean
4424 })
4425})
4426```
4427
4428</details>
4429
4430[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#endsWith)
4431
4432### eqProps
4433
4434It returns `true` if property `prop` in `obj1` is equal to property `prop` in `obj2` according to `R.equals`.
4435
4436[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#eqProps)
4437
4438### equals
4439
4440```typescript
4441
4442equals<T>(x: T, y: T): boolean
4443```
4444
4445It deeply compares `x` and `y` and returns `true` if they are equal.
4446
4447<details>
4448
4449<summary>All Typescript definitions</summary>
4450
4451```typescript
4452equals<T>(x: T, y: T): boolean;
4453equals<T>(x: T): (y: T) => boolean;
4454```
4455
4456</details>
4457
4458<details>
4459
4460<summary><strong>R.equals</strong> source</summary>
4461
4462```javascript
4463import {type} from './type'
4464import {_isArray} from './_internals/_isArray'
4465
4466export function _lastIndexOf(valueToFind, list) {
4467 if (!_isArray(list)) {
4468 throw new Error(`Cannot read property 'indexOf' of ${list}`)
4469 }
4470 const typeOfValue = type(valueToFind)
4471 if (!['Object', 'Array', 'NaN', 'RegExp'].includes(typeOfValue))
4472 return list.lastIndexOf(valueToFind)
4473
4474 const {length} = list
4475 let index = length
4476 let foundIndex = -1
4477
4478 while (--index > -1 && foundIndex === -1) {
4479 if (equals(list[index], valueToFind)) {
4480 foundIndex = index
4481 }
4482 }
4483
4484 return foundIndex
4485}
4486
4487export function _indexOf(valueToFind, list) {
4488 if (!_isArray(list)) {
4489 throw new Error(`Cannot read property 'indexOf' of ${list}`)
4490 }
4491 const typeOfValue = type(valueToFind)
4492 if (!['Object', 'Array', 'NaN', 'RegExp'].includes(typeOfValue))
4493 return list.indexOf(valueToFind)
4494
4495 let index = -1
4496 let foundIndex = -1
4497 const {length} = list
4498
4499 while (++index < length && foundIndex === -1) {
4500 if (equals(list[index], valueToFind)) {
4501 foundIndex = index
4502 }
4503 }
4504
4505 return foundIndex
4506}
4507
4508function _arrayFromIterator(iter) {
4509 const list = []
4510 let next
4511 while (!(next = iter.next()).done) {
4512 list.push(next.value)
4513 }
4514 return list
4515}
4516
4517function _equalsSets(a, b) {
4518 if (a.size !== b.size) {
4519 return false
4520 }
4521 const aList = _arrayFromIterator(a.values())
4522 const bList = _arrayFromIterator(b.values())
4523
4524 const filtered = aList.filter(
4525 aInstance => _indexOf(aInstance, bList) === -1
4526 )
4527 return filtered.length === 0
4528}
4529
4530function parseError(maybeError) {
4531 const typeofError = maybeError.__proto__.toString()
4532 if (!['Error', 'TypeError'].includes(typeofError)) return []
4533
4534 return [typeofError, maybeError.message]
4535}
4536
4537function parseDate(maybeDate) {
4538 if (!maybeDate.toDateString) return [false]
4539
4540 return [true, maybeDate.getTime()]
4541}
4542
4543function parseRegex(maybeRegex) {
4544 if (maybeRegex.constructor !== RegExp) return [false]
4545
4546 return [true, maybeRegex.toString()]
4547}
4548
4549function equalsSets(a, b) {
4550 if (a.size !== b.size) {
4551 return false
4552 }
4553 const aList = _arrayFromIterator(a.values())
4554 const bList = _arrayFromIterator(b.values())
4555
4556 const filtered = aList.filter(
4557 aInstance => _indexOf(aInstance, bList) === -1
4558 )
4559 return filtered.length === 0
4560}
4561
4562export function equals(a, b) {
4563 if (arguments.length === 1) return _b => equals(a, _b)
4564
4565 const aType = type(a)
4566
4567 if (aType !== type(b)) return false
4568 if (aType === 'Function') {
4569 return a.name === undefined ? false : a.name === b.name
4570 }
4571
4572 if (['NaN', 'Undefined', 'Null'].includes(aType)) return true
4573
4574 if (aType === 'Number') {
4575 if (Object.is(-0, a) !== Object.is(-0, b)) return false
4576
4577 return a.toString() === b.toString()
4578 }
4579
4580 if (['String', 'Boolean'].includes(aType)) {
4581 return a.toString() === b.toString()
4582 }
4583
4584 if (aType === 'Array') {
4585 const aClone = Array.from(a)
4586 const bClone = Array.from(b)
4587
4588 if (aClone.toString() !== bClone.toString()) {
4589 return false
4590 }
4591
4592 let loopArrayFlag = true
4593 aClone.forEach((aCloneInstance, aCloneIndex) => {
4594 if (loopArrayFlag) {
4595 if (
4596 aCloneInstance !== bClone[aCloneIndex] &&
4597 !equals(aCloneInstance, bClone[aCloneIndex])
4598 ) {
4599 loopArrayFlag = false
4600 }
4601 }
4602 })
4603
4604 return loopArrayFlag
4605 }
4606
4607 const aRegex = parseRegex(a)
4608 const bRegex = parseRegex(b)
4609
4610 if (aRegex[0]) {
4611 return bRegex[0] ? aRegex[1] === bRegex[1] : false
4612 } else if (bRegex[0]) return false
4613
4614 const aDate = parseDate(a)
4615 const bDate = parseDate(b)
4616
4617 if (aDate[0]) {
4618 return bDate[0] ? aDate[1] === bDate[1] : false
4619 } else if (bDate[0]) return false
4620
4621 const aError = parseError(a)
4622 const bError = parseError(b)
4623
4624 if (aError[0]) {
4625 return bError[0]
4626 ? aError[0] === bError[0] && aError[1] === bError[1]
4627 : false
4628 }
4629 if (aType === 'Set') {
4630 return _equalsSets(a, b)
4631 }
4632 if (aType === 'Object') {
4633 const aKeys = Object.keys(a)
4634
4635 if (aKeys.length !== Object.keys(b).length) {
4636 return false
4637 }
4638
4639 let loopObjectFlag = true
4640 aKeys.forEach(aKeyInstance => {
4641 if (loopObjectFlag) {
4642 const aValue = a[aKeyInstance]
4643 const bValue = b[aKeyInstance]
4644
4645 if (aValue !== bValue && !equals(aValue, bValue)) {
4646 loopObjectFlag = false
4647 }
4648 }
4649 })
4650
4651 return loopObjectFlag
4652 }
4653
4654 return false
4655}
4656```
4657
4658</details>
4659
4660<details>
4661
4662<summary><strong>Tests</strong></summary>
4663
4664```javascript
4665import {equals} from './equals'
4666import {equals as equalsRamda} from 'ramda'
4667import {compareCombinations} from './_internals/testUtils'
4668import {variousTypes} from './benchmarks/_utils'
4669
4670test('compare functions', () => {
4671 function foo() {}
4672 function bar() {}
4673 const baz = () => {}
4674
4675 const expectTrue = equals(foo, foo)
4676 const expectFalseFirst = equals(foo, bar)
4677 const expectFalseSecond = equals(foo, baz)
4678
4679 expect(expectTrue).toBeTrue()
4680 expect(expectFalseFirst).toBeFalse()
4681 expect(expectFalseSecond).toBeFalse()
4682})
4683
4684test('with array of objects', () => {
4685 const list1 = [{a: 1}, [{b: 2}]]
4686 const list2 = [{a: 1}, [{b: 2}]]
4687 const list3 = [{a: 1}, [{b: 3}]]
4688
4689 expect(equals(list1, list2)).toBeTrue()
4690 expect(equals(list1, list3)).toBeFalse()
4691})
4692
4693test('with regex', () => {
4694 expect(equals(/s/, /s/)).toEqual(true)
4695 expect(equals(/s/, /d/)).toEqual(false)
4696 expect(equals(/a/gi, /a/gi)).toEqual(true)
4697 expect(equals(/a/gim, /a/gim)).toEqual(true)
4698 expect(equals(/a/gi, /a/i)).toEqual(false)
4699})
4700
4701test('not a number', () => {
4702 expect(equals([NaN], [NaN])).toBeTrue()
4703})
4704
4705test('new number', () => {
4706 expect(equals(new Number(0), new Number(0))).toEqual(true)
4707 expect(equals(new Number(0), new Number(1))).toEqual(false)
4708 expect(equals(new Number(1), new Number(0))).toEqual(false)
4709})
4710
4711test('new string', () => {
4712 expect(equals(new String(''), new String(''))).toEqual(true)
4713 expect(equals(new String(''), new String('x'))).toEqual(false)
4714 expect(equals(new String('x'), new String(''))).toEqual(false)
4715 expect(equals(new String('foo'), new String('foo'))).toEqual(true)
4716 expect(equals(new String('foo'), new String('bar'))).toEqual(false)
4717 expect(equals(new String('bar'), new String('foo'))).toEqual(false)
4718})
4719
4720test('new Boolean', () => {
4721 expect(equals(new Boolean(true), new Boolean(true))).toEqual(true)
4722 expect(equals(new Boolean(false), new Boolean(false))).toEqual(true)
4723 expect(equals(new Boolean(true), new Boolean(false))).toEqual(false)
4724 expect(equals(new Boolean(false), new Boolean(true))).toEqual(false)
4725})
4726
4727test('new Error', () => {
4728 expect(equals(new Error('XXX'), {})).toEqual(false)
4729 expect(equals(new Error('XXX'), new TypeError('XXX'))).toEqual(false)
4730 expect(equals(new Error('XXX'), new Error('YYY'))).toEqual(false)
4731 expect(equals(new Error('XXX'), new Error('XXX'))).toEqual(true)
4732 expect(equals(new Error('XXX'), new TypeError('YYY'))).toEqual(false)
4733})
4734
4735test('with dates', () => {
4736 expect(equals(new Date(0), new Date(0))).toEqual(true)
4737 expect(equals(new Date(1), new Date(1))).toEqual(true)
4738 expect(equals(new Date(0), new Date(1))).toEqual(false)
4739 expect(equals(new Date(1), new Date(0))).toEqual(false)
4740 expect(equals(new Date(0), {})).toEqual(false)
4741 expect(equals({}, new Date(0))).toEqual(false)
4742})
4743
4744test('ramda spec', () => {
4745 expect(equals({}, {})).toEqual(true)
4746
4747 expect(
4748 equals(
4749 {
4750 a: 1,
4751 b: 2,
4752 },
4753 {
4754 a: 1,
4755 b: 2,
4756 }
4757 )
4758 ).toEqual(true)
4759
4760 expect(
4761 equals(
4762 {
4763 a: 2,
4764 b: 3,
4765 },
4766 {
4767 b: 3,
4768 a: 2,
4769 }
4770 )
4771 ).toEqual(true)
4772
4773 expect(
4774 equals(
4775 {
4776 a: 2,
4777 b: 3,
4778 },
4779 {
4780 a: 3,
4781 b: 3,
4782 }
4783 )
4784 ).toEqual(false)
4785
4786 expect(
4787 equals(
4788 {
4789 a: 2,
4790 b: 3,
4791 c: 1,
4792 },
4793 {
4794 a: 2,
4795 b: 3,
4796 }
4797 )
4798 ).toEqual(false)
4799})
4800
4801test('works with boolean tuple', () => {
4802 expect(equals([true, false], [true, false])).toBeTrue()
4803 expect(equals([true, false], [true, true])).toBeFalse()
4804})
4805
4806test('works with equal objects within array', () => {
4807 const objFirst = {
4808 a: {
4809 b: 1,
4810 c: 2,
4811 d: [1],
4812 },
4813 }
4814 const objSecond = {
4815 a: {
4816 b: 1,
4817 c: 2,
4818 d: [1],
4819 },
4820 }
4821
4822 const x = [1, 2, objFirst, null, '', []]
4823 const y = [1, 2, objSecond, null, '', []]
4824 expect(equals(x, y)).toBeTrue()
4825})
4826
4827test('works with different objects within array', () => {
4828 const objFirst = {a: {b: 1}}
4829 const objSecond = {a: {b: 2}}
4830
4831 const x = [1, 2, objFirst, null, '', []]
4832 const y = [1, 2, objSecond, null, '', []]
4833 expect(equals(x, y)).toBeFalse()
4834})
4835
4836test('works with undefined as second argument', () => {
4837 expect(equals(1, undefined)).toBeFalse()
4838
4839 expect(equals(undefined, undefined)).toBeTrue()
4840})
4841
4842test('compare sets', () => {
4843 const toCompareDifferent = new Set([{a: 1}, {a: 2}])
4844 const toCompareSame = new Set([{a: 1}, {a: 2}, {a: 1}])
4845 const testSet = new Set([{a: 1}, {a: 2}, {a: 1}])
4846 expect(equals(toCompareSame, testSet)).toBeTruthy()
4847 expect(equals(toCompareDifferent, testSet)).toBeFalsy()
4848 expect(equalsRamda(toCompareSame, testSet)).toBeTruthy()
4849 expect(equalsRamda(toCompareDifferent, testSet)).toBeFalsy()
4850})
4851
4852test('compare simple sets', () => {
4853 const testSet = new Set(['2', '3', '3', '2', '1'])
4854 expect(equals(new Set(['3', '2', '1']), testSet)).toBeTruthy()
4855 expect(equals(new Set(['3', '2', '0']), testSet)).toBeFalsy()
4856})
4857
4858test('various examples', () => {
4859 expect(equals([1, 2, 3])([1, 2, 3])).toBeTrue()
4860
4861 expect(equals([1, 2, 3], [1, 2])).toBeFalse()
4862
4863 expect(equals(1, 1)).toBeTrue()
4864
4865 expect(equals(1, '1')).toBeFalse()
4866
4867 expect(equals({}, {})).toBeTrue()
4868
4869 expect(
4870 equals(
4871 {
4872 a: 1,
4873 b: 2,
4874 },
4875 {
4876 b: 2,
4877 a: 1,
4878 }
4879 )
4880 ).toBeTrue()
4881
4882 expect(
4883 equals(
4884 {
4885 a: 1,
4886 b: 2,
4887 },
4888 {
4889 a: 1,
4890 b: 1,
4891 }
4892 )
4893 ).toBeFalse()
4894
4895 expect(
4896 equals(
4897 {
4898 a: 1,
4899 b: false,
4900 },
4901 {
4902 a: 1,
4903 b: 1,
4904 }
4905 )
4906 ).toBeFalse()
4907
4908 expect(
4909 equals(
4910 {
4911 a: 1,
4912 b: 2,
4913 },
4914 {
4915 b: 2,
4916 a: 1,
4917 c: 3,
4918 }
4919 )
4920 ).toBeFalse()
4921
4922 expect(
4923 equals(
4924 {
4925 x: {
4926 a: 1,
4927 b: 2,
4928 },
4929 },
4930 {
4931 x: {
4932 b: 2,
4933 a: 1,
4934 c: 3,
4935 },
4936 }
4937 )
4938 ).toBeFalse()
4939
4940 expect(
4941 equals(
4942 {
4943 a: 1,
4944 b: 2,
4945 },
4946 {
4947 b: 3,
4948 a: 1,
4949 }
4950 )
4951 ).toBeFalse()
4952
4953 expect(equals({a: {b: {c: 1}}}, {a: {b: {c: 1}}})).toBeTrue()
4954
4955 expect(equals({a: {b: {c: 1}}}, {a: {b: {c: 2}}})).toBeFalse()
4956
4957 expect(equals({a: {}}, {a: {}})).toBeTrue()
4958
4959 expect(equals('', '')).toBeTrue()
4960
4961 expect(equals('foo', 'foo')).toBeTrue()
4962
4963 expect(equals('foo', 'bar')).toBeFalse()
4964
4965 expect(equals(0, false)).toBeFalse()
4966
4967 expect(equals(/\s/g, null)).toBeFalse()
4968
4969 expect(equals(null, null)).toBeTrue()
4970
4971 expect(equals(false)(null)).toBeFalse()
4972})
4973
4974test('with custom functions', () => {
4975 function foo() {
4976 return 1
4977 }
4978 foo.prototype.toString = () => ''
4979 const result = equals(foo, foo)
4980
4981 expect(result).toBeTrue()
4982})
4983
4984test('with classes', () => {
4985 class Foo {}
4986 const foo = new Foo()
4987 const result = equals(foo, foo)
4988
4989 expect(result).toBeTrue()
4990})
4991
4992test('with negative zero', () => {
4993 expect(equals(-0, -0)).toBeTrue()
4994 expect(equals(-0, 0)).toBeFalse()
4995 expect(equals(0, 0)).toBeTrue()
4996 expect(equals(-0, 1)).toBeFalse()
4997})
4998
4999const possibleInputs = variousTypes
5000
5001describe('brute force', () => {
5002 compareCombinations({
5003 fn: equals,
5004 fnRamda: equalsRamda,
5005 firstInput: possibleInputs,
5006 secondInput: possibleInputs,
5007 callback: errorsCounters => {
5008 expect(errorsCounters).toMatchInlineSnapshot(`
5009 Object {
5010 "ERRORS_MESSAGE_MISMATCH": 0,
5011 "ERRORS_TYPE_MISMATCH": 0,
5012 "RESULTS_MISMATCH": 5,
5013 "SHOULD_NOT_THROW": 4,
5014 "SHOULD_THROW": 0,
5015 "TOTAL_TESTS": 289,
5016 }
5017 `)
5018 },
5019 })
5020})
5021```
5022
5023</details>
5024
5025<details>
5026
5027<summary><strong>Typescript</strong> test</summary>
5028
5029```typescript
5030import {equals} from 'rambda'
5031
5032describe('R.equals', () => {
5033 it('happy', () => {
5034 const result = equals(4, 1)
5035 result // $ExpectType boolean
5036 })
5037 it('with object', () => {
5038 const foo = {a: 1}
5039 const bar = {a: 2}
5040 const result = equals(foo, bar)
5041 result // $ExpectType boolean
5042 })
5043 it('curried', () => {
5044 const result = equals(4)(1)
5045
5046 result // $ExpectType boolean
5047 })
5048})
5049```
5050
5051</details>
5052
5053<details>
5054
5055<summary>Lodash is fastest. Rambda is 58.37% slower and Ramda is 96.73% slower</summary>
5056
5057```text
5058const R = require('../../dist/rambda.js')
5059
5060const limit = 10000
5061
5062const strings = Array(limit)
5063 .fill(null)
5064 .map(() => Math.floor(Math.random() * 1000))
5065
5066const equals = [
5067 {
5068 label: 'Rambda',
5069 fn: () => {
5070 strings.forEach(x => R.equals(x, 'ss'))
5071 },
5072 },
5073 {
5074 label: 'Ramda',
5075 fn: () => {
5076 strings.forEach(x => Ramda.equals(x, 'ss'))
5077 },
5078 },
5079 {
5080 label: 'Lodash',
5081 fn: () => {
5082 strings.forEach(x => _.isEqual(x, 'ss'))
5083 },
5084 },
5085]
5086```
5087
5088</details>
5089
5090[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#equals)
5091
5092### evolve
5093
5094```typescript
5095
5096evolve<T, U>(rules: ((x: T) => U)[], list: T[]): U[]
5097```
5098
5099It takes object or array of functions as set of rules. These `rules` are applied to the `iterable` input to produce the result.
5100
5101<details>
5102
5103<summary>All Typescript definitions</summary>
5104
5105```typescript
5106evolve<T, U>(rules: ((x: T) => U)[], list: T[]): U[];
5107evolve<T, U>(rules: ((x: T) => U)[]) : (list: T[]) => U[];
5108evolve<E extends Evolver, V extends Evolvable<E>>(rules: E, obj: V): Evolve<V, E>;
5109evolve<E extends Evolver>(rules: E): <V extends Evolvable<E>>(obj: V) => Evolve<V, E>;
5110```
5111
5112</details>
5113
5114<details>
5115
5116<summary><strong>R.evolve</strong> source</summary>
5117
5118```javascript
5119import {_isArray} from './_internals/_isArray'
5120import {mapArray, mapObject} from './map'
5121import {type} from './type'
5122
5123export function evolveArray(rules, list) {
5124 return mapArray(
5125 (x, i) => {
5126 if (type(rules[i]) === 'Function') {
5127 return rules[i](x)
5128 }
5129
5130 return x
5131 },
5132 list,
5133 true
5134 )
5135}
5136
5137export function evolveObject(rules, iterable) {
5138 return mapObject((x, prop) => {
5139 if (type(x) === 'Object') {
5140 const typeRule = type(rules[prop])
5141 if (typeRule === 'Function') {
5142 return rules[prop](x)
5143 }
5144 if (typeRule === 'Object') {
5145 return evolve(rules[prop], x)
5146 }
5147
5148 return x
5149 }
5150 if (type(rules[prop]) === 'Function') {
5151 return rules[prop](x)
5152 }
5153
5154 return x
5155 }, iterable)
5156}
5157
5158export function evolve(rules, iterable) {
5159 if (arguments.length === 1) {
5160 return _iterable => evolve(rules, _iterable)
5161 }
5162 const rulesType = type(rules)
5163 const iterableType = type(iterable)
5164
5165 if (iterableType !== rulesType) {
5166 throw new Error('iterableType !== rulesType')
5167 }
5168
5169 if (!['Object', 'Array'].includes(rulesType)) {
5170 throw new Error(
5171 `'iterable' and 'rules' are from wrong type ${rulesType}`
5172 )
5173 }
5174
5175 if (iterableType === 'Object') {
5176 return evolveObject(rules, iterable)
5177 }
5178
5179 return evolveArray(rules, iterable)
5180}
5181```
5182
5183</details>
5184
5185<details>
5186
5187<summary><strong>Tests</strong></summary>
5188
5189```javascript
5190import {evolve as evolveRamda} from 'ramda'
5191
5192import {add} from '../rambda'
5193import {compareCombinations, compareToRamda} from './_internals/testUtils'
5194import {evolve} from './evolve'
5195
5196test('happy', () => {
5197 const rules = {
5198 foo: add(1),
5199 nested: {bar: x => Object.keys(x).length},
5200 }
5201 const input = {
5202 a: 1,
5203 foo: 2,
5204 nested: {bar: {z: 3}},
5205 }
5206 const result = evolve(rules, input)
5207 expect(result).toEqual({
5208 a: 1,
5209 foo: 3,
5210 nested: {bar: 1},
5211 })
5212})
5213
5214test('nested rule is wrong', () => {
5215 const rules = {
5216 foo: add(1),
5217 nested: {bar: 10},
5218 }
5219 const input = {
5220 a: 1,
5221 foo: 2,
5222 nested: {bar: {z: 3}},
5223 }
5224 const result = evolve(rules)(input)
5225 expect(result).toEqual({
5226 a: 1,
5227 foo: 3,
5228 nested: {bar: {z: 3}},
5229 })
5230})
5231
5232test('is recursive', () => {
5233 const rules = {
5234 nested: {
5235 second: add(-1),
5236 third: add(1),
5237 },
5238 }
5239 const object = {
5240 first: 1,
5241 nested: {
5242 second: 2,
5243 third: 3,
5244 },
5245 }
5246 const expected = {
5247 first: 1,
5248 nested: {
5249 second: 1,
5250 third: 4,
5251 },
5252 }
5253 const result = evolve(rules, object)
5254 expect(result).toEqual(expected)
5255})
5256
5257test('ignores primitive values', () => {
5258 const rules = {
5259 n: 2,
5260 m: 'foo',
5261 }
5262 const object = {
5263 n: 0,
5264 m: 1,
5265 }
5266 const expected = {
5267 n: 0,
5268 m: 1,
5269 }
5270 const result = evolve(rules, object)
5271 expect(result).toEqual(expected)
5272})
5273
5274test('with array', () => {
5275 const rules = [add(1), add(-1)]
5276 const list = [100, 1400]
5277 const expected = [101, 1399]
5278 const result = evolve(rules, list)
5279 expect(result).toEqual(expected)
5280})
5281
5282const rulesObject = {a: add(1)}
5283const rulesList = [add(1)]
5284const possibleIterables = [null, undefined, '', 42, [], [1], {a: 1}]
5285const possibleRules = [...possibleIterables, rulesList, rulesObject]
5286
5287describe('brute force', () => {
5288 compareCombinations({
5289 firstInput: possibleRules,
5290 callback: errorsCounters => {
5291 expect(errorsCounters).toMatchInlineSnapshot(`
5292 Object {
5293 "ERRORS_MESSAGE_MISMATCH": 0,
5294 "ERRORS_TYPE_MISMATCH": 4,
5295 "RESULTS_MISMATCH": 0,
5296 "SHOULD_NOT_THROW": 51,
5297 "SHOULD_THROW": 0,
5298 "TOTAL_TESTS": 63,
5299 }
5300 `)
5301 },
5302 secondInput: possibleIterables,
5303 fn: evolve,
5304 fnRamda: evolveRamda,
5305 })
5306})
5307```
5308
5309</details>
5310
5311<details>
5312
5313<summary><strong>Typescript</strong> test</summary>
5314
5315```typescript
5316import {evolve, add} from 'rambda'
5317
5318describe('R.evolve', () => {
5319 it('happy', () => {
5320 const input = {
5321 foo: 2,
5322 nested: {
5323 a: 1,
5324 bar: 3,
5325 },
5326 }
5327 const rules = {
5328 foo: add(1),
5329 nested: {
5330 a: add(-1),
5331 bar: add(1),
5332 },
5333 }
5334 const result = evolve(rules, input)
5335 const curriedResult = evolve(rules)(input)
5336
5337 result.nested.a // $ExpectType number
5338 curriedResult.nested.a // $ExpectType number
5339 result.nested.bar // $ExpectType number
5340 result.foo // $ExpectType number
5341 })
5342 it('with array', () => {
5343 const rules = [String, String]
5344 const input = [100, 1400]
5345 const result = evolve(rules, input)
5346 const curriedResult = evolve(rules)(input)
5347 result // $ExpectType string[]
5348 curriedResult // $ExpectType string[]
5349 })
5350})
5351```
5352
5353</details>
5354
5355[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#evolve)
5356
5357### F
5358
5359```typescript
5360
5361F(): boolean
5362```
5363
5364<details>
5365
5366<summary>All Typescript definitions</summary>
5367
5368```typescript
5369F(): boolean;
5370```
5371
5372</details>
5373
5374<details>
5375
5376<summary><strong>R.F</strong> source</summary>
5377
5378```javascript
5379export function F() {
5380 return false
5381}
5382```
5383
5384</details>
5385
5386[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#F)
5387
5388### filter
5389
5390```typescript
5391
5392filter<T>(predicate: Predicate<T>): (input: T[]) => T[]
5393```
5394
5395It filters list or object `input` using a `predicate` function.
5396
5397<details>
5398
5399<summary>All Typescript definitions</summary>
5400
5401```typescript
5402filter<T>(predicate: Predicate<T>): (input: T[]) => T[];
5403filter<T>(predicate: Predicate<T>, input: T[]): T[];
5404filter<T, U>(predicate: ObjectPredicate<T>): (x: Dictionary<T>) => Dictionary<T>;
5405filter<T>(predicate: ObjectPredicate<T>, x: Dictionary<T>): Dictionary<T>;
5406```
5407
5408</details>
5409
5410<details>
5411
5412<summary><strong>R.filter</strong> source</summary>
5413
5414```javascript
5415import {_isArray} from './_internals/_isArray'
5416
5417export function filterObject(predicate, obj) {
5418 const willReturn = {}
5419
5420 for (const prop in obj) {
5421 if (predicate(obj[prop], prop, obj)) {
5422 willReturn[prop] = obj[prop]
5423 }
5424 }
5425
5426 return willReturn
5427}
5428
5429export function filterArray(predicate, list, indexed = false) {
5430 let index = 0
5431 const len = list.length
5432 const willReturn = []
5433
5434 while (index < len) {
5435 const predicateResult = indexed
5436 ? predicate(list[index], index)
5437 : predicate(list[index])
5438 if (predicateResult) {
5439 willReturn.push(list[index])
5440 }
5441
5442 index++
5443 }
5444
5445 return willReturn
5446}
5447
5448export function filter(predicate, iterable) {
5449 if (arguments.length === 1)
5450 return _iterable => filter(predicate, _iterable)
5451 if (!iterable) {
5452 throw new Error('Incorrect iterable input')
5453 }
5454
5455 if (_isArray(iterable)) return filterArray(predicate, iterable)
5456
5457 return filterObject(predicate, iterable)
5458}
5459```
5460
5461</details>
5462
5463<details>
5464
5465<summary><strong>Tests</strong></summary>
5466
5467```javascript
5468import {T} from './T'
5469import {filter} from './filter'
5470import {filter as filterRamda} from 'ramda'
5471
5472const sampleObject = {
5473 a: 1,
5474 b: 2,
5475 c: 3,
5476 d: 4,
5477}
5478
5479test('happy', () => {
5480 const isEven = n => n % 2 === 0
5481
5482 expect(filter(isEven, [1, 2, 3, 4])).toEqual([2, 4])
5483 expect(
5484 filter(isEven, {
5485 a: 1,
5486 b: 2,
5487 d: 3,
5488 })
5489 ).toEqual({b: 2})
5490})
5491
5492test('predicate when input is object', () => {
5493 const obj = {
5494 a: 1,
5495 b: 2,
5496 }
5497 const predicate = (val, prop, inputObject) => {
5498 expect(inputObject).toEqual(obj)
5499 expect(typeof prop).toEqual('string')
5500
5501 return val < 2
5502 }
5503 expect(filter(predicate, obj)).toEqual({a: 1})
5504})
5505
5506test('with object', () => {
5507 const isEven = n => n % 2 === 0
5508 const result = filter(isEven, sampleObject)
5509 const expectedResult = {
5510 b: 2,
5511 d: 4,
5512 }
5513
5514 expect(result).toEqual(expectedResult)
5515})
5516
5517test('bad inputs difference between Ramda and Rambda', () => {
5518 expect(() => filter(T, null)).toThrowWithMessage(
5519 Error,
5520 `Incorrect iterable input`
5521 )
5522 expect(() => filter(T)(undefined)).toThrowWithMessage(
5523 Error,
5524 `Incorrect iterable input`
5525 )
5526 expect(() => filterRamda(T, null)).toThrowWithMessage(
5527 TypeError,
5528 `Cannot read properties of null (reading 'filter')`
5529 )
5530 expect(() => filterRamda(T, undefined)).toThrowWithMessage(
5531 TypeError,
5532 `Cannot read properties of undefined (reading 'filter')`
5533 )
5534})
5535```
5536
5537</details>
5538
5539<details>
5540
5541<summary><strong>Typescript</strong> test</summary>
5542
5543```typescript
5544import {filter} from 'rambda'
5545
5546const list = [1, 2, 3]
5547const obj = {a: 1, b: 2}
5548
5549describe('R.filter with array', () => {
5550 it('happy', () => {
5551 const result = filter<number>(x => {
5552 x // $ExpectType number
5553 return x > 1
5554 }, list)
5555 result // $ExpectType number[]
5556 })
5557 it('curried', () => {
5558 const result = filter<number>(x => {
5559 x // $ExpectType number
5560 return x > 1
5561 })(list)
5562 result // $ExpectType number[]
5563 })
5564})
5565
5566describe('R.filter with objects', () => {
5567 it('happy', () => {
5568 const result = filter<number>((val, prop, origin) => {
5569 val // $ExpectType number
5570 prop // $ExpectType string
5571 origin // $ExpectType Dictionary<number>
5572
5573 return val > 1
5574 }, obj)
5575 result // $ExpectType Dictionary<number>
5576 })
5577 it('curried version requires second dummy type', () => {
5578 const result = filter<number, any>((val, prop, origin) => {
5579 val // $ExpectType number
5580 prop // $ExpectType string
5581 origin // $ExpectType Dictionary<number>
5582
5583 return val > 1
5584 })(obj)
5585 result // $ExpectType Dictionary<number>
5586 })
5587})
5588```
5589
5590</details>
5591
5592<details>
5593
5594<summary>Lodash is fastest. Rambda is 6.7% slower and Ramda is 72.03% slower</summary>
5595
5596```text
5597const R = require('../../dist/rambda.js')
5598
5599const arr = [1, 2, 3, 4]
5600const fn = x => x > 2
5601const filter = [
5602 {
5603 label: 'Rambda',
5604 fn: () => {
5605 R.filter(fn, arr)
5606 },
5607 },
5608 {
5609 label: 'Ramda',
5610 fn: () => {
5611 Ramda.filter(fn, arr)
5612 },
5613 },
5614 {
5615 label: 'Lodash',
5616 fn: () => {
5617 _.filter(arr, fn)
5618 },
5619 },
5620]
5621```
5622
5623</details>
5624
5625[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#filter)
5626
5627### find
5628
5629```typescript
5630
5631find<T>(predicate: (x: T) => boolean, list: T[]): T | undefined
5632```
5633
5634It returns the first element of `list` that satisfy the `predicate`.
5635
5636If there is no such element, it returns `undefined`.
5637
5638<details>
5639
5640<summary>All Typescript definitions</summary>
5641
5642```typescript
5643find<T>(predicate: (x: T) => boolean, list: T[]): T | undefined;
5644find<T>(predicate: (x: T) => boolean): (list: T[]) => T | undefined;
5645```
5646
5647</details>
5648
5649<details>
5650
5651<summary><strong>R.find</strong> source</summary>
5652
5653```javascript
5654export function find(predicate, list) {
5655 if (arguments.length === 1) return _list => find(predicate, _list)
5656
5657 let index = 0
5658 const len = list.length
5659
5660 while (index < len) {
5661 const x = list[index]
5662 if (predicate(x)) {
5663 return x
5664 }
5665
5666 index++
5667 }
5668}
5669```
5670
5671</details>
5672
5673<details>
5674
5675<summary><strong>Tests</strong></summary>
5676
5677```javascript
5678import {find} from './find'
5679import {propEq} from './propEq'
5680
5681const list = [{a: 1}, {a: 2}, {a: 3}]
5682
5683test('happy', () => {
5684 const fn = propEq('a', 2)
5685 expect(find(fn, list)).toEqual({a: 2})
5686})
5687
5688test('with curry', () => {
5689 const fn = propEq('a', 4)
5690 expect(find(fn)(list)).toBeUndefined()
5691})
5692
5693test('with empty list', () => {
5694 expect(find(() => true, [])).toBeUndefined()
5695})
5696```
5697
5698</details>
5699
5700<details>
5701
5702<summary><strong>Typescript</strong> test</summary>
5703
5704```typescript
5705import {find} from 'rambda'
5706
5707const list = [1, 2, 3]
5708
5709describe('R.find', () => {
5710 it('happy', () => {
5711 const predicate = (x: number) => x > 2
5712 const result = find(predicate, list)
5713 result // $ExpectType number | undefined
5714 })
5715 it('curried', () => {
5716 const predicate = (x: number) => x > 2
5717 const result = find(predicate)(list)
5718 result // $ExpectType number | undefined
5719 })
5720})
5721```
5722
5723</details>
5724
5725<details>
5726
5727<summary>Rambda is fastest. Ramda is 85.14% slower and Lodash is 42.65% slower</summary>
5728
5729```text
5730const R = require('../../dist/rambda.js')
5731
5732const fn = x => x > 2
5733const list = [1, 2, 3, 4]
5734
5735const find = [
5736 {
5737 label: 'Rambda',
5738 fn: () => {
5739 R.find(fn, list)
5740 },
5741 },
5742 {
5743 label: 'Ramda',
5744 fn: () => {
5745 Ramda.find(fn, list)
5746 },
5747 },
5748 {
5749 label: 'Lodash',
5750 fn: () => {
5751 _.find(list, fn)
5752 },
5753 },
5754]
5755```
5756
5757</details>
5758
5759[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#find)
5760
5761### findIndex
5762
5763```typescript
5764
5765findIndex<T>(predicate: (x: T) => boolean, list: T[]): number
5766```
5767
5768It returns the index of the first element of `list` satisfying the `predicate` function.
5769
5770If there is no such element, then `-1` is returned.
5771
5772<details>
5773
5774<summary>All Typescript definitions</summary>
5775
5776```typescript
5777findIndex<T>(predicate: (x: T) => boolean, list: T[]): number;
5778findIndex<T>(predicate: (x: T) => boolean): (list: T[]) => number;
5779```
5780
5781</details>
5782
5783<details>
5784
5785<summary><strong>R.findIndex</strong> source</summary>
5786
5787```javascript
5788export function findIndex(predicate, list) {
5789 if (arguments.length === 1) return _list => findIndex(predicate, _list)
5790
5791 const len = list.length
5792 let index = -1
5793
5794 while (++index < len) {
5795 if (predicate(list[index])) {
5796 return index
5797 }
5798 }
5799
5800 return -1
5801}
5802```
5803
5804</details>
5805
5806<details>
5807
5808<summary><strong>Tests</strong></summary>
5809
5810```javascript
5811import {findIndex} from './findIndex'
5812import {propEq} from './propEq'
5813
5814const list = [{a: 1}, {a: 2}, {a: 3}]
5815
5816test('happy', () => {
5817 expect(findIndex(propEq('a', 2), list)).toEqual(1)
5818
5819 expect(findIndex(propEq('a', 1))(list)).toEqual(0)
5820
5821 expect(findIndex(propEq('a', 4))(list)).toEqual(-1)
5822})
5823```
5824
5825</details>
5826
5827<details>
5828
5829<summary><strong>Typescript</strong> test</summary>
5830
5831```typescript
5832import {findIndex} from 'rambda'
5833
5834const list = [1, 2, 3]
5835
5836describe('R.findIndex', () => {
5837 it('happy', () => {
5838 const predicate = (x: number) => x > 2
5839 const result = findIndex(predicate, list)
5840 result // $ExpectType number
5841 })
5842 it('curried', () => {
5843 const predicate = (x: number) => x > 2
5844 const result = findIndex(predicate)(list)
5845 result // $ExpectType number
5846 })
5847})
5848```
5849
5850</details>
5851
5852<details>
5853
5854<summary>Rambda is fastest. Ramda is 86.48% slower and Lodash is 72.27% slower</summary>
5855
5856```text
5857const R = require('../../dist/rambda.js')
5858
5859const fn = x => x > 2
5860const list = [1, 2, 3, 4]
5861
5862const findIndex = [
5863 {
5864 label: 'Rambda',
5865 fn: () => {
5866 R.findIndex(fn, list)
5867 },
5868 },
5869 {
5870 label: 'Ramda',
5871 fn: () => {
5872 Ramda.findIndex(fn, list)
5873 },
5874 },
5875 {
5876 label: 'Lodash',
5877 fn: () => {
5878 _.findIndex(list, fn)
5879 },
5880 },
5881]
5882```
5883
5884</details>
5885
5886[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#findIndex)
5887
5888### findLast
5889
5890```typescript
5891
5892findLast<T>(fn: (x: T) => boolean, list: T[]): T | undefined
5893```
5894
5895It returns the last element of `list` satisfying the `predicate` function.
5896
5897If there is no such element, then `undefined` is returned.
5898
5899<details>
5900
5901<summary>All Typescript definitions</summary>
5902
5903```typescript
5904findLast<T>(fn: (x: T) => boolean, list: T[]): T | undefined;
5905findLast<T>(fn: (x: T) => boolean): (list: T[]) => T | undefined;
5906```
5907
5908</details>
5909
5910<details>
5911
5912<summary><strong>R.findLast</strong> source</summary>
5913
5914```javascript
5915export function findLast(predicate, list) {
5916 if (arguments.length === 1) return _list => findLast(predicate, _list)
5917
5918 let index = list.length
5919
5920 while (--index >= 0) {
5921 if (predicate(list[index])) {
5922 return list[index]
5923 }
5924 }
5925
5926 return undefined
5927}
5928```
5929
5930</details>
5931
5932<details>
5933
5934<summary><strong>Tests</strong></summary>
5935
5936```javascript
5937import {findLast} from './findLast'
5938
5939test('happy', () => {
5940 const result = findLast(x => x > 1, [1, 1, 1, 2, 3, 4, 1])
5941 expect(result).toEqual(4)
5942
5943 expect(findLast(x => x === 0, [0, 1, 1, 2, 3, 4, 1])).toEqual(0)
5944})
5945
5946test('with curry', () => {
5947 expect(findLast(x => x > 1)([1, 1, 1, 2, 3, 4, 1])).toEqual(4)
5948})
5949
5950const obj1 = {x: 100}
5951const obj2 = {x: 200}
5952const a = [11, 10, 9, 'cow', obj1, 8, 7, 100, 200, 300, obj2, 4, 3, 2, 1, 0]
5953const even = function (x) {
5954 return x % 2 === 0
5955}
5956const gt100 = function (x) {
5957 return x > 100
5958}
5959const isStr = function (x) {
5960 return typeof x === 'string'
5961}
5962const xGt100 = function (o) {
5963 return o && o.x > 100
5964}
5965
5966test('ramda 1', () => {
5967 expect(findLast(even, a)).toEqual(0)
5968 expect(findLast(gt100, a)).toEqual(300)
5969 expect(findLast(isStr, a)).toEqual('cow')
5970 expect(findLast(xGt100, a)).toEqual(obj2)
5971})
5972
5973test('ramda 2', () => {
5974 expect(findLast(even, ['zing'])).toEqual(undefined)
5975})
5976
5977test('ramda 3', () => {
5978 expect(findLast(even, [2, 3, 5])).toEqual(2)
5979})
5980
5981test('ramda 4', () => {
5982 expect(findLast(even, [])).toEqual(undefined)
5983})
5984```
5985
5986</details>
5987
5988<details>
5989
5990<summary><strong>Typescript</strong> test</summary>
5991
5992```typescript
5993import {findLast} from 'rambda'
5994
5995const list = [1, 2, 3]
5996
5997describe('R.findLast', () => {
5998 it('happy', () => {
5999 const predicate = (x: number) => x > 2
6000 const result = findLast(predicate, list)
6001 result // $ExpectType number | undefined
6002 })
6003 it('curried', () => {
6004 const predicate = (x: number) => x > 2
6005 const result = findLast(predicate)(list)
6006 result // $ExpectType number | undefined
6007 })
6008})
6009```
6010
6011</details>
6012
6013[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#findLast)
6014
6015### findLastIndex
6016
6017```typescript
6018
6019findLastIndex<T>(predicate: (x: T) => boolean, list: T[]): number
6020```
6021
6022It returns the index of the last element of `list` satisfying the `predicate` function.
6023
6024If there is no such element, then `-1` is returned.
6025
6026<details>
6027
6028<summary>All Typescript definitions</summary>
6029
6030```typescript
6031findLastIndex<T>(predicate: (x: T) => boolean, list: T[]): number;
6032findLastIndex<T>(predicate: (x: T) => boolean): (list: T[]) => number;
6033```
6034
6035</details>
6036
6037<details>
6038
6039<summary><strong>R.findLastIndex</strong> source</summary>
6040
6041```javascript
6042export function findLastIndex(fn, list) {
6043 if (arguments.length === 1) return _list => findLastIndex(fn, _list)
6044
6045 let index = list.length
6046
6047 while (--index >= 0) {
6048 if (fn(list[index])) {
6049 return index
6050 }
6051 }
6052
6053 return -1
6054}
6055```
6056
6057</details>
6058
6059<details>
6060
6061<summary><strong>Tests</strong></summary>
6062
6063```javascript
6064import {findLastIndex} from './findLastIndex'
6065
6066test('happy', () => {
6067 const result = findLastIndex(x => x > 1, [1, 1, 1, 2, 3, 4, 1])
6068
6069 expect(result).toEqual(5)
6070
6071 expect(findLastIndex(x => x === 0, [0, 1, 1, 2, 3, 4, 1])).toEqual(0)
6072})
6073
6074test('with curry', () => {
6075 expect(findLastIndex(x => x > 1)([1, 1, 1, 2, 3, 4, 1])).toEqual(5)
6076})
6077
6078const obj1 = {x: 100}
6079const obj2 = {x: 200}
6080const a = [11, 10, 9, 'cow', obj1, 8, 7, 100, 200, 300, obj2, 4, 3, 2, 1, 0]
6081const even = function (x) {
6082 return x % 2 === 0
6083}
6084const gt100 = function (x) {
6085 return x > 100
6086}
6087const isStr = function (x) {
6088 return typeof x === 'string'
6089}
6090const xGt100 = function (o) {
6091 return o && o.x > 100
6092}
6093
6094test('ramda 1', () => {
6095 expect(findLastIndex(even, a)).toEqual(15)
6096 expect(findLastIndex(gt100, a)).toEqual(9)
6097 expect(findLastIndex(isStr, a)).toEqual(3)
6098 expect(findLastIndex(xGt100, a)).toEqual(10)
6099})
6100
6101test('ramda 2', () => {
6102 expect(findLastIndex(even, ['zing'])).toEqual(-1)
6103})
6104
6105test('ramda 3', () => {
6106 expect(findLastIndex(even, [2, 3, 5])).toEqual(0)
6107})
6108
6109test('ramda 4', () => {
6110 expect(findLastIndex(even, [])).toEqual(-1)
6111})
6112```
6113
6114</details>
6115
6116<details>
6117
6118<summary><strong>Typescript</strong> test</summary>
6119
6120```typescript
6121import {findLastIndex} from 'rambda'
6122
6123const list = [1, 2, 3]
6124
6125describe('R.findLastIndex', () => {
6126 it('happy', () => {
6127 const predicate = (x: number) => x > 2
6128 const result = findLastIndex(predicate, list)
6129 result // $ExpectType number
6130 })
6131 it('curried', () => {
6132 const predicate = (x: number) => x > 2
6133 const result = findLastIndex(predicate)(list)
6134 result // $ExpectType number
6135 })
6136})
6137```
6138
6139</details>
6140
6141[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#findLastIndex)
6142
6143### flatten
6144
6145```typescript
6146
6147flatten<T>(list: any[]): T[]
6148```
6149
6150It deeply flattens an array.
6151
6152<details>
6153
6154<summary>All Typescript definitions</summary>
6155
6156```typescript
6157flatten<T>(list: any[]): T[];
6158```
6159
6160</details>
6161
6162<details>
6163
6164<summary><strong>R.flatten</strong> source</summary>
6165
6166```javascript
6167import {_isArray} from './_internals/_isArray'
6168
6169export function flatten(list, input) {
6170 const willReturn = input === undefined ? [] : input
6171
6172 for (let i = 0; i < list.length; i++) {
6173 if (_isArray(list[i])) {
6174 flatten(list[i], willReturn)
6175 } else {
6176 willReturn.push(list[i])
6177 }
6178 }
6179
6180 return willReturn
6181}
6182```
6183
6184</details>
6185
6186<details>
6187
6188<summary><strong>Tests</strong></summary>
6189
6190```javascript
6191import {flatten} from './flatten'
6192
6193test('happy', () => {
6194 expect(flatten([1, 2, 3, [[[[[4]]]]]])).toEqual([1, 2, 3, 4])
6195
6196 expect(flatten([1, [2, [[3]]], [4]])).toEqual([1, 2, 3, 4])
6197
6198 expect(flatten([1, [2, [[[3]]]], [4]])).toEqual([1, 2, 3, 4])
6199
6200 expect(flatten([1, 2, [3, 4], 5, [6, [7, 8, [9, [10, 11], 12]]]])).toEqual(
6201 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
6202 )
6203})
6204
6205test('readme example', () => {
6206 const result = flatten([1, 2, [3, 30, [300]], [4]])
6207 expect(result).toEqual([1, 2, 3, 30, 300, 4])
6208})
6209```
6210
6211</details>
6212
6213<details>
6214
6215<summary><strong>Typescript</strong> test</summary>
6216
6217```typescript
6218import {flatten} from 'rambda'
6219
6220describe('flatten', () => {
6221 it('happy', () => {
6222 const result = flatten<number>([1, 2, [3, [4]]])
6223 result // $ExpectType number[]
6224 })
6225})
6226```
6227
6228</details>
6229
6230<details>
6231
6232<summary>Rambda is fastest. Ramda is 95.26% slower and Lodash is 10.27% slower</summary>
6233
6234```text
6235const R = require('../../dist/rambda.js')
6236
6237const list = [1, [2, [3, 4, 6]]]
6238
6239const flatten = [
6240 {
6241 label: 'Rambda',
6242 fn: () => {
6243 R.flatten(list)
6244 },
6245 },
6246 {
6247 label: 'Ramda',
6248 fn: () => {
6249 Ramda.flatten(list)
6250 },
6251 },
6252 {
6253 label: 'Lodash',
6254 fn: () => {
6255 _.flatten(list)
6256 },
6257 },
6258]
6259```
6260
6261</details>
6262
6263[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#flatten)
6264
6265### flip
6266
6267It returns function which calls `fn` with exchanged first and second argument.
6268
6269[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#flip)
6270
6271### forEach
6272
6273```typescript
6274
6275forEach<T>(fn: Iterator<T, void>, list: T[]): T[]
6276```
6277
6278It applies `iterable` function over all members of `list` and returns `list`.
6279
6280<details>
6281
6282<summary>All Typescript definitions</summary>
6283
6284```typescript
6285forEach<T>(fn: Iterator<T, void>, list: T[]): T[];
6286forEach<T>(fn: Iterator<T, void>): (list: T[]) => T[];
6287forEach<T>(fn: ObjectIterator<T, void>, list: Dictionary<T>): Dictionary<T>;
6288forEach<T, U>(fn: ObjectIterator<T, void>): (list: Dictionary<T>) => Dictionary<T>;
6289```
6290
6291</details>
6292
6293<details>
6294
6295<summary><strong>R.forEach</strong> source</summary>
6296
6297```javascript
6298import {_isArray} from './_internals/_isArray'
6299import {_keys} from './_internals/_keys'
6300
6301export function forEach(fn, list) {
6302 if (arguments.length === 1) return _list => forEach(fn, _list)
6303
6304 if (list === undefined) {
6305 return
6306 }
6307
6308 if (_isArray(list)) {
6309 let index = 0
6310 const len = list.length
6311
6312 while (index < len) {
6313 fn(list[index])
6314 index++
6315 }
6316 } else {
6317 let index = 0
6318 const keys = _keys(list)
6319 const len = keys.length
6320
6321 while (index < len) {
6322 const key = keys[index]
6323 fn(list[key], key, list)
6324 index++
6325 }
6326 }
6327
6328 return list
6329}
6330```
6331
6332</details>
6333
6334<details>
6335
6336<summary><strong>Tests</strong></summary>
6337
6338```javascript
6339import {forEach} from './forEach'
6340import {type} from './type'
6341
6342test('happy', () => {
6343 const sideEffect = {}
6344 forEach(x => (sideEffect[`foo${x}`] = x + 10))([1, 2])
6345
6346 expect(sideEffect).toEqual({
6347 foo1: 11,
6348 foo2: 12,
6349 })
6350})
6351
6352test('iterate over object', () => {
6353 const obj = {
6354 a: 1,
6355 b: [1, 2],
6356 c: {d: 7},
6357 f: 'foo',
6358 }
6359 const result = {}
6360 const returned = forEach((val, prop, inputObj) => {
6361 expect(type(inputObj)).toBe('Object')
6362 result[prop] = `${prop}-${type(val)}`
6363 })(obj)
6364
6365 const expected = {
6366 a: 'a-Number',
6367 b: 'b-Array',
6368 c: 'c-Object',
6369 f: 'f-String',
6370 }
6371
6372 expect(result).toEqual(expected)
6373 expect(returned).toEqual(obj)
6374})
6375
6376test('with empty list', () => {
6377 const list = []
6378 const result = forEach(x => x * x)(list)
6379
6380 expect(result).toEqual(list)
6381})
6382
6383test('with wrong input', () => {
6384 const list = undefined
6385 const result = forEach(x => x * x)(list)
6386
6387 expect(result).toBeUndefined()
6388})
6389
6390test('returns the input', () => {
6391 const list = [1, 2, 3]
6392 const result = forEach(x => x * x)(list)
6393
6394 expect(result).toEqual(list)
6395})
6396```
6397
6398</details>
6399
6400<details>
6401
6402<summary><strong>Typescript</strong> test</summary>
6403
6404```typescript
6405import {forEach} from 'rambda'
6406
6407const list = [1, 2, 3]
6408const obj = {a: 1, b: 2}
6409
6410describe('R.forEach with arrays', () => {
6411 it('happy', () => {
6412 const result = forEach(a => {
6413 a // $ExpectType number
6414 }, list)
6415 result // $ExpectType number[]
6416 })
6417 it('curried require an explicit typing', () => {
6418 const result = forEach<number>(a => {
6419 a // $ExpectType number
6420 })(list)
6421 result // $ExpectType number[]
6422 })
6423})
6424
6425describe('R.forEach with objects', () => {
6426 it('happy', () => {
6427 const result = forEach((a, b, c) => {
6428 a // $ExpectType number
6429 b // $ExpectType string
6430 c // $ExpectType Dictionary<number>
6431 return `${a}`
6432 }, obj)
6433 result // $ExpectType Dictionary<number>
6434 })
6435 it('curried require an input typing and a dummy third typing', () => {
6436 // Required in order all typings to work
6437 const result = forEach<number, any>((a, b, c) => {
6438 a // $ExpectType number
6439 b // $ExpectType string
6440 c // $ExpectType Dictionary<number>
6441 })(obj)
6442 result // $ExpectType Dictionary<number>
6443 })
6444 it('iterator without property', () => {
6445 const result = forEach(a => {
6446 a // $ExpectType number
6447 }, obj)
6448 result // $ExpectType Dictionary<number>
6449 })
6450})
6451```
6452
6453</details>
6454
6455[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#forEach)
6456
6457### fromPairs
6458
6459It transforms a `listOfPairs` to an object.
6460
6461[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#fromPairs)
6462
6463### groupBy
6464
6465It splits `list` according to a provided `groupFn` function and returns an object.
6466
6467[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#groupBy)
6468
6469### groupWith
6470
6471It returns separated version of list or string `input`, where separation is done with equality `compareFn` function.
6472
6473[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#groupWith)
6474
6475### has
6476
6477```typescript
6478
6479has<T>(prop: string, obj: T): boolean
6480```
6481
6482It returns `true` if `obj` has property `prop`.
6483
6484<details>
6485
6486<summary>All Typescript definitions</summary>
6487
6488```typescript
6489has<T>(prop: string, obj: T): boolean;
6490has(prop: string): <T>(obj: T) => boolean;
6491```
6492
6493</details>
6494
6495<details>
6496
6497<summary><strong>R.has</strong> source</summary>
6498
6499```javascript
6500export function has(prop, obj) {
6501 if (arguments.length === 1) return _obj => has(prop, _obj)
6502
6503 if (!obj) return false
6504
6505 return obj.hasOwnProperty(prop)
6506}
6507```
6508
6509</details>
6510
6511<details>
6512
6513<summary><strong>Tests</strong></summary>
6514
6515```javascript
6516import {has} from './has'
6517
6518test('happy', () => {
6519 expect(has('a')({a: 1})).toBeTrue()
6520 expect(has('b', {a: 1})).toBeFalse()
6521})
6522
6523test('with non-object', () => {
6524 expect(has('a', undefined)).toEqual(false)
6525 expect(has('a', null)).toEqual(false)
6526 expect(has('a', true)).toEqual(false)
6527 expect(has('a', '')).toEqual(false)
6528 expect(has('a', /a/)).toEqual(false)
6529})
6530```
6531
6532</details>
6533
6534<details>
6535
6536<summary><strong>Typescript</strong> test</summary>
6537
6538```typescript
6539import {has} from 'rambda'
6540
6541describe('R.has', () => {
6542 it('happy', () => {
6543 const result = has('foo', {a: 1})
6544 const curriedResult = has('bar')({a: 1})
6545 result // $ExpectType boolean
6546 curriedResult // $ExpectType boolean
6547 })
6548})
6549```
6550
6551</details>
6552
6553[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#has)
6554
6555### hasPath
6556
6557```typescript
6558
6559hasPath<T>(
6560 path: string | string[],
6561 input: object
6562): boolean
6563```
6564
6565It will return true, if `input` object has truthy `path`(calculated with `R.path`).
6566
6567<details>
6568
6569<summary>All Typescript definitions</summary>
6570
6571```typescript
6572hasPath<T>(
6573 path: string | string[],
6574 input: object
6575): boolean;
6576hasPath<T>(
6577 path: string | string[]
6578): (input: object) => boolean;
6579```
6580
6581</details>
6582
6583<details>
6584
6585<summary><strong>R.hasPath</strong> source</summary>
6586
6587```javascript
6588import {path} from './path'
6589
6590export function hasPath(pathInput, obj) {
6591 if (arguments.length === 1) {
6592 return objHolder => hasPath(pathInput, objHolder)
6593 }
6594
6595 return path(pathInput, obj) !== undefined
6596}
6597```
6598
6599</details>
6600
6601<details>
6602
6603<summary><strong>Tests</strong></summary>
6604
6605```javascript
6606import {hasPath} from './hasPath'
6607
6608test('when true', () => {
6609 const path = 'a.b'
6610 const obj = {a: {b: []}}
6611
6612 const result = hasPath(path)(obj)
6613 const expectedResult = true
6614
6615 expect(result).toEqual(expectedResult)
6616})
6617
6618test('when false', () => {
6619 const path = 'a.b'
6620 const obj = {}
6621
6622 const result = hasPath(path, obj)
6623 const expectedResult = false
6624
6625 expect(result).toEqual(expectedResult)
6626})
6627```
6628
6629</details>
6630
6631<details>
6632
6633<summary><strong>Typescript</strong> test</summary>
6634
6635```typescript
6636import {hasPath} from 'rambda'
6637
6638describe('R.hasPath', () => {
6639 it('string path', () => {
6640 const obj = {a: {b: 1}}
6641 const result = hasPath('a.b', obj)
6642 const curriedResult = hasPath('a.c')(obj)
6643 result // $ExpectType boolean
6644 curriedResult // $ExpectType boolean
6645 })
6646 it('array path', () => {
6647 const obj = {a: {b: 1}}
6648 const result = hasPath(['a', 'b'], obj)
6649 const curriedResult = hasPath(['a', 'c'])(obj)
6650 result // $ExpectType boolean
6651 curriedResult // $ExpectType boolean
6652 })
6653})
6654```
6655
6656</details>
6657
6658[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#hasPath)
6659
6660### head
6661
6662```typescript
6663
6664head(input: string): string
6665```
6666
6667It returns the first element of list or string `input`.
6668
6669<details>
6670
6671<summary>All Typescript definitions</summary>
6672
6673```typescript
6674head(input: string): string;
6675head(emptyList: []): undefined;
6676head<T>(input: T[]): T | undefined;
6677```
6678
6679</details>
6680
6681<details>
6682
6683<summary><strong>R.head</strong> source</summary>
6684
6685```javascript
6686export function head(listOrString) {
6687 if (typeof listOrString === 'string') return listOrString[0] || ''
6688
6689 return listOrString[0]
6690}
6691```
6692
6693</details>
6694
6695<details>
6696
6697<summary><strong>Tests</strong></summary>
6698
6699```javascript
6700import {head} from './head'
6701
6702test('head', () => {
6703 expect(head(['fi', 'fo', 'fum'])).toEqual('fi')
6704 expect(head([])).toEqual(undefined)
6705 expect(head('foo')).toEqual('f')
6706 expect(head('')).toEqual('')
6707})
6708```
6709
6710</details>
6711
6712<details>
6713
6714<summary><strong>Typescript</strong> test</summary>
6715
6716```typescript
6717import {head} from 'rambda'
6718
6719describe('R.head', () => {
6720 it('string', () => {
6721 const result = head('foo')
6722 result // $ExpectType string
6723 })
6724
6725 it('array', () => {
6726 const result = head([1, 2, 3])
6727 result // $ExpectType number | undefined
6728 })
6729
6730 it('empty array - case 1', () => {
6731 const result = head([])
6732 result // $ExpectType undefined
6733 })
6734 it('empty array - case 2', () => {
6735 const list = ['foo', 'bar'].filter(x => x.startsWith('a'))
6736 const result = head(list)
6737 result // $ExpectType string | undefined
6738 })
6739})
6740```
6741
6742</details>
6743
6744[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#head)
6745
6746### identical
6747
6748It returns `true` if its arguments `a` and `b` are identical.
6749
6750Otherwise, it returns `false`.
6751
6752[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#identical)
6753
6754### identity
6755
6756```typescript
6757
6758identity<T>(input: T): T
6759```
6760
6761It just passes back the supplied `input` argument.
6762
6763<details>
6764
6765<summary>All Typescript definitions</summary>
6766
6767```typescript
6768identity<T>(input: T): T;
6769```
6770
6771</details>
6772
6773<details>
6774
6775<summary><strong>R.identity</strong> source</summary>
6776
6777```javascript
6778export function identity(x) {
6779 return x
6780}
6781```
6782
6783</details>
6784
6785<details>
6786
6787<summary><strong>Tests</strong></summary>
6788
6789```javascript
6790import {identity} from './identity'
6791
6792test('happy', () => {
6793 expect(identity(7)).toEqual(7)
6794 expect(identity(true)).toEqual(true)
6795 expect(identity({a: 1})).toEqual({a: 1})
6796})
6797```
6798
6799</details>
6800
6801<details>
6802
6803<summary><strong>Typescript</strong> test</summary>
6804
6805```typescript
6806import {identity} from 'rambda'
6807
6808describe('R.identity', () => {
6809 it('happy', () => {
6810 const result = identity(4)
6811 result // $ExpectType 4
6812 })
6813})
6814```
6815
6816</details>
6817
6818[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#identity)
6819
6820### ifElse
6821
6822```typescript
6823
6824ifElse<TArgs extends any[], TOnTrueResult, TOnFalseResult>(fn: (...args: TArgs) => boolean, onTrue: (...args: TArgs) => TOnTrueResult, onFalse: (...args: TArgs) => TOnFalseResult): (...args: TArgs) => TOnTrueResult | TOnFalseResult
6825```
6826
6827It expects `condition`, `onTrue` and `onFalse` functions as inputs and it returns a new function with example name of `fn`.
6828
6829When `fn`` is called with `input` argument, it will return either `onTrue(input)` or `onFalse(input)` depending on `condition(input)` evaluation.
6830
6831<details>
6832
6833<summary>All Typescript definitions</summary>
6834
6835```typescript
6836ifElse<TArgs extends any[], TOnTrueResult, TOnFalseResult>(fn: (...args: TArgs) => boolean, onTrue: (...args: TArgs) => TOnTrueResult, onFalse: (...args: TArgs) => TOnFalseResult): (...args: TArgs) => TOnTrueResult | TOnFalseResult;
6837```
6838
6839</details>
6840
6841<details>
6842
6843<summary><strong>R.ifElse</strong> source</summary>
6844
6845```javascript
6846import {curry} from './curry'
6847
6848function ifElseFn(condition, onTrue, onFalse) {
6849 return (...input) => {
6850 const conditionResult =
6851 typeof condition === 'boolean' ? condition : condition(...input)
6852
6853 if (conditionResult === true) {
6854 return onTrue(...input)
6855 }
6856
6857 return onFalse(...input)
6858 }
6859}
6860
6861export const ifElse = curry(ifElseFn)
6862```
6863
6864</details>
6865
6866<details>
6867
6868<summary><strong>Tests</strong></summary>
6869
6870```javascript
6871import {always} from './always'
6872import {has} from './has'
6873import {identity} from './identity'
6874import {ifElse} from './ifElse'
6875import {prop} from './prop'
6876
6877const condition = has('foo')
6878const v = function (a) {
6879 return typeof a === 'number'
6880}
6881const t = function (a) {
6882 return a + 1
6883}
6884const ifFn = x => prop('foo', x).length
6885const elseFn = () => false
6886
6887test('happy', () => {
6888 const fn = ifElse(condition, ifFn)(elseFn)
6889
6890 expect(fn({foo: 'bar'})).toEqual(3)
6891 expect(fn({fo: 'bar'})).toEqual(false)
6892})
6893
6894test('ramda spec', () => {
6895 const ifIsNumber = ifElse(v)
6896 expect(ifIsNumber(t, identity)(15)).toEqual(16)
6897 expect(ifIsNumber(t, identity)('hello')).toEqual('hello')
6898})
6899
6900test('pass all arguments', () => {
6901 const identity = function (a) {
6902 return a
6903 }
6904 const v = function () {
6905 return true
6906 }
6907 const onTrue = function (a, b) {
6908 expect(a).toEqual(123)
6909 expect(b).toEqual('abc')
6910 }
6911 ifElse(v, onTrue, identity)(123, 'abc')
6912})
6913
6914test('accept constant as condition', () => {
6915 const fn = ifElse(true)(always(true))(always(false))
6916
6917 expect(fn()).toEqual(true)
6918})
6919
6920test('accept constant as condition - case 2', () => {
6921 const fn = ifElse(false, always(true), always(false))
6922
6923 expect(fn()).toEqual(false)
6924})
6925
6926test('curry 1', () => {
6927 const fn = ifElse(condition, ifFn)(elseFn)
6928
6929 expect(fn({foo: 'bar'})).toEqual(3)
6930 expect(fn({fo: 'bar'})).toEqual(false)
6931})
6932
6933test('curry 2', () => {
6934 const fn = ifElse(condition)(ifFn)(elseFn)
6935
6936 expect(fn({foo: 'bar'})).toEqual(3)
6937 expect(fn({fo: 'bar'})).toEqual(false)
6938})
6939
6940test('simple arity of 1', () => {
6941 const condition = x => x > 5
6942 const onTrue = x => x + 1
6943 const onFalse = x => x + 10
6944 const result = ifElse(condition, onTrue, onFalse)(1)
6945 expect(result).toBe(11)
6946})
6947
6948test('simple arity of 2', () => {
6949 const condition = (x, y) => x + y > 5
6950 const onTrue = (x, y) => x + y + 1
6951 const onFalse = (x, y) => x + y + 10
6952 const result = ifElse(condition, onTrue, onFalse)(1, 10)
6953 expect(result).toBe(12)
6954})
6955```
6956
6957</details>
6958
6959<details>
6960
6961<summary><strong>Typescript</strong> test</summary>
6962
6963```typescript
6964import {ifElse} from 'rambda'
6965
6966describe('R.ifElse', () => {
6967 it('happy', () => {
6968 const condition = (x: number) => x > 5
6969 const onTrue = (x: number) => `foo${x}`
6970 const onFalse = (x: number) => `bar${x}`
6971 const fn = ifElse(condition, onTrue, onFalse)
6972 fn // $ExpectType (x: number) => string
6973 const result = fn(3)
6974 result // $ExpectType string
6975 })
6976 it('arity of 2', () => {
6977 const condition = (x: number, y: string) => x + y.length > 5
6978 const onTrue = (x: number, y: string) => `foo${x}-${y}`
6979 const onFalse = (x: number, y: string) => `bar${x}-${y}`
6980 const fn = ifElse(condition, onTrue, onFalse)
6981 fn // $ExpectType (x: number, y: string) => string
6982 const result = fn(3, 'hello')
6983 result // $ExpectType string
6984 })
6985})
6986```
6987
6988</details>
6989
6990<details>
6991
6992<summary>Rambda is faster than Ramda with 58.56%</summary>
6993
6994```text
6995const R = require('../../dist/rambda.js')
6996
6997const condition = R.has('foo')
6998const v = function (a) {
6999 return typeof a === 'number'
7000}
7001const t = function (a) {
7002 return a + 1
7003}
7004const ifFn = x => R.prop('foo', x).length
7005const elseFn = () => false
7006
7007const ifElse = [
7008 {
7009 label: 'Rambda',
7010 fn: () => {
7011 const fn = R.ifElse(condition, ifFn)(elseFn)
7012
7013 fn({foo: 'bar'})
7014 fn({fo: 'bar'})
7015
7016 const ifIsNumber = R.ifElse(v)
7017 ifIsNumber(t, R.identity)(15)
7018 ifIsNumber(t, R.identity)('hello')
7019 },
7020 },
7021 {
7022 label: 'Ramda',
7023 fn: () => {
7024 const fn = Ramda.ifElse(condition, ifFn)(elseFn)
7025
7026 fn({foo: 'bar'})
7027 fn({fo: 'bar'})
7028
7029 const ifIsNumber = Ramda.ifElse(v)
7030 ifIsNumber(t, R.identity)(15)
7031 ifIsNumber(t, R.identity)('hello')
7032 },
7033 },
7034]
7035```
7036
7037</details>
7038
7039[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#ifElse)
7040
7041### inc
7042
7043It increments a number.
7044
7045[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#inc)
7046
7047### includes
7048
7049```typescript
7050
7051includes(valueToFind: string, input: string[] | string): boolean
7052```
7053
7054If `input` is string, then this method work as native `String.includes`.
7055
7056If `input` is array, then `R.equals` is used to define if `valueToFind` belongs to the list.
7057
7058<details>
7059
7060<summary>All Typescript definitions</summary>
7061
7062```typescript
7063includes(valueToFind: string, input: string[] | string): boolean;
7064includes(valueToFind: string): (input: string[] | string) => boolean;
7065includes<T>(valueToFind: T, input: T[]): boolean;
7066includes<T>(valueToFind: T): (input: T[]) => boolean;
7067```
7068
7069</details>
7070
7071<details>
7072
7073<summary><strong>R.includes</strong> source</summary>
7074
7075```javascript
7076import {_isArray} from './_internals/_isArray'
7077import {_indexOf} from './equals'
7078
7079export function includes(valueToFind, iterable) {
7080 if (arguments.length === 1)
7081 return _iterable => includes(valueToFind, _iterable)
7082 if (typeof iterable === 'string') {
7083 return iterable.includes(valueToFind)
7084 }
7085 if (!iterable) {
7086 throw new TypeError(`Cannot read property \'indexOf\' of ${iterable}`)
7087 }
7088 if (!_isArray(iterable)) return false
7089
7090 return _indexOf(valueToFind, iterable) > -1
7091}
7092```
7093
7094</details>
7095
7096<details>
7097
7098<summary><strong>Tests</strong></summary>
7099
7100```javascript
7101import {includes} from './includes'
7102import {includes as includesRamda} from 'ramda'
7103
7104test('with string as iterable', () => {
7105 const str = 'foo bar'
7106
7107 expect(includes('bar')(str)).toBeTrue()
7108 expect(includesRamda('bar')(str)).toBeTrue()
7109 expect(includes('never', str)).toBeFalse()
7110 expect(includesRamda('never', str)).toBeFalse()
7111})
7112
7113test('with array as iterable', () => {
7114 const arr = [1, 2, 3]
7115
7116 expect(includes(2)(arr)).toBeTrue()
7117 expect(includesRamda(2)(arr)).toBeTrue()
7118
7119 expect(includes(4, arr)).toBeFalse()
7120 expect(includesRamda(4, arr)).toBeFalse()
7121})
7122
7123test('with list of objects as iterable', () => {
7124 const arr = [{a: 1}, {b: 2}, {c: 3}]
7125
7126 expect(includes({c: 3}, arr)).toBeTrue()
7127 expect(includesRamda({c: 3}, arr)).toBeTrue()
7128})
7129
7130test('with NaN', () => {
7131 const result = includes(NaN, [NaN])
7132 const ramdaResult = includesRamda(NaN, [NaN])
7133 expect(result).toBeTrue()
7134 expect(ramdaResult).toBeTrue()
7135})
7136
7137test('with wrong input that does not throw', () => {
7138 const result = includes(1, /foo/g)
7139 const ramdaResult = includesRamda(1, /foo/g)
7140 expect(result).toBeFalse()
7141 expect(ramdaResult).toBeFalse()
7142})
7143
7144test('throws on wrong input - match ramda behaviour', () => {
7145 expect(() => includes(2, null)).toThrowWithMessage(
7146 TypeError,
7147 "Cannot read property 'indexOf' of null"
7148 )
7149 expect(() => includesRamda(2, null)).toThrowWithMessage(
7150 TypeError,
7151 `Cannot read properties of null (reading 'indexOf')`
7152 )
7153 expect(() => includes(2, undefined)).toThrowWithMessage(
7154 TypeError,
7155 "Cannot read property 'indexOf' of undefined"
7156 )
7157 expect(() => includesRamda(2, undefined)).toThrowWithMessage(
7158 TypeError,
7159 `Cannot read properties of undefined (reading 'indexOf')`
7160 )
7161})
7162```
7163
7164</details>
7165
7166<details>
7167
7168<summary><strong>Typescript</strong> test</summary>
7169
7170```typescript
7171import {includes} from 'rambda'
7172
7173const list = [{a: {b: '1'}}, {a: {c: '2'}}, {a: {b: '3'}}]
7174
7175describe('R.includes', () => {
7176 it('happy', () => {
7177 const result = includes({a: {b: '1'}}, list)
7178 result // $ExpectType boolean
7179 })
7180 it('with string', () => {
7181 const result = includes('oo', 'foo')
7182 const curriedResult = includes('oo')('foo')
7183
7184 result // $ExpectType boolean
7185 curriedResult // $ExpectType boolean
7186 })
7187})
7188```
7189
7190</details>
7191
7192<details>
7193
7194<summary>Rambda is faster than Ramda with 84.63%</summary>
7195
7196```text
7197const R = require('../../dist/rambda.js')
7198
7199const {
7200 uniqListOfStrings,
7201 uniqListOfBooleans,
7202 uniqListOfObjects,
7203 uniqListOfLists,
7204 listOfVariousTypes,
7205 rangeOfNumbers,
7206} = require('./_utils.js')
7207
7208const limit = 100
7209const additionalModes = listOfVariousTypes.map(unknownType => [
7210 unknownType,
7211 uniqListOfLists(limit),
7212])
7213
7214const modes = [
7215 [99, rangeOfNumbers(limit)],
7216 [200, rangeOfNumbers(limit)],
7217 ...additionalModes,
7218 ['zeppelin', uniqListOfStrings(limit)],
7219 [null, uniqListOfBooleans(limit)],
7220 [{foo: true, bar: true}, uniqListOfObjects(limit)],
7221 [1, uniqListOfLists(limit)],
7222 [[1], uniqListOfLists(limit)],
7223]
7224
7225function applyBenchmark(fn, input) {
7226 return fn(input[0], input[1])
7227}
7228
7229const tests = [
7230 {
7231 label: 'Rambda',
7232 fn: R.includes,
7233 },
7234 {
7235 label: 'Ramda',
7236 fn: Ramda.includes,
7237 },
7238]
7239```
7240
7241</details>
7242
7243[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#includes)
7244
7245### indexBy
7246
7247It generates object with properties provided by `condition` and values provided by `list` array.
7248
7249If `condition` is a function, then all list members are passed through it.
7250
7251If `condition` is a string, then all list members are passed through `R.path(condition)`.
7252
7253[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#indexBy)
7254
7255### indexOf
7256
7257It returns the index of the first element of `list` equals to `valueToFind`.
7258
7259If there is no such element, it returns `-1`.
7260
7261[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#indexOf)
7262
7263### init
7264
7265```typescript
7266
7267init<T>(input: T[]): T[]
7268```
7269
7270It returns all but the last element of list or string `input`.
7271
7272<details>
7273
7274<summary>All Typescript definitions</summary>
7275
7276```typescript
7277init<T>(input: T[]): T[];
7278init(input: string): string;
7279```
7280
7281</details>
7282
7283<details>
7284
7285<summary><strong>R.init</strong> source</summary>
7286
7287```javascript
7288import baseSlice from './_internals/baseSlice'
7289
7290export function init(listOrString) {
7291 if (typeof listOrString === 'string') return listOrString.slice(0, -1)
7292
7293 return listOrString.length ? baseSlice(listOrString, 0, -1) : []
7294}
7295```
7296
7297</details>
7298
7299<details>
7300
7301<summary><strong>Tests</strong></summary>
7302
7303```javascript
7304import {init} from './init'
7305
7306test('with array', () => {
7307 expect(init([1, 2, 3])).toEqual([1, 2])
7308 expect(init([1, 2])).toEqual([1])
7309 expect(init([1])).toEqual([])
7310 expect(init([])).toEqual([])
7311 expect(init([])).toEqual([])
7312 expect(init([1])).toEqual([])
7313})
7314
7315test('with string', () => {
7316 expect(init('foo')).toEqual('fo')
7317 expect(init('f')).toEqual('')
7318 expect(init('')).toEqual('')
7319})
7320```
7321
7322</details>
7323
7324<details>
7325
7326<summary><strong>Typescript</strong> test</summary>
7327
7328```typescript
7329import {init} from 'rambda'
7330
7331describe('R.init', () => {
7332 it('with string', () => {
7333 const result = init('foo')
7334
7335 result // $ExpectType string
7336 })
7337 it('with list', () => {
7338 const result = init([1, 2, 3])
7339
7340 result // $ExpectType number[]
7341 })
7342})
7343```
7344
7345</details>
7346
7347<details>
7348
7349<summary>Rambda is fastest. Ramda is 92.24% slower and Lodash is 13.3% slower</summary>
7350
7351```text
7352const R = require('../../dist/rambda.js')
7353
7354const list = [1, 2, 3, 4]
7355
7356const init = [
7357 {
7358 label: 'Rambda',
7359 fn: () => {
7360 R.init(list)
7361 },
7362 },
7363 {
7364 label: 'Ramda',
7365 fn: () => {
7366 Ramda.init(list)
7367 },
7368 },
7369 {
7370 label: 'Lodash',
7371 fn: () => {
7372 _.initial(list)
7373 },
7374 },
7375]
7376```
7377
7378</details>
7379
7380[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#init)
7381
7382### intersection
7383
7384It loops throw `listA` and `listB` and returns the intersection of the two according to `R.equals`.
7385
7386[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#intersection)
7387
7388### intersperse
7389
7390It adds a `separator` between members of `list`.
7391
7392[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#intersperse)
7393
7394### is
7395
7396It returns `true` if `x` is instance of `targetPrototype`.
7397
7398[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#is)
7399
7400### isEmpty
7401
7402```typescript
7403
7404isEmpty<T>(x: T): boolean
7405```
7406
7407It returns `true` if `x` is `empty`.
7408
7409<details>
7410
7411<summary>All Typescript definitions</summary>
7412
7413```typescript
7414isEmpty<T>(x: T): boolean;
7415```
7416
7417</details>
7418
7419<details>
7420
7421<summary><strong>R.isEmpty</strong> source</summary>
7422
7423```javascript
7424import {type} from './type'
7425
7426export function isEmpty(input) {
7427 const inputType = type(input)
7428 if (['Undefined', 'NaN', 'Number', 'Null'].includes(inputType))
7429 return false
7430 if (!input) return true
7431
7432 if (inputType === 'Object') {
7433 return Object.keys(input).length === 0
7434 }
7435
7436 if (inputType === 'Array') {
7437 return input.length === 0
7438 }
7439
7440 return false
7441}
7442```
7443
7444</details>
7445
7446<details>
7447
7448<summary><strong>Tests</strong></summary>
7449
7450```javascript
7451import {isEmpty} from './isEmpty'
7452
7453test('happy', () => {
7454 expect(isEmpty(undefined)).toEqual(false)
7455 expect(isEmpty('')).toEqual(true)
7456 expect(isEmpty(null)).toEqual(false)
7457 expect(isEmpty(' ')).toEqual(false)
7458 expect(isEmpty(new RegExp(''))).toEqual(false)
7459 expect(isEmpty([])).toEqual(true)
7460 expect(isEmpty([[]])).toEqual(false)
7461 expect(isEmpty({})).toEqual(true)
7462 expect(isEmpty({x: 0})).toEqual(false)
7463 expect(isEmpty(0)).toEqual(false)
7464 expect(isEmpty(NaN)).toEqual(false)
7465 expect(isEmpty([''])).toEqual(false)
7466})
7467```
7468
7469</details>
7470
7471<details>
7472
7473<summary><strong>Typescript</strong> test</summary>
7474
7475```typescript
7476import {isEmpty} from 'rambda'
7477
7478describe('R.isEmpty', () => {
7479 it('happy', () => {
7480 const result = isEmpty('foo')
7481 result // $ExpectType boolean
7482 })
7483})
7484```
7485
7486</details>
7487
7488<details>
7489
7490<summary>Rambda is fastest. Ramda is 97.14% slower and Lodash is 54.99% slower</summary>
7491
7492```text
7493const R = require('../../dist/rambda.js')
7494
7495const isEmpty = [
7496 {
7497 label: 'Rambda',
7498 fn: () => {
7499 R.isEmpty(undefined)
7500 R.isEmpty('')
7501 R.isEmpty(null)
7502 R.isEmpty(' ')
7503 R.isEmpty(new RegExp(''))
7504 R.isEmpty([])
7505 R.isEmpty([[]])
7506 R.isEmpty({})
7507 R.isEmpty({x: 0})
7508 R.isEmpty(0)
7509 R.isEmpty(NaN)
7510 R.isEmpty([''])
7511 },
7512 },
7513 {
7514 label: 'Ramda',
7515 fn: () => {
7516 Ramda.isEmpty(undefined)
7517 Ramda.isEmpty('')
7518 Ramda.isEmpty(null)
7519 Ramda.isEmpty(' ')
7520 Ramda.isEmpty(new RegExp(''))
7521 Ramda.isEmpty([])
7522 Ramda.isEmpty([[]])
7523 Ramda.isEmpty({})
7524 Ramda.isEmpty({x: 0})
7525 Ramda.isEmpty(0)
7526 Ramda.isEmpty(NaN)
7527 Ramda.isEmpty([''])
7528 },
7529 },
7530 {
7531 label: 'Lodash',
7532 fn: () => {
7533 _.isEmpty(undefined)
7534 _.isEmpty('')
7535 _.isEmpty(null)
7536 _.isEmpty(' ')
7537 _.isEmpty(new RegExp(''))
7538 _.isEmpty([])
7539 _.isEmpty([[]])
7540 _.isEmpty({})
7541 _.isEmpty({x: 0})
7542 _.isEmpty(0)
7543 _.isEmpty(NaN)
7544 _.isEmpty([''])
7545 },
7546 },
7547]
7548```
7549
7550</details>
7551
7552[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#isEmpty)
7553
7554### isNil
7555
7556```typescript
7557
7558isNil(x: any): x is null | undefined
7559```
7560
7561It returns `true` if `x` is either `null` or `undefined`.
7562
7563<details>
7564
7565<summary>All Typescript definitions</summary>
7566
7567```typescript
7568isNil(x: any): x is null | undefined;
7569```
7570
7571</details>
7572
7573<details>
7574
7575<summary><strong>R.isNil</strong> source</summary>
7576
7577```javascript
7578export function isNil(x) {
7579 return x === undefined || x === null
7580}
7581```
7582
7583</details>
7584
7585<details>
7586
7587<summary><strong>Tests</strong></summary>
7588
7589```javascript
7590import {isNil} from './isNil'
7591
7592test('happy', () => {
7593 expect(isNil(null)).toBeTrue()
7594
7595 expect(isNil(undefined)).toBeTrue()
7596
7597 expect(isNil([])).toBeFalse()
7598})
7599```
7600
7601</details>
7602
7603[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#isNil)
7604
7605### join
7606
7607```typescript
7608
7609join<T>(glue: string, list: T[]): string
7610```
7611
7612It returns a string of all `list` instances joined with a `glue`.
7613
7614<details>
7615
7616<summary>All Typescript definitions</summary>
7617
7618```typescript
7619join<T>(glue: string, list: T[]): string;
7620join<T>(glue: string): (list: T[]) => string;
7621```
7622
7623</details>
7624
7625<details>
7626
7627<summary><strong>R.join</strong> source</summary>
7628
7629```javascript
7630export function join(glue, list) {
7631 if (arguments.length === 1) return _list => join(glue, _list)
7632
7633 return list.join(glue)
7634}
7635```
7636
7637</details>
7638
7639<details>
7640
7641<summary><strong>Tests</strong></summary>
7642
7643```javascript
7644import {join} from './join'
7645
7646test('curry', () => {
7647 expect(join('|')(['foo', 'bar', 'baz'])).toEqual('foo|bar|baz')
7648
7649 expect(join('|', [1, 2, 3])).toEqual('1|2|3')
7650
7651 const spacer = join(' ')
7652
7653 expect(spacer(['a', 2, 3.4])).toEqual('a 2 3.4')
7654})
7655```
7656
7657</details>
7658
7659<details>
7660
7661<summary><strong>Typescript</strong> test</summary>
7662
7663```typescript
7664import {join} from 'rambda'
7665
7666describe('R.join', () => {
7667 it('happy', () => {
7668 const result = join('|', [1, 2, 3])
7669 result // $ExpectType string
7670 })
7671})
7672```
7673
7674</details>
7675
7676[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#join)
7677
7678### keys
7679
7680```typescript
7681
7682keys<T extends object>(x: T): (keyof T)[]
7683```
7684
7685It applies `Object.keys` over `x` and returns its keys.
7686
7687<details>
7688
7689<summary>All Typescript definitions</summary>
7690
7691```typescript
7692keys<T extends object>(x: T): (keyof T)[];
7693keys<T>(x: T): string[];
7694```
7695
7696</details>
7697
7698<details>
7699
7700<summary><strong>R.keys</strong> source</summary>
7701
7702```javascript
7703export function keys(x) {
7704 return Object.keys(x)
7705}
7706```
7707
7708</details>
7709
7710<details>
7711
7712<summary><strong>Tests</strong></summary>
7713
7714```javascript
7715import {keys} from './keys'
7716
7717test('happy', () => {
7718 expect(keys({a: 1})).toEqual(['a'])
7719})
7720```
7721
7722</details>
7723
7724<details>
7725
7726<summary><strong>Typescript</strong> test</summary>
7727
7728```typescript
7729import {keys} from 'rambda'
7730
7731const obj = {a: 1, b: 2}
7732
7733describe('R.keys', () => {
7734 it('happy', () => {
7735 const result = keys(obj)
7736 result // $ExpectType ("b" | "a")[]
7737 })
7738})
7739```
7740
7741</details>
7742
7743[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#keys)
7744
7745### last
7746
7747```typescript
7748
7749last(str: string): string
7750```
7751
7752It returns the last element of `input`, as the `input` can be either a string or an array.
7753
7754<details>
7755
7756<summary>All Typescript definitions</summary>
7757
7758```typescript
7759last(str: string): string;
7760last(emptyList: []): undefined;
7761last<T extends any>(list: T[]): T | undefined;
7762```
7763
7764</details>
7765
7766<details>
7767
7768<summary><strong>R.last</strong> source</summary>
7769
7770```javascript
7771export function last(listOrString) {
7772 if (typeof listOrString === 'string') {
7773 return listOrString[listOrString.length - 1] || ''
7774 }
7775
7776 return listOrString[listOrString.length - 1]
7777}
7778```
7779
7780</details>
7781
7782<details>
7783
7784<summary><strong>Tests</strong></summary>
7785
7786```javascript
7787import {last} from './last'
7788
7789test('with list', () => {
7790 expect(last([1, 2, 3])).toBe(3)
7791 expect(last([])).toBeUndefined()
7792})
7793
7794test('with string', () => {
7795 expect(last('abc')).toEqual('c')
7796 expect(last('')).toEqual('')
7797})
7798```
7799
7800</details>
7801
7802<details>
7803
7804<summary><strong>Typescript</strong> test</summary>
7805
7806```typescript
7807import {last} from 'rambda'
7808
7809describe('R.last', () => {
7810 it('string', () => {
7811 const result = last('foo')
7812 result // $ExpectType string
7813 })
7814
7815 it('array', () => {
7816 const result = last([1, 2, 3])
7817 result // $ExpectType number | undefined
7818 })
7819
7820 it('empty array - case 1', () => {
7821 const result = last([])
7822 result // $ExpectType undefined
7823 })
7824 it('empty array - case 2', () => {
7825 const list = ['foo', 'bar'].filter(x => x.startsWith('a'))
7826 const result = last(list)
7827 result // $ExpectType string | undefined
7828 })
7829})
7830```
7831
7832</details>
7833
7834<details>
7835
7836<summary>Rambda is fastest. Ramda is 93.43% slower and Lodash is 5.28% slower</summary>
7837
7838```text
7839const R = require('../../dist/rambda.js')
7840
7841const list = [1, 2, 3, 4]
7842
7843const last = [
7844 {
7845 label: 'Rambda',
7846 fn: () => {
7847 R.last(list)
7848 },
7849 },
7850 {
7851 label: 'Ramda',
7852 fn: () => {
7853 Ramda.last(list)
7854 },
7855 },
7856 {
7857 label: 'Lodash',
7858 fn: () => {
7859 _.last(list)
7860 },
7861 },
7862]
7863```
7864
7865</details>
7866
7867[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#last)
7868
7869### lastIndexOf
7870
7871```typescript
7872
7873lastIndexOf<T>(target: T, list: T[]): number
7874```
7875
7876It returns the last index of `target` in `list` array.
7877
7878`R.equals` is used to determine equality between `target` and members of `list`.
7879
7880If there is no such index, then `-1` is returned.
7881
7882<details>
7883
7884<summary>All Typescript definitions</summary>
7885
7886```typescript
7887lastIndexOf<T>(target: T, list: T[]): number;
7888lastIndexOf<T>(target: T): (list: T[]) => number;
7889```
7890
7891</details>
7892
7893<details>
7894
7895<summary><strong>R.lastIndexOf</strong> source</summary>
7896
7897```javascript
7898import {_lastIndexOf} from './equals'
7899
7900export function lastIndexOf(valueToFind, list) {
7901 if (arguments.length === 1) {
7902 return _list => _lastIndexOf(valueToFind, _list)
7903 }
7904
7905 return _lastIndexOf(valueToFind, list)
7906}
7907```
7908
7909</details>
7910
7911<details>
7912
7913<summary><strong>Tests</strong></summary>
7914
7915```javascript
7916import {lastIndexOf} from './lastIndexOf'
7917import {lastIndexOf as lastIndexOfRamda} from 'ramda'
7918import {compareCombinations} from './_internals/testUtils'
7919import {possibleTargets, possibleIterables} from './indexOf.spec.js'
7920
7921test('with NaN', () => {
7922 expect(lastIndexOf(NaN, [NaN])).toEqual(0)
7923})
7924
7925test('will throw with bad input', () => {
7926 expect(lastIndexOfRamda([], true)).toEqual(-1)
7927 expect(() => indexOf([], true)).toThrow()
7928})
7929
7930test('without list of objects - no R.equals', () => {
7931 expect(lastIndexOf(3, [1, 2, 3, 4])).toEqual(2)
7932 expect(lastIndexOf(10)([1, 2, 3, 4])).toEqual(-1)
7933})
7934
7935test('list of objects uses R.equals', () => {
7936 const listOfObjects = [{a: 1}, {b: 2}, {c: 3}]
7937 expect(lastIndexOf({c: 4}, listOfObjects)).toBe(-1)
7938 expect(lastIndexOf({c: 3}, listOfObjects)).toBe(2)
7939})
7940
7941test('list of arrays uses R.equals', () => {
7942 const listOfLists = [[1], [2, 3], [2, 3, 4], [2, 3], [1], []]
7943 expect(lastIndexOf([], listOfLists)).toBe(5)
7944 expect(lastIndexOf([1], listOfLists)).toBe(4)
7945 expect(lastIndexOf([2, 3, 4], listOfLists)).toBe(2)
7946 expect(lastIndexOf([2, 3, 5], listOfLists)).toBe(-1)
7947})
7948
7949test('with string as iterable', () => {
7950 expect(() => lastIndexOf('a', 'abc')).toThrowWithMessage(
7951 Error,
7952 `Cannot read property 'indexOf' of abc`
7953 )
7954 expect(lastIndexOfRamda('a', 'abc')).toBe(0)
7955})
7956
7957describe('brute force', () => {
7958 compareCombinations({
7959 fn: lastIndexOf,
7960 fnRamda: lastIndexOfRamda,
7961 firstInput: possibleTargets,
7962 secondInput: possibleIterables,
7963 callback: errorsCounters => {
7964 expect(errorsCounters).toMatchInlineSnapshot(`
7965 Object {
7966 "ERRORS_MESSAGE_MISMATCH": 0,
7967 "ERRORS_TYPE_MISMATCH": 34,
7968 "RESULTS_MISMATCH": 0,
7969 "SHOULD_NOT_THROW": 51,
7970 "SHOULD_THROW": 0,
7971 "TOTAL_TESTS": 170,
7972 }
7973 `)
7974 },
7975 })
7976})
7977```
7978
7979</details>
7980
7981<details>
7982
7983<summary><strong>Typescript</strong> test</summary>
7984
7985```typescript
7986import {lastIndexOf} from 'rambda'
7987
7988const list = [1, 2, 3]
7989
7990describe('R.lastIndexOf', () => {
7991 it('happy', () => {
7992 const result = lastIndexOf(2, list)
7993 result // $ExpectType number
7994 })
7995 it('curried', () => {
7996 const result = lastIndexOf(2)(list)
7997 result // $ExpectType number
7998 })
7999})
8000```
8001
8002</details>
8003
8004<details>
8005
8006<summary>Rambda is faster than Ramda with 85.19%</summary>
8007
8008```text
8009const R = require('../../dist/rambda.js')
8010
8011const isEven = n => n % 2 === 0
8012const arr = [1, 3, 5, 7, 9, 11]
8013
8014const lastIndexOf = [
8015 {
8016 label: 'Rambda',
8017 fn: () => {
8018 R.lastIndexOf(1, [1, 2, 3, 1, 2])
8019 R.lastIndexOf(1)([1, 2, 3, 1, 2])
8020 },
8021 },
8022 {
8023 label: 'Ramda',
8024 fn: () => {
8025 Ramda.lastIndexOf(1, [1, 2, 3, 1, 2])
8026 Ramda.lastIndexOf(1)([1, 2, 3, 1, 2])
8027 },
8028 },
8029]
8030```
8031
8032</details>
8033
8034[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#lastIndexOf)
8035
8036### length
8037
8038```typescript
8039
8040length<T>(input: T[]): number
8041```
8042
8043It returns the `length` property of list or string `input`.
8044
8045<details>
8046
8047<summary>All Typescript definitions</summary>
8048
8049```typescript
8050length<T>(input: T[]): number;
8051```
8052
8053</details>
8054
8055<details>
8056
8057<summary><strong>R.length</strong> source</summary>
8058
8059```javascript
8060import {_isArray} from './_internals/_isArray'
8061
8062export function length(x) {
8063 if (_isArray(x)) return x.length
8064 if (typeof x === 'string') return x.length
8065
8066 return NaN
8067}
8068```
8069
8070</details>
8071
8072<details>
8073
8074<summary><strong>Tests</strong></summary>
8075
8076```javascript
8077import {length} from './length'
8078import {length as lengthRamda} from 'ramda'
8079
8080test('happy', () => {
8081 expect(length('foo')).toEqual(3)
8082 expect(length([1, 2, 3])).toEqual(3)
8083 expect(length([])).toEqual(0)
8084})
8085
8086test('with empty string', () => {
8087 expect(length('')).toEqual(0)
8088})
8089
8090test('with bad input returns NaN', () => {
8091 expect(length(0)).toBeNaN()
8092 expect(length({})).toBeNaN()
8093 expect(length(null)).toBeNaN()
8094 expect(length(undefined)).toBeNaN()
8095})
8096
8097test('with length as property', () => {
8098 const input1 = {length: '123'}
8099 const input2 = {length: null}
8100 const input3 = {length: ''}
8101
8102 expect(length(input1)).toBeNaN()
8103 expect(lengthRamda(input1)).toBeNaN()
8104 expect(length(input2)).toBeNaN()
8105 expect(lengthRamda(input2)).toBeNaN()
8106 expect(length(input3)).toBeNaN()
8107 expect(lengthRamda(input3)).toBeNaN()
8108})
8109```
8110
8111</details>
8112
8113[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#length)
8114
8115### lens
8116
8117```typescript
8118
8119lens<T, U, V>(getter: (s: T) => U, setter: (a: U, s: T) => V): Lens
8120```
8121
8122It returns a `lens` for the given `getter` and `setter` functions.
8123
8124The `getter` **gets** the value of the focus; the `setter` **sets** the value of the focus.
8125
8126The setter should not mutate the data structure.
8127
8128<details>
8129
8130<summary>All Typescript definitions</summary>
8131
8132```typescript
8133lens<T, U, V>(getter: (s: T) => U, setter: (a: U, s: T) => V): Lens;
8134```
8135
8136</details>
8137
8138<details>
8139
8140<summary><strong>R.lens</strong> source</summary>
8141
8142```javascript
8143export function lens(getter, setter) {
8144 return function (functor) {
8145 return function (target) {
8146 return functor(getter(target)).map(focus => setter(focus, target))
8147 }
8148 }
8149}
8150```
8151
8152</details>
8153
8154<details>
8155
8156<summary><strong>Typescript</strong> test</summary>
8157
8158```typescript
8159import {lens, assoc} from 'rambda'
8160
8161interface Input {
8162 foo: string,
8163}
8164
8165describe('R.lens', () => {
8166 it('happy', () => {
8167 const fn = lens<Input, string, string>((x: Input) => {
8168 x.foo // $ExpectType string
8169 return x.foo
8170 }, assoc('name'))
8171 fn // $ExpectType Lens
8172 })
8173})
8174```
8175
8176</details>
8177
8178[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#lens)
8179
8180### lensIndex
8181
8182```typescript
8183
8184lensIndex(index: number): Lens
8185```
8186
8187It returns a lens that focuses on specified `index`.
8188
8189<details>
8190
8191<summary>All Typescript definitions</summary>
8192
8193```typescript
8194lensIndex(index: number): Lens;
8195```
8196
8197</details>
8198
8199<details>
8200
8201<summary><strong>R.lensIndex</strong> source</summary>
8202
8203```javascript
8204import {lens} from './lens'
8205import {nth} from './nth'
8206import {update} from './update'
8207
8208export function lensIndex(index) {
8209 return lens(nth(index), update(index))
8210}
8211```
8212
8213</details>
8214
8215<details>
8216
8217<summary><strong>Tests</strong></summary>
8218
8219```javascript
8220import {compose} from './compose'
8221import {keys} from './keys'
8222import {lensIndex} from './lensIndex'
8223import {over} from './over'
8224import {set} from './set'
8225import {view} from './view'
8226
8227const testList = [{a: 1}, {b: 2}, {c: 3}]
8228
8229test('focuses list element at the specified index', () => {
8230 expect(view(lensIndex(0), testList)).toEqual({a: 1})
8231})
8232
8233test('returns undefined if the specified index does not exist', () => {
8234 expect(view(lensIndex(10), testList)).toEqual(undefined)
8235})
8236
8237test('sets the list value at the specified index', () => {
8238 expect(set(lensIndex(0), 0, testList)).toEqual([0, {b: 2}, {c: 3}])
8239})
8240
8241test('applies function to the value at the specified list index', () => {
8242 expect(over(lensIndex(2), keys, testList)).toEqual([{a: 1}, {b: 2}, ['c']])
8243})
8244
8245test('can be composed', () => {
8246 const nestedList = [0, [10, 11, 12], 1, 2]
8247 const composedLens = compose(lensIndex(1), lensIndex(0))
8248
8249 expect(view(composedLens, nestedList)).toEqual(10)
8250})
8251
8252test('set s (get s) === s', () => {
8253 expect(set(lensIndex(0), view(lensIndex(0), testList), testList)).toEqual(
8254 testList
8255 )
8256})
8257
8258test('get (set s v) === v', () => {
8259 expect(view(lensIndex(0), set(lensIndex(0), 0, testList))).toEqual(0)
8260})
8261
8262test('get (set(set s v1) v2) === v2', () => {
8263 expect(
8264 view(
8265 lensIndex(0),
8266 set(lensIndex(0), 11, set(lensIndex(0), 10, testList))
8267 )
8268 ).toEqual(11)
8269})
8270```
8271
8272</details>
8273
8274<details>
8275
8276<summary><strong>Typescript</strong> test</summary>
8277
8278```typescript
8279import {view, lensIndex} from 'rambda'
8280
8281interface Input {
8282 a: number,
8283}
8284const testList: Input[] = [{a: 1}, {a: 2}, {a: 3}]
8285
8286describe('R.lensIndex', () => {
8287 it('happy', () => {
8288 const result = view<Input[], Input>(lensIndex(0), testList)
8289 result // $ExpectType Input
8290 result.a // $ExpectType number
8291 })
8292})
8293```
8294
8295</details>
8296
8297[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#lensIndex)
8298
8299### lensPath
8300
8301```typescript
8302
8303lensPath(path: RamdaPath): Lens
8304```
8305
8306It returns a lens that focuses on specified `path`.
8307
8308<details>
8309
8310<summary>All Typescript definitions</summary>
8311
8312```typescript
8313lensPath(path: RamdaPath): Lens;
8314lensPath(path: string): Lens;
8315```
8316
8317</details>
8318
8319<details>
8320
8321<summary><strong>R.lensPath</strong> source</summary>
8322
8323```javascript
8324import {assocPath} from './assocPath'
8325import {lens} from './lens'
8326import {path} from './path'
8327
8328export function lensPath(key) {
8329 return lens(path(key), assocPath(key))
8330}
8331```
8332
8333</details>
8334
8335<details>
8336
8337<summary><strong>Tests</strong></summary>
8338
8339```javascript
8340import {compose} from './compose'
8341import {identity} from './identity'
8342import {inc} from './inc'
8343import {lensPath} from './lensPath'
8344import {lensProp} from './lensProp'
8345import {over} from './over'
8346import {set} from './set'
8347import {view} from './view'
8348
8349const testObj = {
8350 a: [{b: 1}, {b: 2}],
8351 d: 3,
8352}
8353
8354test('view', () => {
8355 expect(view(lensPath('d'), testObj)).toEqual(3)
8356 expect(view(lensPath('a.0.b'), testObj)).toEqual(1)
8357 // this is different to ramda, as ramda will return a clone of the input object
8358 expect(view(lensPath(''), testObj)).toEqual(undefined)
8359})
8360
8361test('set', () => {
8362 expect(set(lensProp('d'), 0, testObj)).toEqual({
8363 a: [{b: 1}, {b: 2}],
8364 d: 0,
8365 })
8366 expect(set(lensPath('a.0.b'), 0, testObj)).toEqual({
8367 a: [{b: 0}, {b: 2}],
8368 d: 3,
8369 })
8370 expect(set(lensPath('a.0.X'), 0, testObj)).toEqual({
8371 a: [
8372 {
8373 b: 1,
8374 X: 0,
8375 },
8376 {b: 2},
8377 ],
8378 d: 3,
8379 })
8380 expect(set(lensPath([]), 0, testObj)).toEqual(0)
8381})
8382
8383test('over', () => {
8384 expect(over(lensPath('d'), inc, testObj)).toEqual({
8385 a: [{b: 1}, {b: 2}],
8386 d: 4,
8387 })
8388 expect(over(lensPath('a.1.b'), inc, testObj)).toEqual({
8389 a: [{b: 1}, {b: 3}],
8390 d: 3,
8391 })
8392 expect(over(lensProp('X'), identity, testObj)).toEqual({
8393 a: [{b: 1}, {b: 2}],
8394 d: 3,
8395 X: undefined,
8396 })
8397 expect(over(lensPath('a.0.X'), identity, testObj)).toEqual({
8398 a: [
8399 {
8400 b: 1,
8401 X: undefined,
8402 },
8403 {b: 2},
8404 ],
8405 d: 3,
8406 })
8407})
8408
8409test('compose', () => {
8410 const composedLens = compose(lensPath('a'), lensPath('1.b'))
8411 expect(view(composedLens, testObj)).toEqual(2)
8412})
8413
8414test('set s (get s) === s', () => {
8415 expect(
8416 set(lensPath(['d']), view(lensPath(['d']), testObj), testObj)
8417 ).toEqual(testObj)
8418 expect(
8419 set(
8420 lensPath(['a', 0, 'b']),
8421 view(lensPath(['a', 0, 'b']), testObj),
8422 testObj
8423 )
8424 ).toEqual(testObj)
8425})
8426
8427test('get (set s v) === v', () => {
8428 expect(view(lensPath(['d']), set(lensPath(['d']), 0, testObj))).toEqual(0)
8429 expect(
8430 view(lensPath(['a', 0, 'b']), set(lensPath(['a', 0, 'b']), 0, testObj))
8431 ).toEqual(0)
8432})
8433
8434test('get (set(set s v1) v2) === v2', () => {
8435 const p = ['d']
8436 const q = ['a', 0, 'b']
8437 expect(
8438 view(lensPath(p), set(lensPath(p), 11, set(lensPath(p), 10, testObj)))
8439 ).toEqual(11)
8440 expect(
8441 view(lensPath(q), set(lensPath(q), 11, set(lensPath(q), 10, testObj)))
8442 ).toEqual(11)
8443})
8444```
8445
8446</details>
8447
8448<details>
8449
8450<summary><strong>Typescript</strong> test</summary>
8451
8452```typescript
8453import {lensPath, view} from 'rambda'
8454
8455interface Input {
8456 foo: number[],
8457 bar: {
8458 a: string,
8459 b: string,
8460 },
8461}
8462
8463const testObject: Input = {
8464 foo: [1, 2],
8465 bar: {
8466 a: 'x',
8467 b: 'y',
8468 },
8469}
8470
8471const path = lensPath(['bar', 'a'])
8472const pathAsString = lensPath('bar.a')
8473
8474describe('R.lensPath', () => {
8475 it('happy', () => {
8476 const result = view<Input, string>(path, testObject)
8477 result // $ExpectType string
8478 })
8479 it('using string as path input', () => {
8480 const result = view<Input, string>(pathAsString, testObject)
8481 result // $ExpectType string
8482 })
8483})
8484```
8485
8486</details>
8487
8488[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#lensPath)
8489
8490### lensProp
8491
8492```typescript
8493
8494lensProp(prop: string): {
8495 <T, U>(obj: T): U
8496```
8497
8498It returns a lens that focuses on specified property `prop`.
8499
8500<details>
8501
8502<summary>All Typescript definitions</summary>
8503
8504```typescript
8505lensProp(prop: string): {
8506 <T, U>(obj: T): U;
8507 set<T, U, V>(val: T, obj: U): V;
8508};
8509```
8510
8511</details>
8512
8513<details>
8514
8515<summary><strong>R.lensProp</strong> source</summary>
8516
8517```javascript
8518import {assoc} from './assoc'
8519import {lens} from './lens'
8520import {prop} from './prop'
8521
8522export function lensProp(key) {
8523 return lens(prop(key), assoc(key))
8524}
8525```
8526
8527</details>
8528
8529<details>
8530
8531<summary><strong>Tests</strong></summary>
8532
8533```javascript
8534import {compose} from './compose'
8535import {identity} from './identity'
8536import {inc} from './inc'
8537import {lensProp} from './lensProp'
8538import {over} from './over'
8539import {set} from './set'
8540import {view} from './view'
8541
8542const testObj = {
8543 a: 1,
8544 b: 2,
8545 c: 3,
8546}
8547
8548test('focuses object the specified object property', () => {
8549 expect(view(lensProp('a'), testObj)).toEqual(1)
8550})
8551
8552test('returns undefined if the specified property does not exist', () => {
8553 expect(view(lensProp('X'), testObj)).toEqual(undefined)
8554})
8555
8556test('sets the value of the object property specified', () => {
8557 expect(set(lensProp('a'), 0, testObj)).toEqual({
8558 a: 0,
8559 b: 2,
8560 c: 3,
8561 })
8562})
8563
8564test("adds the property to the object if it doesn't exist", () => {
8565 expect(set(lensProp('d'), 4, testObj)).toEqual({
8566 a: 1,
8567 b: 2,
8568 c: 3,
8569 d: 4,
8570 })
8571})
8572
8573test('applies function to the value of the specified object property', () => {
8574 expect(over(lensProp('a'), inc, testObj)).toEqual({
8575 a: 2,
8576 b: 2,
8577 c: 3,
8578 })
8579})
8580
8581test("applies function to undefined and adds the property if it doesn't exist", () => {
8582 expect(over(lensProp('X'), identity, testObj)).toEqual({
8583 a: 1,
8584 b: 2,
8585 c: 3,
8586 X: undefined,
8587 })
8588})
8589
8590test('can be composed', () => {
8591 const nestedObj = {
8592 a: {b: 1},
8593 c: 2,
8594 }
8595 const composedLens = compose(lensProp('a'), lensProp('b'))
8596
8597 expect(view(composedLens, nestedObj)).toEqual(1)
8598})
8599
8600test('set s (get s) === s', () => {
8601 expect(set(lensProp('a'), view(lensProp('a'), testObj), testObj)).toEqual(
8602 testObj
8603 )
8604})
8605
8606test('get (set s v) === v', () => {
8607 expect(view(lensProp('a'), set(lensProp('a'), 0, testObj))).toEqual(0)
8608})
8609
8610test('get (set(set s v1) v2) === v2', () => {
8611 expect(
8612 view(
8613 lensProp('a'),
8614 set(lensProp('a'), 11, set(lensProp('a'), 10, testObj))
8615 )
8616 ).toEqual(11)
8617})
8618```
8619
8620</details>
8621
8622<details>
8623
8624<summary><strong>Typescript</strong> test</summary>
8625
8626```typescript
8627import {lensProp, view} from 'rambda'
8628
8629interface Input {
8630 foo: string,
8631}
8632
8633const testObject: Input = {
8634 foo: 'Led Zeppelin',
8635}
8636
8637const lens = lensProp('foo')
8638
8639describe('R.lensProp', () => {
8640 it('happy', () => {
8641 const result = view<Input, string>(lens, testObject)
8642 result // $ExpectType string
8643 })
8644})
8645```
8646
8647</details>
8648
8649[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#lensProp)
8650
8651### map
8652
8653```typescript
8654
8655map<T, U>(fn: ObjectIterator<T, U>, iterable: Dictionary<T>): Dictionary<U>
8656```
8657
8658It returns the result of looping through `iterable` with `fn`.
8659
8660It works with both array and object.
8661
8662<details>
8663
8664<summary>All Typescript definitions</summary>
8665
8666```typescript
8667map<T, U>(fn: ObjectIterator<T, U>, iterable: Dictionary<T>): Dictionary<U>;
8668map<T, U>(fn: Iterator<T, U>, iterable: T[]): U[];
8669map<T, U>(fn: Iterator<T, U>): (iterable: T[]) => U[];
8670map<T, U, S>(fn: ObjectIterator<T, U>): (iterable: Dictionary<T>) => Dictionary<U>;
8671map<T>(fn: Iterator<T, T>): (iterable: T[]) => T[];
8672map<T>(fn: Iterator<T, T>, iterable: T[]): T[];
8673```
8674
8675</details>
8676
8677<details>
8678
8679<summary><strong>R.map</strong> source</summary>
8680
8681```javascript
8682import {_isArray} from './_internals/_isArray'
8683import {_keys} from './_internals/_keys'
8684
8685export function mapArray(fn, list, isIndexed = false) {
8686 let index = 0
8687 const willReturn = Array(list.length)
8688
8689 while (index < list.length) {
8690 willReturn[index] = isIndexed ? fn(list[index], index) : fn(list[index])
8691
8692 index++
8693 }
8694
8695 return willReturn
8696}
8697
8698export function mapObject(fn, obj) {
8699 let index = 0
8700 const keys = _keys(obj)
8701 const len = keys.length
8702 const willReturn = {}
8703
8704 while (index < len) {
8705 const key = keys[index]
8706 willReturn[key] = fn(obj[key], key, obj)
8707 index++
8708 }
8709
8710 return willReturn
8711}
8712
8713export const mapObjIndexed = mapObject
8714
8715export function map(fn, iterable) {
8716 if (arguments.length === 1) return _iterable => map(fn, _iterable)
8717 if (!iterable) {
8718 throw new Error('Incorrect iterable input')
8719 }
8720
8721 if (_isArray(iterable)) return mapArray(fn, iterable)
8722
8723 return mapObject(fn, iterable)
8724}
8725```
8726
8727</details>
8728
8729<details>
8730
8731<summary><strong>Tests</strong></summary>
8732
8733```javascript
8734import {map} from './map'
8735import {map as mapRamda} from 'ramda'
8736
8737const double = x => x * 2
8738
8739describe(`with array`, () => {
8740 test('happy', () => {
8741 expect(map(double, [1, 2, 3])).toEqual([2, 4, 6])
8742 })
8743
8744 test('curried', () => {
8745 expect(map(double)([1, 2, 3])).toEqual([2, 4, 6])
8746 })
8747})
8748
8749describe(`with object`, () => {
8750 const obj = {
8751 a: 1,
8752 b: 2,
8753 }
8754
8755 test('happy', () => {
8756 expect(map(double, obj)).toEqual({
8757 a: 2,
8758 b: 4,
8759 })
8760 })
8761 test('property as second and input object as third argument', () => {
8762 const obj = {
8763 a: 1,
8764 b: 2,
8765 }
8766 const iterator = (val, prop, inputObject) => {
8767 expect(prop).toBeString()
8768 expect(inputObject).toEqual(obj)
8769
8770 return val * 2
8771 }
8772
8773 expect(map(iterator)(obj)).toEqual({
8774 a: 2,
8775 b: 4,
8776 })
8777 })
8778})
8779
8780test('bad inputs difference between Ramda and Rambda', () => {
8781 expect(() => map(double, null)).toThrowWithMessage(
8782 Error,
8783 `Incorrect iterable input`
8784 )
8785 expect(() => map(double)(undefined)).toThrowWithMessage(
8786 Error,
8787 `Incorrect iterable input`
8788 )
8789 expect(() => mapRamda(double, null)).toThrowWithMessage(
8790 TypeError,
8791 `Cannot read properties of null (reading 'fantasy-land/map')`
8792 )
8793 expect(() => mapRamda(double, undefined)).toThrowWithMessage(
8794 TypeError,
8795 `Cannot read properties of undefined (reading 'fantasy-land/map')`
8796 )
8797})
8798```
8799
8800</details>
8801
8802<details>
8803
8804<summary><strong>Typescript</strong> test</summary>
8805
8806```typescript
8807import {map} from 'rambda'
8808
8809describe('R.map with arrays', () => {
8810 it('iterable returns the same type as the input', () => {
8811 const result = map<number>(
8812 (x: number) => {
8813 x // $ExpectType number
8814 return x + 2
8815 },
8816 [1, 2, 3]
8817 )
8818 result // $ExpectType number[]
8819 })
8820 it('iterable returns the same type as the input - curried', () => {
8821 const result = map<number>((x: number) => {
8822 x // $ExpectType number
8823 return x + 2
8824 })([1, 2, 3])
8825 result // $ExpectType number[]
8826 })
8827 it('iterable returns different type as the input', () => {
8828 const result = map<number, string>(
8829 (x: number) => {
8830 x // $ExpectType number
8831 return String(x)
8832 },
8833 [1, 2, 3]
8834 )
8835 result // $ExpectType string[]
8836 })
8837})
8838
8839describe('R.map with objects', () => {
8840 it('iterable with all three arguments - curried', () => {
8841 // It requires dummy third typing argument
8842 // in order to identify compared to curry typings for arrays
8843 // ============================================
8844 const result = map<number, string, any>((a, b, c) => {
8845 a // $ExpectType number
8846 b // $ExpectType string
8847 c // $ExpectType Dictionary<number>
8848 return `${a}`
8849 })({a: 1, b: 2})
8850 result // $ExpectType Dictionary<string>
8851 })
8852 it('iterable with all three arguments', () => {
8853 const result = map<number, string>(
8854 (a, b, c) => {
8855 a // $ExpectType number
8856 b // $ExpectType string
8857 c // $ExpectType Dictionary<number>
8858 return `${a}`
8859 },
8860 {a: 1, b: 2}
8861 )
8862 result // $ExpectType Dictionary<string>
8863 })
8864 it('iterable with property argument', () => {
8865 const result = map<number, string>(
8866 (a, b) => {
8867 a // $ExpectType number
8868 b // $ExpectType string
8869 return `${a}`
8870 },
8871 {a: 1, b: 2}
8872 )
8873 result // $ExpectType Dictionary<string>
8874 })
8875 it('iterable with no property argument', () => {
8876 const result = map<number, string>(
8877 a => {
8878 a // $ExpectType number
8879 return `${a}`
8880 },
8881 {a: 1, b: 2}
8882 )
8883 result // $ExpectType Dictionary<string>
8884 })
8885})
8886```
8887
8888</details>
8889
8890<details>
8891
8892<summary>Rambda is fastest. Ramda is 86.6% slower and Lodash is 11.73% slower</summary>
8893
8894```text
8895const R = require('../../dist/rambda.js')
8896
8897const arr = [1, 2, 3, 4]
8898const fn = x => x * 2
8899const map = [
8900 {
8901 label: 'Rambda',
8902 fn: () => {
8903 R.map(fn, arr)
8904 },
8905 },
8906 {
8907 label: 'Ramda',
8908 fn: () => {
8909 Ramda.map(fn, arr)
8910 },
8911 },
8912 {
8913 label: 'Lodash',
8914 fn: () => {
8915 _.map(arr, fn)
8916 },
8917 },
8918]
8919```
8920
8921</details>
8922
8923[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#map)
8924
8925### mapObjIndexed
8926
8927It works the same way as `R.map` does for objects. It is added as Ramda also has this method.
8928
8929[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#mapObjIndexed)
8930
8931### match
8932
8933```typescript
8934
8935match(regExpression: RegExp, str: string): string[]
8936```
8937
8938Curried version of `String.prototype.match` which returns empty array, when there is no match.
8939
8940<details>
8941
8942<summary>All Typescript definitions</summary>
8943
8944```typescript
8945match(regExpression: RegExp, str: string): string[];
8946match(regExpression: RegExp): (str: string) => string[];
8947```
8948
8949</details>
8950
8951<details>
8952
8953<summary><strong>R.match</strong> source</summary>
8954
8955```javascript
8956export function match(pattern, input) {
8957 if (arguments.length === 1) return _input => match(pattern, _input)
8958
8959 const willReturn = input.match(pattern)
8960
8961 return willReturn === null ? [] : willReturn
8962}
8963```
8964
8965</details>
8966
8967<details>
8968
8969<summary><strong>Tests</strong></summary>
8970
8971```javascript
8972import {equals} from './equals'
8973import {match} from './match'
8974
8975test('happy', () => {
8976 expect(match(/a./g)('foo bar baz')).toEqual(['ar', 'az'])
8977})
8978
8979test('fallback', () => {
8980 expect(match(/a./g)('foo')).toEqual([])
8981})
8982
8983test('with string', () => {
8984 expect(match('a', 'foo')).toEqual([])
8985 expect(equals(match('o', 'foo'), ['o'])).toBeTrue()
8986})
8987
8988test('throwing', () => {
8989 expect(() => {
8990 match(/a./g, null)
8991 }).toThrowWithMessage(
8992 TypeError,
8993 `Cannot read properties of null (reading 'match')`
8994 )
8995})
8996```
8997
8998</details>
8999
9000<details>
9001
9002<summary><strong>Typescript</strong> test</summary>
9003
9004```typescript
9005import {match} from 'rambda'
9006
9007const str = 'foo bar'
9008
9009describe('R.match', () => {
9010 it('happy', () => {
9011 const result = match(/foo/, str)
9012 result // $ExpectType string[]
9013 })
9014 it('curried', () => {
9015 const result = match(/foo/)(str)
9016 result // $ExpectType string[]
9017 })
9018})
9019```
9020
9021</details>
9022
9023<details>
9024
9025<summary>Rambda is faster than Ramda with 44.83%</summary>
9026
9027```text
9028const R = require('../../dist/rambda.js')
9029
9030const match = [
9031 {
9032 label: 'Rambda',
9033 fn: () => {
9034 R.match(/a./g)('foo bar baz')
9035 R.match(/a./g, 'foo bar baz')
9036 },
9037 },
9038 {
9039 label: 'Ramda',
9040 fn: () => {
9041 Ramda.match(/a./g)('foo bar baz')
9042 Ramda.match(/a./g, 'foo bar baz')
9043 },
9044 },
9045]
9046```
9047
9048</details>
9049
9050[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#match)
9051
9052### mathMod
9053
9054`R.mathMod` behaves like the modulo operator should mathematically, unlike the `%` operator (and by extension, `R.modulo`). So while `-17 % 5` is `-2`, `mathMod(-17, 5)` is `3`.
9055
9056[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#mathMod)
9057
9058### max
9059
9060```typescript
9061
9062max<T extends Ord>(x: T, y: T): T
9063```
9064
9065It returns the greater value between `x` and `y`.
9066
9067<details>
9068
9069<summary>All Typescript definitions</summary>
9070
9071```typescript
9072max<T extends Ord>(x: T, y: T): T;
9073max<T extends Ord>(x: T): (y: T) => T;
9074```
9075
9076</details>
9077
9078<details>
9079
9080<summary><strong>R.max</strong> source</summary>
9081
9082```javascript
9083export function max(x, y) {
9084 if (arguments.length === 1) return _y => max(x, _y)
9085
9086 return y > x ? y : x
9087}
9088```
9089
9090</details>
9091
9092<details>
9093
9094<summary><strong>Tests</strong></summary>
9095
9096```javascript
9097import {max} from './max'
9098
9099test('with number', () => {
9100 expect(max(2, 1)).toBe(2)
9101})
9102
9103test('with string', () => {
9104 expect(max('foo')('bar')).toBe('foo')
9105 expect(max('bar')('baz')).toBe('baz')
9106})
9107```
9108
9109</details>
9110
9111<details>
9112
9113<summary><strong>Typescript</strong> test</summary>
9114
9115```typescript
9116import {max} from 'rambda'
9117
9118const first = 1
9119const second = 2
9120
9121describe('R.max', () => {
9122 it('happy', () => {
9123 const result = max(first, second)
9124 result // $ExpectType 1 | 2
9125 })
9126 it('curried', () => {
9127 const result = max(first, second)
9128 result // $ExpectType 1 | 2
9129 })
9130 it('curried - cann pass type', () => {
9131 const result = max<number>(first, second)
9132 result // $ExpectType number
9133 })
9134 it('can pass type', () => {
9135 const result = max<number>(first, second)
9136 result // $ExpectType number
9137 })
9138})
9139```
9140
9141</details>
9142
9143[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#max)
9144
9145### maxBy
9146
9147```typescript
9148
9149maxBy<T>(compareFn: (input: T) => Ord, x: T, y: T): T
9150```
9151
9152It returns the greater value between `x` and `y` according to `compareFn` function.
9153
9154<details>
9155
9156<summary>All Typescript definitions</summary>
9157
9158```typescript
9159maxBy<T>(compareFn: (input: T) => Ord, x: T, y: T): T;
9160maxBy<T>(compareFn: (input: T) => Ord, x: T): (y: T) => T;
9161maxBy<T>(compareFn: (input: T) => Ord): (x: T) => (y: T) => T;
9162```
9163
9164</details>
9165
9166<details>
9167
9168<summary><strong>R.maxBy</strong> source</summary>
9169
9170```javascript
9171import {curry} from './curry'
9172
9173export function maxByFn(compareFn, x, y) {
9174 return compareFn(y) > compareFn(x) ? y : x
9175}
9176
9177export const maxBy = curry(maxByFn)
9178```
9179
9180</details>
9181
9182<details>
9183
9184<summary><strong>Tests</strong></summary>
9185
9186```javascript
9187import {maxBy} from './maxBy'
9188
9189test('happy', () => {
9190 expect(maxBy(Math.abs, -5, 2)).toEqual(-5)
9191})
9192
9193test('curried', () => {
9194 expect(maxBy(Math.abs)(2, -5)).toEqual(-5)
9195 expect(maxBy(Math.abs)(2)(-5)).toEqual(-5)
9196})
9197```
9198
9199</details>
9200
9201<details>
9202
9203<summary><strong>Typescript</strong> test</summary>
9204
9205```typescript
9206import {maxBy} from 'rambda'
9207
9208const compareFn = (x: number) => x % 2 === 0 ? 1 : -1
9209const first = 1
9210const second = 2
9211
9212describe('R.maxBy', () => {
9213 it('happy', () => {
9214 const result = maxBy(compareFn, first, second)
9215 result // $ExpectType 1 | 2
9216 })
9217})
9218```
9219
9220</details>
9221
9222[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#maxBy)
9223
9224### mean
9225
9226```typescript
9227
9228mean(list: number[]): number
9229```
9230
9231It returns the mean value of `list` input.
9232
9233<details>
9234
9235<summary>All Typescript definitions</summary>
9236
9237```typescript
9238mean(list: number[]): number;
9239```
9240
9241</details>
9242
9243<details>
9244
9245<summary><strong>R.mean</strong> source</summary>
9246
9247```javascript
9248import {sum} from './sum'
9249
9250export function mean(list) {
9251 return sum(list) / list.length
9252}
9253```
9254
9255</details>
9256
9257<details>
9258
9259<summary><strong>Tests</strong></summary>
9260
9261```javascript
9262import {mean} from './mean'
9263
9264test('happy', () => {
9265 expect(mean([2, 7])).toBe(4.5)
9266})
9267
9268test('with NaN', () => {
9269 expect(mean([])).toBeNaN()
9270})
9271```
9272
9273</details>
9274
9275<details>
9276
9277<summary><strong>Typescript</strong> test</summary>
9278
9279```typescript
9280import {mean} from 'rambda'
9281
9282describe('R.mean', () => {
9283 it('happy', () => {
9284 const result = mean([1, 2, 3])
9285
9286 result // $ExpectType number
9287 })
9288})
9289```
9290
9291</details>
9292
9293[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#mean)
9294
9295### median
9296
9297```typescript
9298
9299median(list: number[]): number
9300```
9301
9302It returns the median value of `list` input.
9303
9304<details>
9305
9306<summary>All Typescript definitions</summary>
9307
9308```typescript
9309median(list: number[]): number;
9310```
9311
9312</details>
9313
9314<details>
9315
9316<summary><strong>R.median</strong> source</summary>
9317
9318```javascript
9319import {mean} from './mean'
9320
9321export function median(list) {
9322 const len = list.length
9323 if (len === 0) return NaN
9324 const width = 2 - (len % 2)
9325 const idx = (len - width) / 2
9326
9327 return mean(
9328 Array.prototype.slice
9329 .call(list, 0)
9330 .sort((a, b) => {
9331 if (a === b) return 0
9332
9333 return a < b ? -1 : 1
9334 })
9335 .slice(idx, idx + width)
9336 )
9337}
9338```
9339
9340</details>
9341
9342<details>
9343
9344<summary><strong>Tests</strong></summary>
9345
9346```javascript
9347import {median} from './median'
9348
9349test('happy', () => {
9350 expect(median([2])).toEqual(2)
9351 expect(median([7, 2, 10, 2, 9])).toEqual(7)
9352})
9353
9354test('with empty array', () => {
9355 expect(median([])).toBeNaN()
9356})
9357```
9358
9359</details>
9360
9361<details>
9362
9363<summary><strong>Typescript</strong> test</summary>
9364
9365```typescript
9366import {median} from 'rambda'
9367
9368describe('R.median', () => {
9369 it('happy', () => {
9370 const result = median([1, 2, 3])
9371
9372 result // $ExpectType number
9373 })
9374})
9375```
9376
9377</details>
9378
9379[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#median)
9380
9381### merge
9382
9383```typescript
9384
9385merge<A, B>(target: A, newProps: B): A & B
9386export function merge<Output>(target: any): (newProps: any) => Output
9387```
9388
9389It creates a copy of `target` object with overidden `newProps` properties.
9390
9391<details>
9392
9393<summary>All Typescript definitions</summary>
9394
9395```typescript
9396merge<A, B>(target: A, newProps: B): A & B
9397merge<Output>(target: any): (newProps: any) => Output;
9398```
9399
9400</details>
9401
9402<details>
9403
9404<summary><strong>R.merge</strong> source</summary>
9405
9406```javascript
9407export function merge(target, newProps) {
9408 if (arguments.length === 1) return _newProps => merge(target, _newProps)
9409
9410 return Object.assign({}, target || {}, newProps || {})
9411}
9412```
9413
9414</details>
9415
9416<details>
9417
9418<summary><strong>Tests</strong></summary>
9419
9420```javascript
9421import {merge} from './merge'
9422
9423const obj = {
9424 foo: 1,
9425 bar: 2,
9426}
9427
9428test('happy', () => {
9429 expect(merge(obj, {bar: 20})).toEqual({
9430 foo: 1,
9431 bar: 20,
9432 })
9433})
9434
9435test('curry', () => {
9436 expect(merge(obj)({baz: 3})).toEqual({
9437 foo: 1,
9438 bar: 2,
9439 baz: 3,
9440 })
9441})
9442
9443/**
9444 * https://github.com/selfrefactor/rambda/issues/77
9445 */
9446test('when undefined or null instead of object', () => {
9447 expect(merge(null, undefined)).toEqual({})
9448 expect(merge(obj, null)).toEqual(obj)
9449 expect(merge(obj, undefined)).toEqual(obj)
9450 expect(merge(undefined, obj)).toEqual(obj)
9451})
9452```
9453
9454</details>
9455
9456<details>
9457
9458<summary><strong>Typescript</strong> test</summary>
9459
9460```typescript
9461import {merge} from 'rambda'
9462
9463interface Output {
9464 foo: number,
9465 bar: number,
9466}
9467
9468describe('R.merge', () => {
9469 const result = merge({foo: 1}, {bar: 2})
9470 const curriedResult = merge<Output>({foo: 1})({bar: 2})
9471
9472 result.foo // $ExpectType number
9473 result.bar // $ExpectType number
9474 curriedResult.bar // $ExpectType number
9475})
9476```
9477
9478</details>
9479
9480<details>
9481
9482<summary>Rambda is fastest. Ramda is 12.21% slower and Lodash is 55.76% slower</summary>
9483
9484```text
9485const R = require('../../dist/rambda.js')
9486
9487const obj = {bar: 'yes'}
9488const a = {
9489 foo: 'bar',
9490 bar: 'baz',
9491}
9492const merge = [
9493 {
9494 label: 'Rambda',
9495 fn: () => {
9496 R.merge(a, obj)
9497 },
9498 },
9499 {
9500 label: 'Ramda',
9501 fn: () => {
9502 Ramda.merge(a, obj)
9503 },
9504 },
9505 {
9506 label: 'Lodash',
9507 fn: () => {
9508 _.merge(a, obj)
9509 },
9510 },
9511]
9512```
9513
9514</details>
9515
9516[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#merge)
9517
9518### mergeAll
9519
9520```typescript
9521
9522mergeAll<T>(list: object[]): T
9523```
9524
9525It merges all objects of `list` array sequentially and returns the result.
9526
9527<details>
9528
9529<summary>All Typescript definitions</summary>
9530
9531```typescript
9532mergeAll<T>(list: object[]): T;
9533mergeAll(list: object[]): object;
9534```
9535
9536</details>
9537
9538<details>
9539
9540<summary><strong>R.mergeAll</strong> source</summary>
9541
9542```javascript
9543import {map} from './map'
9544import {merge} from './merge'
9545
9546export function mergeAll(arr) {
9547 let willReturn = {}
9548 map(val => {
9549 willReturn = merge(willReturn, val)
9550 }, arr)
9551
9552 return willReturn
9553}
9554```
9555
9556</details>
9557
9558<details>
9559
9560<summary><strong>Tests</strong></summary>
9561
9562```javascript
9563import {mergeAll} from './mergeAll'
9564
9565test('case 1', () => {
9566 const arr = [{a: 1}, {b: 2}, {c: 3}]
9567 const expectedResult = {
9568 a: 1,
9569 b: 2,
9570 c: 3,
9571 }
9572 expect(mergeAll(arr)).toEqual(expectedResult)
9573})
9574
9575test('case 2', () => {
9576 expect(mergeAll([{foo: 1}, {bar: 2}, {baz: 3}])).toEqual({
9577 foo: 1,
9578 bar: 2,
9579 baz: 3,
9580 })
9581})
9582```
9583
9584</details>
9585
9586<details>
9587
9588<summary><strong>Typescript</strong> test</summary>
9589
9590```typescript
9591import {mergeAll} from 'rambda'
9592
9593describe('R.mergeAll', () => {
9594 it('with passing type', () => {
9595 interface Output {
9596 foo: number,
9597 bar: number,
9598 }
9599 const result = mergeAll<Output>([{foo: 1}, {bar: 2}])
9600 result.foo // $ExpectType number
9601 result.bar // $ExpectType number
9602 })
9603
9604 it('without passing type', () => {
9605 const result = mergeAll([{foo: 1}, {bar: 2}])
9606 result // $ExpectType unknown
9607 })
9608})
9609```
9610
9611</details>
9612
9613[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#mergeAll)
9614
9615### mergeDeepRight
9616
9617```typescript
9618
9619mergeDeepRight<Output>(target: object, newProps: object): Output
9620```
9621
9622Creates a new object with the own properties of the first object merged with the own properties of the second object. If a key exists in both objects:
9623
9624 - and both values are objects, the two values will be recursively merged
9625 - otherwise the value from the second object will be used.
9626
9627<details>
9628
9629<summary>All Typescript definitions</summary>
9630
9631```typescript
9632mergeDeepRight<Output>(target: object, newProps: object): Output;
9633mergeDeepRight<Output>(target: object): (newProps: object) => Output;
9634```
9635
9636</details>
9637
9638<details>
9639
9640<summary><strong>R.mergeDeepRight</strong> source</summary>
9641
9642```javascript
9643import {type} from './type'
9644
9645export function mergeDeepRight(target, source) {
9646 if (arguments.length === 1) {
9647 return sourceHolder => mergeDeepRight(target, sourceHolder)
9648 }
9649
9650 const willReturn = JSON.parse(JSON.stringify(target))
9651
9652 Object.keys(source).forEach(key => {
9653 if (type(source[key]) === 'Object') {
9654 if (type(target[key]) === 'Object') {
9655 willReturn[key] = mergeDeepRight(target[key], source[key])
9656 } else {
9657 willReturn[key] = source[key]
9658 }
9659 } else {
9660 willReturn[key] = source[key]
9661 }
9662 })
9663
9664 return willReturn
9665}
9666```
9667
9668</details>
9669
9670<details>
9671
9672<summary><strong>Tests</strong></summary>
9673
9674```javascript
9675// import { mergeDeepRight } from 'ramda'
9676import {mergeDeepRight} from './mergeDeepRight'
9677
9678const slave = {
9679 name: 'evilMe',
9680 age: 10,
9681 contact: {
9682 a: 1,
9683 email: 'foo@example.com',
9684 },
9685}
9686const master = {
9687 age: 40,
9688 contact: {email: 'baz@example.com'},
9689 songs: {title: 'Remains the same'},
9690}
9691
9692test('happy', () => {
9693 const result = mergeDeepRight(slave, master)
9694 const curryResult = mergeDeepRight(slave)(master)
9695 const expected = {
9696 age: 40,
9697 name: 'evilMe',
9698 contact: {
9699 a: 1,
9700 email: 'baz@example.com',
9701 },
9702 songs: {title: 'Remains the same'},
9703 }
9704
9705 expect(result).toEqual(expected)
9706 expect(curryResult).toEqual(expected)
9707})
9708
9709test('ramda compatible test 1', () => {
9710 const a = {
9711 w: 1,
9712 x: 2,
9713 y: {z: 3},
9714 }
9715 const b = {
9716 a: 4,
9717 b: 5,
9718 c: {d: 6},
9719 }
9720 const result = mergeDeepRight(a, b)
9721 const expected = {
9722 w: 1,
9723 x: 2,
9724 y: {z: 3},
9725 a: 4,
9726 b: 5,
9727 c: {d: 6},
9728 }
9729
9730 expect(result).toEqual(expected)
9731})
9732
9733test('ramda compatible test 2', () => {
9734 const a = {
9735 a: {
9736 b: 1,
9737 c: 2,
9738 },
9739 y: 0,
9740 }
9741 const b = {
9742 a: {
9743 b: 3,
9744 d: 4,
9745 },
9746 z: 0,
9747 }
9748 const result = mergeDeepRight(a, b)
9749 const expected = {
9750 a: {
9751 b: 3,
9752 c: 2,
9753 d: 4,
9754 },
9755 y: 0,
9756 z: 0,
9757 }
9758
9759 expect(result).toEqual(expected)
9760})
9761
9762test('ramda compatible test 3', () => {
9763 const a = {
9764 w: 1,
9765 x: {y: 2},
9766 }
9767 const result = mergeDeepRight(a, {x: {y: 3}})
9768 const expected = {
9769 w: 1,
9770 x: {y: 3},
9771 }
9772 expect(result).toEqual(expected)
9773})
9774```
9775
9776</details>
9777
9778<details>
9779
9780<summary><strong>Typescript</strong> test</summary>
9781
9782```typescript
9783import {mergeDeepRight} from 'rambda'
9784
9785interface Output {
9786 foo: {
9787 bar: number,
9788 },
9789}
9790
9791describe('R.mergeDeepRight', () => {
9792 const result = mergeDeepRight<Output>({foo: {bar: 1}}, {foo: {bar: 2}})
9793 result.foo.bar // $ExpectType number
9794})
9795```
9796
9797</details>
9798
9799[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#mergeDeepRight)
9800
9801### mergeLeft
9802
9803```typescript
9804
9805mergeLeft<Output>(newProps: object, target: object): Output
9806```
9807
9808Same as `R.merge`, but in opposite direction.
9809
9810<details>
9811
9812<summary>All Typescript definitions</summary>
9813
9814```typescript
9815mergeLeft<Output>(newProps: object, target: object): Output;
9816mergeLeft<Output>(newProps: object): (target: object) => Output;
9817```
9818
9819</details>
9820
9821<details>
9822
9823<summary><strong>R.mergeLeft</strong> source</summary>
9824
9825```javascript
9826import {merge} from './merge'
9827
9828export function mergeLeft(x, y) {
9829 if (arguments.length === 1) return _y => mergeLeft(x, _y)
9830
9831 return merge(y, x)
9832}
9833```
9834
9835</details>
9836
9837<details>
9838
9839<summary><strong>Tests</strong></summary>
9840
9841```javascript
9842import {mergeLeft} from './mergeLeft'
9843
9844const obj = {
9845 foo: 1,
9846 bar: 2,
9847}
9848
9849test('happy', () => {
9850 expect(mergeLeft({bar: 20}, obj)).toEqual({
9851 foo: 1,
9852 bar: 20,
9853 })
9854})
9855
9856test('curry', () => {
9857 expect(mergeLeft({baz: 3})(obj)).toEqual({
9858 foo: 1,
9859 bar: 2,
9860 baz: 3,
9861 })
9862})
9863
9864test('when undefined or null instead of object', () => {
9865 expect(mergeLeft(null, undefined)).toEqual({})
9866 expect(mergeLeft(obj, null)).toEqual(obj)
9867 expect(mergeLeft(obj, undefined)).toEqual(obj)
9868 expect(mergeLeft(undefined, obj)).toEqual(obj)
9869})
9870```
9871
9872</details>
9873
9874<details>
9875
9876<summary><strong>Typescript</strong> test</summary>
9877
9878```typescript
9879import {mergeLeft} from 'rambda'
9880
9881interface Output {
9882 foo: number,
9883 bar: number,
9884}
9885
9886describe('R.mergeLeft', () => {
9887 const result = mergeLeft<Output>({foo: 1}, {bar: 2})
9888 const curriedResult = mergeLeft<Output>({foo: 1})({bar: 2})
9889
9890 result.foo // $ExpectType number
9891 result.bar // $ExpectType number
9892 curriedResult.bar // $ExpectType number
9893})
9894```
9895
9896</details>
9897
9898[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#mergeLeft)
9899
9900### min
9901
9902```typescript
9903
9904min<T extends Ord>(x: T, y: T): T
9905```
9906
9907It returns the lesser value between `x` and `y`.
9908
9909<details>
9910
9911<summary>All Typescript definitions</summary>
9912
9913```typescript
9914min<T extends Ord>(x: T, y: T): T;
9915min<T extends Ord>(x: T): (y: T) => T;
9916```
9917
9918</details>
9919
9920<details>
9921
9922<summary><strong>R.min</strong> source</summary>
9923
9924```javascript
9925export function min(x, y) {
9926 if (arguments.length === 1) return _y => min(x, _y)
9927
9928 return y < x ? y : x
9929}
9930```
9931
9932</details>
9933
9934<details>
9935
9936<summary><strong>Tests</strong></summary>
9937
9938```javascript
9939import {min} from './min'
9940
9941test('happy', () => {
9942 expect(min(2, 1)).toBe(1)
9943 expect(min(1)(2)).toBe(1)
9944})
9945```
9946
9947</details>
9948
9949<details>
9950
9951<summary><strong>Typescript</strong> test</summary>
9952
9953```typescript
9954import {min} from 'rambda'
9955
9956const first = 1
9957const second = 2
9958
9959describe('R.min', () => {
9960 it('happy', () => {
9961 const result = min(first, second)
9962 result // $ExpectType 1 | 2
9963 })
9964 it('curried', () => {
9965 const result = min(first, second)
9966 result // $ExpectType 1 | 2
9967 })
9968 it('curried - cann pass type', () => {
9969 const result = min<number>(first, second)
9970 result // $ExpectType number
9971 })
9972 it('can pass type', () => {
9973 const result = min<number>(first, second)
9974 result // $ExpectType number
9975 })
9976})
9977```
9978
9979</details>
9980
9981[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#min)
9982
9983### minBy
9984
9985```typescript
9986
9987minBy<T>(compareFn: (input: T) => Ord, x: T, y: T): T
9988```
9989
9990It returns the lesser value between `x` and `y` according to `compareFn` function.
9991
9992<details>
9993
9994<summary>All Typescript definitions</summary>
9995
9996```typescript
9997minBy<T>(compareFn: (input: T) => Ord, x: T, y: T): T;
9998minBy<T>(compareFn: (input: T) => Ord, x: T): (y: T) => T;
9999minBy<T>(compareFn: (input: T) => Ord): (x: T) => (y: T) => T;
10000```
10001
10002</details>
10003
10004<details>
10005
10006<summary><strong>R.minBy</strong> source</summary>
10007
10008```javascript
10009import {curry} from './curry'
10010
10011export function minByFn(compareFn, x, y) {
10012 return compareFn(y) < compareFn(x) ? y : x
10013}
10014
10015export const minBy = curry(minByFn)
10016```
10017
10018</details>
10019
10020<details>
10021
10022<summary><strong>Tests</strong></summary>
10023
10024```javascript
10025import {minBy} from './minBy'
10026
10027test('happy', () => {
10028 expect(minBy(Math.abs, -5, 2)).toEqual(2)
10029})
10030
10031test('curried', () => {
10032 expect(minBy(Math.abs)(2, -5)).toEqual(2)
10033 expect(minBy(Math.abs)(2)(-5)).toEqual(2)
10034})
10035```
10036
10037</details>
10038
10039<details>
10040
10041<summary><strong>Typescript</strong> test</summary>
10042
10043```typescript
10044import {minBy} from 'rambda'
10045
10046const compareFn = (x: number) => x % 2 === 0 ? 1 : -1
10047const first = 1
10048const second = 2
10049
10050describe('R.minBy', () => {
10051 it('happy', () => {
10052 const result = minBy(compareFn, first, second)
10053 result // $ExpectType 1 | 2
10054 })
10055})
10056```
10057
10058</details>
10059
10060[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#minBy)
10061
10062### modulo
10063
10064Curried version of `x%y`.
10065
10066[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#modulo)
10067
10068### move
10069
10070```typescript
10071
10072move<T>(fromIndex: number, toIndex: number, list: T[]): T[]
10073```
10074
10075It returns a copy of `list` with exchanged `fromIndex` and `toIndex` elements.
10076
10077<details>
10078
10079<summary>All Typescript definitions</summary>
10080
10081```typescript
10082move<T>(fromIndex: number, toIndex: number, list: T[]): T[];
10083move(fromIndex: number, toIndex: number): <T>(list: T[]) => T[];
10084move(fromIndex: number): {
10085 <T>(toIndex: number, list: T[]): T[];
10086 (toIndex: number): <T>(list: T[]) => T[];
10087};
10088```
10089
10090</details>
10091
10092<details>
10093
10094<summary><strong>R.move</strong> source</summary>
10095
10096```javascript
10097import {curry} from './curry'
10098import {cloneList} from './_internals/cloneList'
10099
10100function moveFn(fromIndex, toIndex, list) {
10101 if (fromIndex < 0 || toIndex < 0) {
10102 throw new Error('Rambda.move does not support negative indexes')
10103 }
10104 if (fromIndex > list.length - 1 || toIndex > list.length - 1) return list
10105
10106 const clone = cloneList(list)
10107 clone[fromIndex] = list[toIndex]
10108 clone[toIndex] = list[fromIndex]
10109
10110 return clone
10111}
10112
10113export const move = curry(moveFn)
10114```
10115
10116</details>
10117
10118<details>
10119
10120<summary><strong>Tests</strong></summary>
10121
10122```javascript
10123import {move} from './move'
10124const list = [1, 2, 3, 4]
10125
10126test('happy', () => {
10127 const result = move(0, 1, list)
10128
10129 expect(result).toEqual([2, 1, 3, 4])
10130})
10131
10132test('with negative index', () => {
10133 const errorMessage = 'Rambda.move does not support negative indexes'
10134 expect(() => move(0, -1, list)).toThrowWithMessage(Error, errorMessage)
10135 expect(() => move(-1, 0, list)).toThrowWithMessage(Error, errorMessage)
10136})
10137
10138test('when indexes are outside the list outbounds', () => {
10139 const result1 = move(10, 1, list)
10140 const result2 = move(1, 10, list)
10141
10142 expect(result1).toEqual(list)
10143 expect(result2).toEqual(list)
10144})
10145```
10146
10147</details>
10148
10149<details>
10150
10151<summary><strong>Typescript</strong> test</summary>
10152
10153```typescript
10154import {move} from 'rambda'
10155
10156const list = [1, 2, 3]
10157
10158describe('R.move', () => {
10159 it('happy', () => {
10160 const result = move(0, 1, list)
10161
10162 result // $ExpectType number[]
10163 })
10164 it('curried 1', () => {
10165 const result = move(0, 1)(list)
10166
10167 result // $ExpectType number[]
10168 })
10169 it('curried 2', () => {
10170 const result = move(0)(1)(list)
10171
10172 result // $ExpectType number[]
10173 })
10174})
10175```
10176
10177</details>
10178
10179[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#move)
10180
10181### multiply
10182
10183Curried version of `x*y`.
10184
10185[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#multiply)
10186
10187### negate
10188
10189[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#negate)
10190
10191### none
10192
10193```typescript
10194
10195none<T>(predicate: (x: T) => boolean, list: T[]): boolean
10196```
10197
10198It returns `true`, if all members of array `list` returns `false`, when applied as argument to `predicate` function.
10199
10200<details>
10201
10202<summary>All Typescript definitions</summary>
10203
10204```typescript
10205none<T>(predicate: (x: T) => boolean, list: T[]): boolean;
10206none<T>(predicate: (x: T) => boolean): (list: T[]) => boolean;
10207```
10208
10209</details>
10210
10211<details>
10212
10213<summary><strong>R.none</strong> source</summary>
10214
10215```javascript
10216export function none(predicate, list) {
10217 if (arguments.length === 1) return _list => none(predicate, _list)
10218
10219 for (let i = 0; i < list.length; i++) {
10220 if (!predicate(list[i])) return true
10221 }
10222
10223 return false
10224}
10225```
10226
10227</details>
10228
10229<details>
10230
10231<summary><strong>Tests</strong></summary>
10232
10233```javascript
10234import {none} from './none'
10235
10236const isEven = n => n % 2 === 0
10237const isOdd = n => n % 2 === 1
10238const arr = [1, 3, 5, 7, 9, 11]
10239
10240test('when true', () => {
10241 expect(none(isEven, arr)).toBeTrue()
10242})
10243
10244test('when false curried', () => {
10245 expect(none(isOdd)(arr)).toBeFalse()
10246})
10247```
10248
10249</details>
10250
10251<details>
10252
10253<summary><strong>Typescript</strong> test</summary>
10254
10255```typescript
10256import {none} from 'rambda'
10257
10258describe('R.none', () => {
10259 it('happy', () => {
10260 const result = none(
10261 x => {
10262 x // $ExpectType number
10263 return x > 0
10264 },
10265 [1, 2, 3]
10266 )
10267 result // $ExpectType boolean
10268 })
10269 it('curried needs a type', () => {
10270 const result = none<number>(x => {
10271 x // $ExpectType number
10272 return x > 0
10273 })([1, 2, 3])
10274 result // $ExpectType boolean
10275 })
10276})
10277```
10278
10279</details>
10280
10281<details>
10282
10283<summary>Rambda is faster than Ramda with 96.48%</summary>
10284
10285```text
10286const R = require('../../dist/rambda.js')
10287
10288const isEven = n => n % 2 === 0
10289const arr = [1, 3, 5, 7, 9, 11]
10290
10291const none = [
10292 {
10293 label: 'Rambda',
10294 fn: () => {
10295 R.none(isEven, arr)
10296 R.none(isEven)(arr)
10297 },
10298 },
10299 {
10300 label: 'Ramda',
10301 fn: () => {
10302 Ramda.none(isEven, arr)
10303 Ramda.none(isEven)(arr)
10304 },
10305 },
10306]
10307```
10308
10309</details>
10310
10311[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#none)
10312
10313### not
10314
10315```typescript
10316
10317not(input: any): boolean
10318```
10319
10320It returns a boolean negated version of `input`.
10321
10322<details>
10323
10324<summary>All Typescript definitions</summary>
10325
10326```typescript
10327not(input: any): boolean;
10328```
10329
10330</details>
10331
10332<details>
10333
10334<summary><strong>R.not</strong> source</summary>
10335
10336```javascript
10337export function not(input) {
10338 return !input
10339}
10340```
10341
10342</details>
10343
10344<details>
10345
10346<summary><strong>Tests</strong></summary>
10347
10348```javascript
10349import {not} from './not'
10350
10351test('not', () => {
10352 expect(not(false)).toEqual(true)
10353 expect(not(true)).toEqual(false)
10354 expect(not(0)).toEqual(true)
10355 expect(not(1)).toEqual(false)
10356})
10357```
10358
10359</details>
10360
10361<details>
10362
10363<summary><strong>Typescript</strong> test</summary>
10364
10365```typescript
10366import {not} from 'rambda'
10367
10368describe('R.not', () => {
10369 it('happy', () => {
10370 const result = not(4)
10371
10372 result // $ExpectType boolean
10373 })
10374})
10375```
10376
10377</details>
10378
10379[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#not)
10380
10381### nth
10382
10383```typescript
10384
10385nth<T>(index: number, list: T[]): T | undefined
10386```
10387
10388Curried version of `list[index]`.
10389
10390<details>
10391
10392<summary>All Typescript definitions</summary>
10393
10394```typescript
10395nth<T>(index: number, list: T[]): T | undefined;
10396nth(index: number): <T>(list: T[]) => T | undefined;
10397```
10398
10399</details>
10400
10401<details>
10402
10403<summary><strong>R.nth</strong> source</summary>
10404
10405```javascript
10406export function nth(index, list) {
10407 if (arguments.length === 1) return _list => nth(index, _list)
10408
10409 const idx = index < 0 ? list.length + index : index
10410
10411 return Object.prototype.toString.call(list) === '[object String]'
10412 ? list.charAt(idx)
10413 : list[idx]
10414}
10415```
10416
10417</details>
10418
10419<details>
10420
10421<summary><strong>Tests</strong></summary>
10422
10423```javascript
10424import {nth} from './nth'
10425
10426test('happy', () => {
10427 expect(nth(2, [1, 2, 3, 4])).toEqual(3)
10428})
10429
10430test('with curry', () => {
10431 expect(nth(2)([1, 2, 3, 4])).toEqual(3)
10432})
10433
10434test('with string', () => {
10435 expect(nth(2)('foo')).toEqual('o')
10436})
10437
10438test('with negative index', () => {
10439 expect(nth(-3)([1, 2, 3, 4])).toEqual(2)
10440})
10441```
10442
10443</details>
10444
10445<details>
10446
10447<summary><strong>Typescript</strong> test</summary>
10448
10449```typescript
10450import {nth} from 'rambda'
10451
10452const list = [1, 2, 3]
10453
10454describe('R.nth', () => {
10455 it('happy', () => {
10456 const result = nth(4, list)
10457
10458 result // $ExpectType number | undefined
10459 })
10460 it('curried', () => {
10461 const result = nth(1)(list)
10462
10463 result // $ExpectType number | undefined
10464 })
10465})
10466```
10467
10468</details>
10469
10470[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#nth)
10471
10472### objOf
10473
10474It creates an object with a single key-value pair.
10475
10476[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#objOf)
10477
10478### of
10479
10480```typescript
10481
10482of<T>(x: T): T[]
10483```
10484
10485<details>
10486
10487<summary>All Typescript definitions</summary>
10488
10489```typescript
10490of<T>(x: T): T[];
10491```
10492
10493</details>
10494
10495<details>
10496
10497<summary><strong>R.of</strong> source</summary>
10498
10499```javascript
10500export function of(value) {
10501 return [value]
10502}
10503```
10504
10505</details>
10506
10507<details>
10508
10509<summary><strong>Tests</strong></summary>
10510
10511```javascript
10512import {of} from './of'
10513
10514test('happy', () => {
10515 expect(of(3)).toEqual([3])
10516
10517 expect(of(null)).toEqual([null])
10518})
10519```
10520
10521</details>
10522
10523<details>
10524
10525<summary><strong>Typescript</strong> test</summary>
10526
10527```typescript
10528import {of} from 'ramda'
10529
10530const list = [1, 2, 3]
10531
10532describe('R.of', () => {
10533 it('happy', () => {
10534 const result = of(4)
10535
10536 result // $ExpectType number[]
10537 })
10538 it('curried', () => {
10539 const result = of(list)
10540
10541 result // $ExpectType number[][]
10542 })
10543})
10544```
10545
10546</details>
10547
10548[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#of)
10549
10550### omit
10551
10552```typescript
10553
10554omit<T, K extends string>(propsToOmit: K[], obj: T): Omit<T, K>
10555```
10556
10557It returns a partial copy of an `obj` without `propsToOmit` properties.
10558
10559<details>
10560
10561<summary>All Typescript definitions</summary>
10562
10563```typescript
10564omit<T, K extends string>(propsToOmit: K[], obj: T): Omit<T, K>;
10565omit<K extends string>(propsToOmit: K[]): <T>(obj: T) => Omit<T, K>;
10566omit<T, U>(propsToOmit: string, obj: T): U;
10567omit<T, U>(propsToOmit: string): (obj: T) => U;
10568omit<T>(propsToOmit: string, obj: object): T;
10569omit<T>(propsToOmit: string): (obj: object) => T;
10570```
10571
10572</details>
10573
10574<details>
10575
10576<summary><strong>R.omit</strong> source</summary>
10577
10578```javascript
10579export function omit(propsToOmit, obj) {
10580 if (arguments.length === 1) return _obj => omit(propsToOmit, _obj)
10581
10582 if (obj === null || obj === undefined) {
10583 return undefined
10584 }
10585
10586 const propsToOmitValue =
10587 typeof propsToOmit === 'string' ? propsToOmit.split(',') : propsToOmit
10588
10589 const willReturn = {}
10590
10591 for (const key in obj) {
10592 if (!propsToOmitValue.includes(key)) {
10593 willReturn[key] = obj[key]
10594 }
10595 }
10596
10597 return willReturn
10598}
10599```
10600
10601</details>
10602
10603<details>
10604
10605<summary><strong>Tests</strong></summary>
10606
10607```javascript
10608import {omit} from './omit'
10609
10610test('with string as condition', () => {
10611 const obj = {
10612 a: 1,
10613 b: 2,
10614 c: 3,
10615 }
10616 const result = omit('a,c', obj)
10617 const resultCurry = omit('a,c')(obj)
10618 const expectedResult = {b: 2}
10619
10620 expect(result).toEqual(expectedResult)
10621 expect(resultCurry).toEqual(expectedResult)
10622})
10623
10624test('with null', () => {
10625 expect(omit('a,b', null)).toEqual(undefined)
10626})
10627
10628test("doesn't work with number as property", () => {
10629 expect(
10630 omit([42], {
10631 a: 1,
10632 42: 2,
10633 })
10634 ).toEqual({
10635 42: 2,
10636 a: 1,
10637 })
10638})
10639
10640test('happy', () => {
10641 expect(
10642 omit(['a', 'c'])({
10643 a: 'foo',
10644 b: 'bar',
10645 c: 'baz',
10646 })
10647 ).toEqual({b: 'bar'})
10648})
10649```
10650
10651</details>
10652
10653<details>
10654
10655<summary><strong>Typescript</strong> test</summary>
10656
10657```typescript
10658import {omit} from 'rambda'
10659
10660describe('R.omit with array as props input', () => {
10661 it('allow Typescript to infer object type', () => {
10662 const input = {a: 'foo', b: 2, c: 3, d: 4}
10663 const result = omit(['b,c'], input)
10664
10665 result.a // $ExpectType string
10666 result.d // $ExpectType number
10667
10668 const curriedResult = omit(['a,c'], input)
10669
10670 curriedResult.a // $ExpectType string
10671 curriedResult.d // $ExpectType number
10672 })
10673
10674 it('declare type of input object', () => {
10675 interface Input {
10676 a: string,
10677 b: number,
10678 c: number,
10679 d: number,
10680 }
10681 const input: Input = {a: 'foo', b: 2, c: 3, d: 4}
10682 const result = omit(['b,c'], input)
10683 result // $ExpectType Omit<Input, "b,c">
10684
10685 result.a // $ExpectType string
10686 result.d // $ExpectType number
10687
10688 const curriedResult = omit(['a,c'], input)
10689
10690 curriedResult.a // $ExpectType string
10691 curriedResult.d // $ExpectType number
10692 })
10693})
10694
10695describe('R.omit with string as props input', () => {
10696 interface Output {
10697 b: number,
10698 d: number,
10699 }
10700
10701 it('explicitly declare output', () => {
10702 const result = omit<Output>('a,c', {a: 1, b: 2, c: 3, d: 4})
10703 result // $ExpectType Output
10704 result.b // $ExpectType number
10705
10706 const curriedResult = omit<Output>('a,c')({a: 1, b: 2, c: 3, d: 4})
10707
10708 curriedResult.b // $ExpectType number
10709 })
10710
10711 it('explicitly declare input and output', () => {
10712 interface Input {
10713 a: number,
10714 b: number,
10715 c: number,
10716 d: number,
10717 }
10718 const result = omit<Input, Output>('a,c', {a: 1, b: 2, c: 3, d: 4})
10719 result // $ExpectType Output
10720 result.b // $ExpectType number
10721
10722 const curriedResult = omit<Input, Output>('a,c')({
10723 a: 1,
10724 b: 2,
10725 c: 3,
10726 d: 4,
10727 })
10728
10729 curriedResult.b // $ExpectType number
10730 })
10731
10732 it('without passing type', () => {
10733 const result = omit('a,c', {a: 1, b: 2, c: 3, d: 4})
10734 result // $ExpectType unknown
10735 })
10736})
10737```
10738
10739</details>
10740
10741<details>
10742
10743<summary>Rambda is fastest. Ramda is 69.95% slower and Lodash is 97.34% slower</summary>
10744
10745```text
10746const R = require('../../dist/rambda.js')
10747
10748const obj = {
10749 a: 'foo',
10750 b: 'bar',
10751 c: 'baz',
10752}
10753const toOmit = ['a', 'c']
10754const omit = [
10755 {
10756 label: 'Rambda',
10757 fn: () => {
10758 R.omit(toOmit, obj)
10759 },
10760 },
10761 {
10762 label: 'Ramda',
10763 fn: () => {
10764 Ramda.omit(toOmit, obj)
10765 },
10766 },
10767 {
10768 label: 'Lodash',
10769 fn: () => {
10770 _.omit(obj, toOmit)
10771 },
10772 },
10773]
10774```
10775
10776</details>
10777
10778[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#omit)
10779
10780### once
10781
10782```typescript
10783
10784once<T extends (...args: any[]) => any>(func: T): T
10785```
10786
10787It returns a function, which invokes only once `fn` function.
10788
10789<details>
10790
10791<summary>All Typescript definitions</summary>
10792
10793```typescript
10794once<T extends (...args: any[]) => any>(func: T): T;
10795```
10796
10797</details>
10798
10799<details>
10800
10801<summary><strong>R.once</strong> source</summary>
10802
10803```javascript
10804import {curry} from './curry'
10805
10806function onceFn(fn, context) {
10807 let result
10808
10809 return function () {
10810 if (fn) {
10811 result = fn.apply(context || this, arguments)
10812 fn = null
10813 }
10814
10815 return result
10816 }
10817}
10818
10819export function once(fn, context) {
10820 if (arguments.length === 1) {
10821 const wrap = onceFn(fn, context)
10822
10823 return curry(wrap)
10824 }
10825
10826 return onceFn(fn, context)
10827}
10828```
10829
10830</details>
10831
10832<details>
10833
10834<summary><strong>Tests</strong></summary>
10835
10836```javascript
10837import {once} from './once'
10838
10839test('with counter', () => {
10840 let counter = 0
10841 const runOnce = once(x => {
10842 counter++
10843
10844 return x + 2
10845 })
10846 expect(runOnce(1)).toEqual(3)
10847 runOnce(1)
10848 runOnce(1)
10849 runOnce(1)
10850 expect(counter).toEqual(1)
10851})
10852
10853test('happy path', () => {
10854 const addOneOnce = once((a, b, c) => a + b + c, 1)
10855
10856 expect(addOneOnce(10, 20, 30)).toBe(60)
10857 expect(addOneOnce(40)).toEqual(60)
10858})
10859```
10860
10861</details>
10862
10863<details>
10864
10865<summary><strong>Typescript</strong> test</summary>
10866
10867```typescript
10868import {once} from 'rambda'
10869
10870describe('R.once', () => {
10871 it('happy', () => {
10872 const runOnce = once((x: number) => {
10873 return x + 2
10874 })
10875
10876 const result = runOnce(1)
10877 result // $ExpectType number
10878 })
10879})
10880```
10881
10882</details>
10883
10884[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#once)
10885
10886### or
10887
10888```typescript
10889
10890or<T, U>(a: T, b: U): T | U
10891```
10892
10893Logical OR
10894
10895<details>
10896
10897<summary>All Typescript definitions</summary>
10898
10899```typescript
10900or<T, U>(a: T, b: U): T | U;
10901or<T>(a: T): <U>(b: U) => T | U;
10902```
10903
10904</details>
10905
10906<details>
10907
10908<summary><strong>R.or</strong> source</summary>
10909
10910```javascript
10911export function or(a, b) {
10912 if (arguments.length === 1) return _b => or(a, _b)
10913
10914 return a || b
10915}
10916```
10917
10918</details>
10919
10920<details>
10921
10922<summary><strong>Tests</strong></summary>
10923
10924```javascript
10925import {or} from './or'
10926
10927test('happy', () => {
10928 expect(or(0, 'foo')).toBe('foo')
10929 expect(or(true, true)).toBeTrue()
10930 expect(or(false)(true)).toBeTrue()
10931 expect(or(false, false)).toBeFalse()
10932})
10933```
10934
10935</details>
10936
10937<details>
10938
10939<summary><strong>Typescript</strong> test</summary>
10940
10941```typescript
10942import {or} from 'ramda'
10943
10944describe('R.or', () => {
10945 it('happy', () => {
10946 const result = or(true, false)
10947 result // $ExpectType boolean
10948 })
10949 it('curried', () => {
10950 const result = or(1)('foo')
10951 result // $ExpectType number | "foo"
10952 })
10953})
10954```
10955
10956</details>
10957
10958[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#or)
10959
10960### over
10961
10962```typescript
10963
10964over<T>(lens: Lens, fn: Arity1Fn, value: T): T
10965```
10966
10967It returns a copied **Object** or **Array** with modified value received by applying function `fn` to `lens` focus.
10968
10969<details>
10970
10971<summary>All Typescript definitions</summary>
10972
10973```typescript
10974over<T>(lens: Lens, fn: Arity1Fn, value: T): T;
10975over<T>(lens: Lens, fn: Arity1Fn, value: T[]): T[];
10976over(lens: Lens, fn: Arity1Fn): <T>(value: T) => T;
10977over(lens: Lens, fn: Arity1Fn): <T>(value: T[]) => T[];
10978over(lens: Lens): <T>(fn: Arity1Fn, value: T) => T;
10979over(lens: Lens): <T>(fn: Arity1Fn, value: T[]) => T[];
10980```
10981
10982</details>
10983
10984<details>
10985
10986<summary><strong>R.over</strong> source</summary>
10987
10988```javascript
10989import {curry} from './curry'
10990
10991const Identity = x => ({
10992 x,
10993 map: fn => Identity(fn(x)),
10994})
10995
10996function overFn(lens, fn, object) {
10997 return lens(x => Identity(fn(x)))(object).x
10998}
10999
11000export const over = curry(overFn)
11001```
11002
11003</details>
11004
11005<details>
11006
11007<summary><strong>Tests</strong></summary>
11008
11009```javascript
11010import {assoc} from './assoc'
11011import {lens} from './lens'
11012import {lensIndex} from './lensIndex'
11013import {lensPath} from './lensPath'
11014import {over} from './over'
11015import {prop} from './prop'
11016import {toUpper} from './toUpper'
11017
11018const testObject = {
11019 foo: 'bar',
11020 baz: {
11021 a: 'x',
11022 b: 'y',
11023 },
11024}
11025
11026test('assoc lens', () => {
11027 const assocLens = lens(prop('foo'), assoc('foo'))
11028 const result = over(assocLens, toUpper, testObject)
11029 const expected = {
11030 ...testObject,
11031 foo: 'BAR',
11032 }
11033 expect(result).toEqual(expected)
11034})
11035
11036test('path lens', () => {
11037 const pathLens = lensPath('baz.a')
11038 const result = over(pathLens, toUpper, testObject)
11039 const expected = {
11040 ...testObject,
11041 baz: {
11042 a: 'X',
11043 b: 'y',
11044 },
11045 }
11046 expect(result).toEqual(expected)
11047})
11048
11049test('index lens', () => {
11050 const indexLens = lensIndex(0)
11051 const result = over(indexLens, toUpper)(['foo', 'bar'])
11052 expect(result).toEqual(['FOO', 'bar'])
11053})
11054```
11055
11056</details>
11057
11058<details>
11059
11060<summary>Rambda is faster than Ramda with 56.23%</summary>
11061
11062```text
11063const R = require('../../dist/rambda.js')
11064
11065const testObj = {a: 1}
11066
11067const last = [
11068 {
11069 label: 'Rambda',
11070 fn: () => {
11071 R.over(R.lensProp('a'), R.inc, testObj)
11072 },
11073 },
11074 {
11075 label: 'Ramda',
11076 fn: () => {
11077 Ramda.over(Ramda.lensProp('a'), Ramda.inc, testObj)
11078 },
11079 },
11080]
11081```
11082
11083</details>
11084
11085[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#over)
11086
11087### partial
11088
11089```typescript
11090
11091partial<V0, V1, T>(fn: (x0: V0, x1: V1) => T, args: [V0]): (x1: V1) => T
11092```
11093
11094It is very similar to `R.curry`, but you can pass initial arguments when you create the curried function.
11095
11096`R.partial` will keep returning a function until all the arguments that the function `fn` expects are passed.
11097The name comes from the fact that you partially inject the inputs.
11098
11099<details>
11100
11101<summary>All Typescript definitions</summary>
11102
11103```typescript
11104partial<V0, V1, T>(fn: (x0: V0, x1: V1) => T, args: [V0]): (x1: V1) => T;
11105partial<V0, V1, V2, T>(fn: (x0: V0, x1: V1, x2: V2) => T, args: [V0, V1]): (x2: V2) => T;
11106partial<V0, V1, V2, T>(fn: (x0: V0, x1: V1, x2: V2) => T, args: [V0]): (x1: V1, x2: V2) => T;
11107partial<V0, V1, V2, V3, T>(fn: (x0: V0, x1: V1, x2: V2, x3: V3) => T, args: [V0, V1, V2]): (x2: V3) => T;
11108partial<V0, V1, V2, V3, T>(fn: (x0: V0, x1: V1, x2: V2, x3: V3) => T, args: [V0, V1]): (x2: V2, x3: V3) => T;
11109partial<V0, V1, V2, V3, T>(fn: (x0: V0, x1: V1, x2: V2, x3: V3) => T, args: [V0]): (x1: V1, x2: V2, x3: V3) => T;
11110partial<T>(fn: (...a: any[]) => T, args: any[]): (...x: any[]) => T;
11111```
11112
11113</details>
11114
11115<details>
11116
11117<summary><strong>R.partial</strong> source</summary>
11118
11119```javascript
11120export function partial(fn, ...args) {
11121 const len = fn.length
11122
11123 return (...rest) => {
11124 if (args.length + rest.length >= len) {
11125 return fn(...args, ...rest)
11126 }
11127
11128 return partial(fn, ...[...args, ...rest])
11129 }
11130}
11131```
11132
11133</details>
11134
11135<details>
11136
11137<summary><strong>Tests</strong></summary>
11138
11139```javascript
11140import {partial} from './partial'
11141import {type} from './type'
11142
11143const greet = (salutation, title, firstName, lastName) =>
11144 salutation + ', ' + title + ' ' + firstName + ' ' + lastName + '!'
11145
11146test('happy', () => {
11147 const canPassAnyNumberOfArguments = partial(greet, 'Hello', 'Ms.')
11148 const fn = canPassAnyNumberOfArguments('foo')
11149 const sayHello = partial(greet, ['Hello'])
11150 const sayHelloRamda = partial(sayHello, ['Ms.'])
11151
11152 expect(type(fn)).toBe('Function')
11153
11154 expect(fn('bar')).toBe('Hello, Ms. foo bar!')
11155 expect(sayHelloRamda('foo', 'bar')).toBe('Hello, Ms. foo bar!')
11156})
11157
11158test('extra arguments are ignored', () => {
11159 const canPassAnyNumberOfArguments = partial(greet, 'Hello', 'Ms.')
11160 const fn = canPassAnyNumberOfArguments('foo')
11161
11162 expect(type(fn)).toBe('Function')
11163
11164 expect(fn('bar', 1, 2)).toBe('Hello, Ms. foo bar!')
11165})
11166
11167test('when array is input', () => {
11168 const fooFn = (a, b, c, d) => ({
11169 a,
11170 b,
11171 c,
11172 d,
11173 })
11174 const barFn = partial(fooFn, [1, 2], [])
11175
11176 expect(barFn(1, 2)).toEqual({
11177 a: [1, 2],
11178 b: [],
11179 c: 1,
11180 d: 2,
11181 })
11182})
11183
11184test('ramda spec', () => {
11185 const sayHello = partial(greet, 'Hello')
11186 const sayHelloToMs = partial(sayHello, 'Ms.')
11187
11188 expect(sayHelloToMs('Jane', 'Jones')).toBe('Hello, Ms. Jane Jones!')
11189})
11190```
11191
11192</details>
11193
11194<details>
11195
11196<summary><strong>Typescript</strong> test</summary>
11197
11198```typescript
11199import {partial} from 'rambda'
11200
11201describe('R.partial', () => {
11202 it('happy', () => {
11203 function greet(
11204 salutation: string,
11205 title: string,
11206 firstName: string,
11207 lastName: string
11208 ) {
11209 return `${salutation}, ${title} ${firstName} ${lastName}!`
11210 }
11211
11212 const sayHello = partial(greet, ['Hello'])
11213 const sayHelloToMs = partial(sayHello, ['Ms.'])
11214 const result = sayHelloToMs('Jane', 'Jones')
11215 result // $ExpectType string
11216 })
11217})
11218```
11219
11220</details>
11221
11222[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#partial)
11223
11224### partition
11225
11226```typescript
11227
11228partition<T>(
11229 predicate: Predicate<T>,
11230 input: T[]
11231): [T[], T[]]
11232```
11233
11234It will return array of two objects/arrays according to `predicate` function. The first member holds all instances of `input` that pass the `predicate` function, while the second member - those who doesn't.
11235
11236<details>
11237
11238<summary>All Typescript definitions</summary>
11239
11240```typescript
11241partition<T>(
11242 predicate: Predicate<T>,
11243 input: T[]
11244): [T[], T[]];
11245partition<T>(
11246 predicate: Predicate<T>
11247): (input: T[]) => [T[], T[]];
11248partition<T>(
11249 predicate: (x: T, prop?: string) => boolean,
11250 input: { [key: string]: T}
11251): [{ [key: string]: T}, { [key: string]: T}];
11252partition<T>(
11253 predicate: (x: T, prop?: string) => boolean
11254): (input: { [key: string]: T}) => [{ [key: string]: T}, { [key: string]: T}];
11255```
11256
11257</details>
11258
11259<details>
11260
11261<summary><strong>R.partition</strong> source</summary>
11262
11263```javascript
11264import {_isArray} from './_internals/_isArray'
11265
11266export function partitionObject(predicate, iterable) {
11267 const yes = {}
11268 const no = {}
11269 Object.entries(iterable).forEach(([prop, value]) => {
11270 if (predicate(value, prop)) {
11271 yes[prop] = value
11272 } else {
11273 no[prop] = value
11274 }
11275 })
11276
11277 return [yes, no]
11278}
11279
11280export function partitionArray(predicate, list, indexed = false) {
11281 const yes = []
11282 const no = []
11283 let counter = -1
11284
11285 while (counter++ < list.length - 1) {
11286 if (
11287 indexed ? predicate(list[counter], counter) : predicate(list[counter])
11288 ) {
11289 yes.push(list[counter])
11290 } else {
11291 no.push(list[counter])
11292 }
11293 }
11294
11295 return [yes, no]
11296}
11297
11298export function partition(predicate, iterable) {
11299 if (arguments.length === 1) {
11300 return listHolder => partition(predicate, listHolder)
11301 }
11302 if (!_isArray(iterable)) return partitionObject(predicate, iterable)
11303
11304 return partitionArray(predicate, iterable)
11305}
11306```
11307
11308</details>
11309
11310<details>
11311
11312<summary><strong>Tests</strong></summary>
11313
11314```javascript
11315import {partition} from './partition'
11316
11317test('with array', () => {
11318 const predicate = x => x > 2
11319 const list = [1, 2, 3, 4]
11320
11321 const result = partition(predicate, list)
11322 const expectedResult = [
11323 [3, 4],
11324 [1, 2],
11325 ]
11326
11327 expect(result).toEqual(expectedResult)
11328})
11329
11330test('with object', () => {
11331 const predicate = (value, prop) => {
11332 expect(typeof prop).toBe('string')
11333
11334 return value > 2
11335 }
11336 const hash = {
11337 a: 1,
11338 b: 2,
11339 c: 3,
11340 d: 4,
11341 }
11342
11343 const result = partition(predicate)(hash)
11344 const expectedResult = [
11345 {
11346 c: 3,
11347 d: 4,
11348 },
11349 {
11350 a: 1,
11351 b: 2,
11352 },
11353 ]
11354
11355 expect(result).toEqual(expectedResult)
11356})
11357
11358test('readme example', () => {
11359 const list = [1, 2, 3]
11360 const obj = {
11361 a: 1,
11362 b: 2,
11363 c: 3,
11364 }
11365 const predicate = x => x > 2
11366
11367 const result = [partition(predicate, list), partition(predicate, obj)]
11368 const expected = [
11369 [[3], [1, 2]],
11370 [
11371 {c: 3},
11372 {
11373 a: 1,
11374 b: 2,
11375 },
11376 ],
11377 ]
11378 expect(result).toEqual(expected)
11379})
11380```
11381
11382</details>
11383
11384<details>
11385
11386<summary><strong>Typescript</strong> test</summary>
11387
11388```typescript
11389import {partition} from 'rambda'
11390
11391describe('R.partition', () => {
11392 it('with array', () => {
11393 const predicate = (x: number) => {
11394 return x > 2
11395 }
11396 const list = [1, 2, 3, 4]
11397
11398 const result = partition(predicate, list)
11399 const curriedResult = partition(predicate)(list)
11400 result // $ExpectType [number[], number[]]
11401 curriedResult // $ExpectType [number[], number[]]
11402 })
11403
11404 /*
11405 TODO
11406 revert to old version of `dtslint` and `R.partition` typing
11407 as there is diff between VSCode types(correct) and dtslint(incorrect)
11408
11409 it('with object', () => {
11410 const predicate = (value: number, prop?: string) => {
11411 return value > 2
11412 }
11413 const hash = {
11414 a: 1,
11415 b: 2,
11416 c: 3,
11417 d: 4,
11418 }
11419
11420 const result = partition(predicate, hash)
11421 const curriedResult = partition(predicate)(hash)
11422 result[0] // $xExpectType { [key: string]: number; }
11423 result[1] // $xExpectType { [key: string]: number; }
11424 curriedResult[0] // $xExpectType { [key: string]: number; }
11425 curriedResult[1] // $xExpectType { [key: string]: number; }
11426 })
11427 */
11428})
11429```
11430
11431</details>
11432
11433[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#partition)
11434
11435### path
11436
11437```typescript
11438
11439path<Input, T>(pathToSearch: Path, obj: Input): T | undefined
11440```
11441
11442If `pathToSearch` is `'a.b'` then it will return `1` if `obj` is `{a:{b:1}}`.
11443
11444It will return `undefined`, if such path is not found.
11445
11446<details>
11447
11448<summary>All Typescript definitions</summary>
11449
11450```typescript
11451path<Input, T>(pathToSearch: Path, obj: Input): T | undefined;
11452path<T>(pathToSearch: Path, obj: any): T | undefined;
11453path<T>(pathToSearch: Path): (obj: any) => T | undefined;
11454path<Input, T>(pathToSearch: Path): (obj: Input) => T | undefined;
11455```
11456
11457</details>
11458
11459<details>
11460
11461<summary><strong>R.path</strong> source</summary>
11462
11463```javascript
11464export function path(pathInput, obj) {
11465 if (arguments.length === 1) return _obj => path(pathInput, _obj)
11466
11467 if (obj === null || obj === undefined) {
11468 return undefined
11469 }
11470 let willReturn = obj
11471 let counter = 0
11472
11473 const pathArrValue =
11474 typeof pathInput === 'string' ? pathInput.split('.') : pathInput
11475
11476 while (counter < pathArrValue.length) {
11477 if (willReturn === null || willReturn === undefined) {
11478 return undefined
11479 }
11480 if (willReturn[pathArrValue[counter]] === null) return undefined
11481
11482 willReturn = willReturn[pathArrValue[counter]]
11483 counter++
11484 }
11485
11486 return willReturn
11487}
11488```
11489
11490</details>
11491
11492<details>
11493
11494<summary><strong>Tests</strong></summary>
11495
11496```javascript
11497import {path} from './path'
11498
11499test('with array inside object', () => {
11500 const obj = {a: {b: [1, {c: 1}]}}
11501
11502 expect(path('a.b.1.c', obj)).toBe(1)
11503})
11504
11505test('works with undefined', () => {
11506 const obj = {a: {b: {c: 1}}}
11507
11508 expect(path('a.b.c.d.f', obj)).toBeUndefined()
11509 expect(path('foo.babaz', undefined)).toBeUndefined()
11510 expect(path('foo.babaz')(undefined)).toBeUndefined()
11511})
11512
11513test('works with string instead of array', () => {
11514 expect(path('foo.bar.baz')({foo: {bar: {baz: 'yes'}}})).toEqual('yes')
11515})
11516
11517test('path', () => {
11518 expect(path(['foo', 'bar', 'baz'])({foo: {bar: {baz: 'yes'}}})).toEqual(
11519 'yes'
11520 )
11521
11522 expect(path(['foo', 'bar', 'baz'])(null)).toBeUndefined()
11523
11524 expect(path(['foo', 'bar', 'baz'])({foo: {bar: 'baz'}})).toBeUndefined()
11525})
11526
11527test('null is not a valid path', () => {
11528 expect(path('audio_tracks', {a: 1, audio_tracks: null})).toBeUndefined()
11529})
11530```
11531
11532</details>
11533
11534<details>
11535
11536<summary><strong>Typescript</strong> test</summary>
11537
11538```typescript
11539import {path} from 'rambda'
11540
11541interface Input {
11542 a: number,
11543 b: {
11544 c: boolean,
11545 },
11546}
11547
11548describe('R.path', () => {
11549 it('without specified input type', () => {
11550 const input = {a: 1, b: {c: true}}
11551 const result = path<boolean>('a.b.c', input)
11552 const curriedResult = path<boolean>('a.b.c')(input)
11553 result // $ExpectType boolean | undefined
11554 curriedResult // $ExpectType boolean | undefined
11555 })
11556
11557 it('without specified output type', () => {
11558 const input = {a: 1, b: {c: true}}
11559 const result = path('a.b.c', input)
11560 result // $ExpectType unknown
11561 })
11562
11563 it('with string as path', () => {
11564 const input: Input = {a: 1, b: {c: true}}
11565 const resultA = path<boolean>('a.b.c', input)
11566 const resultB = path<boolean>('a.b.c')(input)
11567 resultA // $ExpectType boolean | undefined
11568 resultB // $ExpectType boolean | undefined
11569 })
11570 it('with array as path', () => {
11571 const input: Input = {a: 1, b: {c: true}}
11572 const resultA = path<boolean>(['a', 'b', 'c'], input)
11573 const resultB = path<boolean>(['a', 'b', 'c'])(input)
11574 resultA // $ExpectType boolean | undefined
11575 resultB // $ExpectType boolean | undefined
11576 })
11577})
11578
11579describe('path with specified input', () => {
11580 it('with string as path', () => {
11581 const input: Input = {a: 1, b: {c: true}}
11582 // const wrongInput = { a: 1, b: true }
11583 // const resultA = path<Input, boolean>('a.b.c', wrongInput)
11584 const resultA = path<Input, boolean>('a.b.c', input)
11585 const resultB = path<Input, boolean>('a.b.c')(input)
11586 resultA // $ExpectType boolean | undefined
11587 resultB // $ExpectType boolean | undefined
11588 })
11589 it('with array as path', () => {
11590 const input: Input = {a: 1, b: {c: true}}
11591 const resultA = path<Input, boolean>(['a', 'b', 'c'], input)
11592 const resultB = path<Input, boolean>(['a', 'b', 'c'])(input)
11593 resultA // $ExpectType boolean | undefined
11594 resultB // $ExpectType boolean | undefined
11595 })
11596})
11597```
11598
11599</details>
11600
11601<details>
11602
11603<summary>Lodash is fastest. Rambda is 37.81% slower and Ramda is 77.81% slower</summary>
11604
11605```text
11606const R = require('../../dist/rambda.js')
11607
11608const obj = {a: {b: 2}}
11609const pathInput = ['a', 'b']
11610
11611const path = [
11612 {
11613 label: 'Rambda',
11614 fn: () => {
11615 R.path(pathInput, obj)
11616 },
11617 },
11618 {
11619 label: 'Ramda',
11620 fn: () => {
11621 Ramda.path(pathInput, obj)
11622 },
11623 },
11624 {
11625 label: 'Lodash',
11626 fn: () => {
11627 _.get(obj, pathInput)
11628 },
11629 },
11630]
11631```
11632
11633</details>
11634
11635[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#path)
11636
11637### pathEq
11638
11639```typescript
11640
11641pathEq(pathToSearch: Path, target: any, input: any): boolean
11642```
11643
11644It returns `true` if `pathToSearch` of `input` object is equal to `target` value.
11645
11646`pathToSearch` is passed to `R.path`, which means that it can be either a string or an array. Also equality between `target` and the found value is determined by `R.equals`.
11647
11648<details>
11649
11650<summary>All Typescript definitions</summary>
11651
11652```typescript
11653pathEq(pathToSearch: Path, target: any, input: any): boolean;
11654pathEq(pathToSearch: Path, target: any): (input: any) => boolean;
11655pathEq(pathToSearch: Path): (target: any) => (input: any) => boolean;
11656```
11657
11658</details>
11659
11660<details>
11661
11662<summary><strong>R.pathEq</strong> source</summary>
11663
11664```javascript
11665import {curry} from './curry'
11666import {equals} from './equals'
11667import {path} from './path'
11668
11669function pathEqFn(pathToSearch, target, input) {
11670 return equals(path(pathToSearch, input), target)
11671}
11672
11673export const pathEq = curry(pathEqFn)
11674```
11675
11676</details>
11677
11678<details>
11679
11680<summary><strong>Tests</strong></summary>
11681
11682```javascript
11683import {pathEq} from './pathEq'
11684
11685test('when true', () => {
11686 const path = 'a.b'
11687 const obj = {a: {b: {c: 1}}}
11688 const target = {c: 1}
11689
11690 expect(pathEq(path, target, obj)).toBeTrue()
11691})
11692
11693test('when false', () => {
11694 const path = 'a.b'
11695 const obj = {a: {b: 1}}
11696 const target = 2
11697
11698 expect(pathEq(path, target)(obj)).toBeFalse()
11699})
11700
11701test('when wrong path', () => {
11702 const path = 'foo.bar'
11703 const obj = {a: {b: 1}}
11704 const target = 2
11705
11706 expect(pathEq(path, target, obj)).toBeFalse()
11707})
11708```
11709
11710</details>
11711
11712<details>
11713
11714<summary><strong>Typescript</strong> test</summary>
11715
11716```typescript
11717import {pathEq} from 'rambda'
11718
11719describe('R.pathEq', () => {
11720 it('with string path', () => {
11721 const pathToSearch = 'a.b.c'
11722 const input = {a: {b: {c: 1}}}
11723 const target = {c: 1}
11724
11725 const result = pathEq(pathToSearch, input, target)
11726 const curriedResult = pathEq(pathToSearch, input, target)
11727 result // $ExpectType boolean
11728 curriedResult // $ExpectType boolean
11729 })
11730
11731 it('with array path', () => {
11732 const pathToSearch = ['a', 'b', 'c']
11733 const input = {a: {b: {c: 1}}}
11734 const target = {c: 1}
11735
11736 const result = pathEq(pathToSearch, input, target)
11737 const curriedResult = pathEq(pathToSearch, input, target)
11738 result // $ExpectType boolean
11739 curriedResult // $ExpectType boolean
11740 })
11741})
11742
11743describe('with ramda specs', () => {
11744 const testPath = ['x', 0, 'y']
11745 const testObj = {
11746 x: [
11747 {y: 2, z: 3},
11748 {y: 4, z: 5},
11749 ],
11750 }
11751
11752 const result1 = pathEq(testPath, 2, testObj)
11753 const result2 = pathEq(testPath, 2)(testObj)
11754 const result3 = pathEq(testPath)(2)(testObj)
11755 result1 // $ExpectType boolean
11756 result2 // $ExpectType boolean
11757 result3 // $ExpectType boolean
11758})
11759```
11760
11761</details>
11762
11763[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#pathEq)
11764
11765### pathOr
11766
11767```typescript
11768
11769pathOr<T>(defaultValue: T, pathToSearch: Path, obj: any): T
11770```
11771
11772It reads `obj` input and returns either `R.path(pathToSearch, obj)` result or `defaultValue` input.
11773
11774<details>
11775
11776<summary>All Typescript definitions</summary>
11777
11778```typescript
11779pathOr<T>(defaultValue: T, pathToSearch: Path, obj: any): T;
11780pathOr<T>(defaultValue: T, pathToSearch: Path): (obj: any) => T;
11781pathOr<T>(defaultValue: T): (pathToSearch: Path) => (obj: any) => T;
11782```
11783
11784</details>
11785
11786<details>
11787
11788<summary><strong>R.pathOr</strong> source</summary>
11789
11790```javascript
11791import {curry} from './curry'
11792import {defaultTo} from './defaultTo'
11793import {path} from './path'
11794
11795function pathOrFn(defaultValue, pathInput, obj) {
11796 return defaultTo(defaultValue, path(pathInput, obj))
11797}
11798
11799export const pathOr = curry(pathOrFn)
11800```
11801
11802</details>
11803
11804<details>
11805
11806<summary><strong>Tests</strong></summary>
11807
11808```javascript
11809import {pathOr} from './pathOr'
11810
11811test('with undefined', () => {
11812 const result = pathOr('foo', 'x.y', {x: {y: 1}})
11813
11814 expect(result).toEqual(1)
11815})
11816
11817test('with null', () => {
11818 const result = pathOr('foo', 'x.y', null)
11819
11820 expect(result).toEqual('foo')
11821})
11822
11823test('with NaN', () => {
11824 const result = pathOr('foo', 'x.y', NaN)
11825
11826 expect(result).toEqual('foo')
11827})
11828
11829test('curry case (x)(y)(z)', () => {
11830 const result = pathOr('foo')('x.y.z')({x: {y: {a: 1}}})
11831
11832 expect(result).toEqual('foo')
11833})
11834
11835test('curry case (x)(y,z)', () => {
11836 const result = pathOr('foo', 'x.y.z')({x: {y: {a: 1}}})
11837
11838 expect(result).toEqual('foo')
11839})
11840
11841test('curry case (x,y)(z)', () => {
11842 const result = pathOr('foo')('x.y.z', {x: {y: {a: 1}}})
11843
11844 expect(result).toEqual('foo')
11845})
11846```
11847
11848</details>
11849
11850<details>
11851
11852<summary><strong>Typescript</strong> test</summary>
11853
11854```typescript
11855import {pathOr} from 'rambda'
11856
11857describe('R.pathOr', () => {
11858 it('with string path', () => {
11859 const x = pathOr<string>('foo', 'x.y', {x: {y: 'bar'}})
11860 x // $ExpectType string
11861 })
11862 it('with array path', () => {
11863 const x = pathOr<string>('foo', ['x', 'y'], {x: {y: 'bar'}})
11864 x // $ExpectType string
11865 })
11866 it('without passing type looks bad', () => {
11867 const x = pathOr('foo', 'x.y', {x: {y: 'bar'}})
11868 x // $ExpectType "foo"
11869 })
11870 it('curried', () => {
11871 const x = pathOr<string>('foo', 'x.y')({x: {y: 'bar'}})
11872 x // $ExpectType string
11873 })
11874})
11875```
11876
11877</details>
11878
11879[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#pathOr)
11880
11881### paths
11882
11883```typescript
11884
11885paths<Input, T>(pathsToSearch: Path[], obj: Input): (T | undefined)[]
11886```
11887
11888It loops over members of `pathsToSearch` as `singlePath` and returns the array produced by `R.path(singlePath, obj)`.
11889
11890Because it calls `R.path`, then `singlePath` can be either string or a list.
11891
11892<details>
11893
11894<summary>All Typescript definitions</summary>
11895
11896```typescript
11897paths<Input, T>(pathsToSearch: Path[], obj: Input): (T | undefined)[];
11898paths<Input, T>(pathsToSearch: Path[]): (obj: Input) => (T | undefined)[];
11899paths<T>(pathsToSearch: Path[], obj: any): (T | undefined)[];
11900paths<T>(pathsToSearch: Path[]): (obj: any) => (T | undefined)[];
11901```
11902
11903</details>
11904
11905<details>
11906
11907<summary><strong>R.paths</strong> source</summary>
11908
11909```javascript
11910import {path} from './path'
11911
11912export function paths(pathsToSearch, obj) {
11913 if (arguments.length === 1) {
11914 return _obj => paths(pathsToSearch, _obj)
11915 }
11916
11917 return pathsToSearch.map(singlePath => path(singlePath, obj))
11918}
11919```
11920
11921</details>
11922
11923<details>
11924
11925<summary><strong>Tests</strong></summary>
11926
11927```javascript
11928import {paths} from './paths'
11929
11930const obj = {
11931 a: {
11932 b: {
11933 c: 1,
11934 d: 2,
11935 },
11936 },
11937 p: [{q: 3}],
11938 x: {
11939 y: 'FOO',
11940 z: [[{}]],
11941 },
11942}
11943
11944test('with string path + curry', () => {
11945 const pathsInput = ['a.b.d', 'p.q']
11946 const expected = [2, undefined]
11947 const result = paths(pathsInput, obj)
11948 const curriedResult = paths(pathsInput)(obj)
11949
11950 expect(result).toEqual(expected)
11951 expect(curriedResult).toEqual(expected)
11952})
11953
11954test('with array path', () => {
11955 const result = paths(
11956 [
11957 ['a', 'b', 'c'],
11958 ['x', 'y'],
11959 ],
11960 obj
11961 )
11962
11963 expect(result).toEqual([1, 'FOO'])
11964})
11965
11966test('takes a paths that contains indices into arrays', () => {
11967 expect(
11968 paths(
11969 [
11970 ['p', 0, 'q'],
11971 ['x', 'z', 0, 0],
11972 ],
11973 obj
11974 )
11975 ).toEqual([3, {}])
11976 expect(
11977 paths(
11978 [
11979 ['p', 0, 'q'],
11980 ['x', 'z', 2, 1],
11981 ],
11982 obj
11983 )
11984 ).toEqual([3, undefined])
11985})
11986
11987test("gets a deep property's value from objects", () => {
11988 expect(paths([['a', 'b']], obj)).toEqual([obj.a.b])
11989 expect(paths([['p', 0]], obj)).toEqual([obj.p[0]])
11990})
11991
11992test('returns undefined for items not found', () => {
11993 expect(paths([['a', 'x', 'y']], obj)).toEqual([undefined])
11994 expect(paths([['p', 2]], obj)).toEqual([undefined])
11995})
11996```
11997
11998</details>
11999
12000<details>
12001
12002<summary><strong>Typescript</strong> test</summary>
12003
12004```typescript
12005import {paths} from 'rambda'
12006
12007interface Input {
12008 a: number,
12009 b: number,
12010 c: number,
12011}
12012
12013const input: Input = {a: 1, b: 2, c: 3}
12014
12015describe('R.paths', () => {
12016 it('with dot notation', () => {
12017 const result = paths<number>(['a.b.c', 'foo.bar'], input)
12018 result // $ExpectType (number | undefined)[]
12019 })
12020
12021 it('without type', () => {
12022 const result = paths(['a.b.c', 'foo.bar'], input)
12023 result // $ExpectType unknown[]
12024 })
12025
12026 it('with array as path', () => {
12027 const result = paths<number>([['a', 'b', 'c'], ['foo.bar']], input)
12028 result // $ExpectType (number | undefined)[]
12029 })
12030
12031 it('curried', () => {
12032 const result = paths<number>([['a', 'b', 'c'], ['foo.bar']])(input)
12033 result // $ExpectType (number | undefined)[]
12034 })
12035})
12036```
12037
12038</details>
12039
12040[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#paths)
12041
12042### pick
12043
12044```typescript
12045
12046pick<T, K extends string | number | symbol>(propsToPick: K[], input: T): Pick<T, Exclude<keyof T, Exclude<keyof T, K>>>
12047```
12048
12049It returns a partial copy of an `input` containing only `propsToPick` properties.
12050
12051`input` can be either an object or an array.
12052
12053String anotation of `propsToPick` is one of the differences between `Rambda` and `Ramda`.
12054
12055<details>
12056
12057<summary>All Typescript definitions</summary>
12058
12059```typescript
12060pick<T, K extends string | number | symbol>(propsToPick: K[], input: T): Pick<T, Exclude<keyof T, Exclude<keyof T, K>>>;
12061pick<K extends string | number | symbol>(propsToPick: K[]): <T>(input: T) => Pick<T, Exclude<keyof T, Exclude<keyof T, K>>>;
12062pick<T, U>(propsToPick: string, input: T): U;
12063pick<T, U>(propsToPick: string): (input: T) => U;
12064pick<T>(propsToPick: string, input: object): T;
12065pick<T>(propsToPick: string): (input: object) => T;
12066```
12067
12068</details>
12069
12070<details>
12071
12072<summary><strong>R.pick</strong> source</summary>
12073
12074```javascript
12075export function pick(propsToPick, input) {
12076 if (arguments.length === 1) return _input => pick(propsToPick, _input)
12077
12078 if (input === null || input === undefined) {
12079 return undefined
12080 }
12081 const keys =
12082 typeof propsToPick === 'string' ? propsToPick.split(',') : propsToPick
12083
12084 const willReturn = {}
12085 let counter = 0
12086
12087 while (counter < keys.length) {
12088 if (keys[counter] in input) {
12089 willReturn[keys[counter]] = input[keys[counter]]
12090 }
12091 counter++
12092 }
12093
12094 return willReturn
12095}
12096```
12097
12098</details>
12099
12100<details>
12101
12102<summary><strong>Tests</strong></summary>
12103
12104```javascript
12105import {pick} from './pick'
12106
12107const obj = {
12108 a: 1,
12109 b: 2,
12110 c: 3,
12111}
12112
12113test('props to pick is a string', () => {
12114 const result = pick('a,c', obj)
12115 const resultCurry = pick('a,c')(obj)
12116 const expectedResult = {
12117 a: 1,
12118 c: 3,
12119 }
12120
12121 expect(result).toEqual(expectedResult)
12122 expect(resultCurry).toEqual(expectedResult)
12123})
12124
12125test('when prop is missing', () => {
12126 const result = pick('a,d,f', obj)
12127 expect(result).toEqual({a: 1})
12128})
12129
12130test('props to pick is an array', () => {
12131 expect(
12132 pick(['a', 'c'])({
12133 a: 'foo',
12134 b: 'bar',
12135 c: 'baz',
12136 })
12137 ).toEqual({
12138 a: 'foo',
12139 c: 'baz',
12140 })
12141
12142 expect(
12143 pick(['a', 'd', 'e', 'f'])({
12144 a: 'foo',
12145 b: 'bar',
12146 c: 'baz',
12147 })
12148 ).toEqual({a: 'foo'})
12149
12150 expect(pick('a,d,e,f')(null)).toEqual(undefined)
12151})
12152
12153test('works with list as input and number as props - props to pick is an array', () => {
12154 const result = pick([1, 2], ['a', 'b', 'c', 'd'])
12155 expect(result).toEqual({
12156 1: 'b',
12157 2: 'c',
12158 })
12159})
12160
12161test('works with list as input and number as props - props to pick is a string', () => {
12162 const result = pick('1,2', ['a', 'b', 'c', 'd'])
12163 expect(result).toEqual({
12164 1: 'b',
12165 2: 'c',
12166 })
12167})
12168
12169test('with symbol', () => {
12170 const symbolProp = Symbol('s')
12171 expect(pick([symbolProp], {[symbolProp]: 'a'})).toMatchInlineSnapshot(`
12172 Object {
12173 Symbol(s): "a",
12174 }
12175 `)
12176})
12177```
12178
12179</details>
12180
12181<details>
12182
12183<summary><strong>Typescript</strong> test</summary>
12184
12185```typescript
12186import {pick} from 'rambda'
12187
12188const input = {a: 'foo', b: 2, c: 3, d: 4}
12189
12190describe('R.pick with array as props input', () => {
12191 it('without passing type', () => {
12192 const result = pick(['a', 'c'], input)
12193 result.a // $ExpectType string
12194 result.c // $ExpectType number
12195 })
12196})
12197
12198describe('R.pick with string as props input', () => {
12199 interface Input {
12200 a: string,
12201 b: number,
12202 c: number,
12203 d: number,
12204 }
12205 interface Output {
12206 a: string,
12207 c: number,
12208 }
12209 it('explicitly declare output', () => {
12210 const result = pick<Output>('a,c', input)
12211 result // $ExpectType Output
12212 result.a // $ExpectType string
12213 result.c // $ExpectType number
12214
12215 const curriedResult = pick<Output>('a,c')(input)
12216
12217 curriedResult.a // $ExpectType string
12218 })
12219
12220 it('explicitly declare input and output', () => {
12221 const result = pick<Input, Output>('a,c', input)
12222 result // $ExpectType Output
12223 result.a // $ExpectType string
12224
12225 const curriedResult = pick<Input, Output>('a,c')(input)
12226
12227 curriedResult.a // $ExpectType string
12228 })
12229
12230 it('without passing type', () => {
12231 const result = pick('a,c', input)
12232 result // $ExpectType unknown
12233 })
12234})
12235```
12236
12237</details>
12238
12239<details>
12240
12241<summary>Rambda is fastest. Ramda is 19.07% slower and Lodash is 80.2% slower</summary>
12242
12243```text
12244const R = require('../../dist/rambda.js')
12245
12246const obj = {
12247 a: 'foo',
12248 b: 'bar',
12249 c: 'baz',
12250}
12251const pickInput = ['a', 'c']
12252const pick = [
12253 {
12254 label: 'Rambda',
12255 fn: () => {
12256 R.pick(pickInput, obj)
12257 },
12258 },
12259 {
12260 label: 'Ramda',
12261 fn: () => {
12262 Ramda.pick(pickInput, obj)
12263 },
12264 },
12265 {
12266 label: 'Lodash',
12267 fn: () => {
12268 _.pick(obj, pickInput)
12269 },
12270 },
12271]
12272```
12273
12274</details>
12275
12276[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#pick)
12277
12278### pickAll
12279
12280```typescript
12281
12282pickAll<T, U>(propsToPick: string[], input: T): U
12283```
12284
12285Same as `R.pick` but it won't skip the missing props, i.e. it will assign them to `undefined`.
12286
12287<details>
12288
12289<summary>All Typescript definitions</summary>
12290
12291```typescript
12292pickAll<T, U>(propsToPick: string[], input: T): U;
12293pickAll<T, U>(propsToPick: string[]): (input: T) => U;
12294pickAll<T, U>(propsToPick: string, input: T): U;
12295pickAll<T, U>(propsToPick: string): (input: T) => U;
12296```
12297
12298</details>
12299
12300<details>
12301
12302<summary><strong>R.pickAll</strong> source</summary>
12303
12304```javascript
12305export function pickAll(propsToPick, obj) {
12306 if (arguments.length === 1) return _obj => pickAll(propsToPick, _obj)
12307
12308 if (obj === null || obj === undefined) {
12309 return undefined
12310 }
12311 const keysValue =
12312 typeof propsToPick === 'string' ? propsToPick.split(',') : propsToPick
12313
12314 const willReturn = {}
12315 let counter = 0
12316
12317 while (counter < keysValue.length) {
12318 if (keysValue[counter] in obj) {
12319 willReturn[keysValue[counter]] = obj[keysValue[counter]]
12320 } else {
12321 willReturn[keysValue[counter]] = undefined
12322 }
12323 counter++
12324 }
12325
12326 return willReturn
12327}
12328```
12329
12330</details>
12331
12332<details>
12333
12334<summary><strong>Tests</strong></summary>
12335
12336```javascript
12337import {pickAll} from './pickAll'
12338
12339test('when input is undefined or null', () => {
12340 expect(pickAll('a', null)).toBe(undefined)
12341 expect(pickAll('a', undefined)).toBe(undefined)
12342})
12343
12344test('with string as condition', () => {
12345 const obj = {
12346 a: 1,
12347 b: 2,
12348 c: 3,
12349 }
12350 const result = pickAll('a,c', obj)
12351 const resultCurry = pickAll('a,c')(obj)
12352 const expectedResult = {
12353 a: 1,
12354 b: undefined,
12355 c: 3,
12356 }
12357
12358 expect(result).toEqual(expectedResult)
12359 expect(resultCurry).toEqual(expectedResult)
12360})
12361
12362test('with array as condition', () => {
12363 expect(
12364 pickAll(['a', 'b', 'c'], {
12365 a: 'foo',
12366 c: 'baz',
12367 })
12368 ).toEqual({
12369 a: 'foo',
12370 b: undefined,
12371 c: 'baz',
12372 })
12373})
12374```
12375
12376</details>
12377
12378<details>
12379
12380<summary><strong>Typescript</strong> test</summary>
12381
12382```typescript
12383import {pickAll} from 'rambda'
12384
12385interface Input {
12386 a: string,
12387 b: number,
12388 c: number,
12389 d: number,
12390}
12391interface Output {
12392 a?: string,
12393 c?: number,
12394}
12395const input = {a: 'foo', b: 2, c: 3, d: 4}
12396
12397describe('R.pickAll with array as props input', () => {
12398 it('without passing type', () => {
12399 const result = pickAll(['a', 'c'], input)
12400 result // $ExpectType unknown
12401 })
12402 it('without passing type + curry', () => {
12403 const result = pickAll(['a', 'c'])(input)
12404 result // $ExpectType unknown
12405 })
12406 it('explicitly passing types', () => {
12407 const result = pickAll<Input, Output>(['a', 'c'], input)
12408 result.a // $ExpectType string | undefined
12409 result.c // $ExpectType number | undefined
12410 })
12411 it('explicitly passing types + curry', () => {
12412 const result = pickAll<Input, Output>(['a', 'c'])(input)
12413 result.a // $ExpectType string | undefined
12414 result.c // $ExpectType number | undefined
12415 })
12416})
12417
12418describe('R.pickAll with string as props input', () => {
12419 it('without passing type', () => {
12420 const result = pickAll('a,c', input)
12421 result // $ExpectType unknown
12422 })
12423 it('without passing type + curry', () => {
12424 const result = pickAll('a,c')(input)
12425 result // $ExpectType unknown
12426 })
12427 it('explicitly passing types', () => {
12428 const result = pickAll<Input, Output>('a,c', input)
12429 result.a // $ExpectType string | undefined
12430 result.c // $ExpectType number | undefined
12431 })
12432 it('explicitly passing types + curry', () => {
12433 const result = pickAll<Input, Output>('a,c')(input)
12434 result.a // $ExpectType string | undefined
12435 result.c // $ExpectType number | undefined
12436 })
12437})
12438```
12439
12440</details>
12441
12442[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#pickAll)
12443
12444### pipe
12445
12446It performs left-to-right function composition.
12447
12448[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#pipe)
12449
12450### pluck
12451
12452```typescript
12453
12454pluck<K extends keyof T, T>(property: K, list: T[]): T[K][]
12455```
12456
12457It returns list of the values of `property` taken from the all objects inside `list`.
12458
12459<details>
12460
12461<summary>All Typescript definitions</summary>
12462
12463```typescript
12464pluck<K extends keyof T, T>(property: K, list: T[]): T[K][];
12465pluck<T>(property: number, list: { [k: number]: T }[]): T[];
12466pluck<P extends string>(property: P): <T>(list: Record<P, T>[]) => T[];
12467pluck(property: number): <T>(list: { [k: number]: T }[]) => T[];
12468```
12469
12470</details>
12471
12472<details>
12473
12474<summary><strong>R.pluck</strong> source</summary>
12475
12476```javascript
12477import {map} from './map'
12478
12479export function pluck(property, list) {
12480 if (arguments.length === 1) return _list => pluck(property, _list)
12481
12482 const willReturn = []
12483
12484 map(x => {
12485 if (x[property] !== undefined) {
12486 willReturn.push(x[property])
12487 }
12488 }, list)
12489
12490 return willReturn
12491}
12492```
12493
12494</details>
12495
12496<details>
12497
12498<summary><strong>Tests</strong></summary>
12499
12500```javascript
12501import {pluck} from './pluck'
12502
12503test('happy', () => {
12504 expect(pluck('a')([{a: 1}, {a: 2}, {b: 1}])).toEqual([1, 2])
12505})
12506
12507test('with number', () => {
12508 const input = [
12509 [1, 2],
12510 [3, 4],
12511 ]
12512
12513 expect(pluck(0, input)).toEqual([1, 3])
12514})
12515```
12516
12517</details>
12518
12519<details>
12520
12521<summary><strong>Typescript</strong> test</summary>
12522
12523```typescript
12524import {pluck} from 'rambda'
12525
12526describe('R.pluck', () => {
12527 it('with object', () => {
12528 interface ListMember {
12529 a: number,
12530 b: string,
12531 }
12532 const input: ListMember[] = [
12533 {a: 1, b: 'foo'},
12534 {a: 2, b: 'bar'},
12535 ]
12536 const resultA = pluck('a', input)
12537 const resultB = pluck('b')(input)
12538 resultA // $ExpectType number[]
12539 resultB // $ExpectType string[]
12540 })
12541
12542 it('with array', () => {
12543 const input = [
12544 [1, 2],
12545 [3, 4],
12546 [5, 6],
12547 ]
12548 const result = pluck(0, input)
12549 const resultCurry = pluck(0)(input)
12550 result // $ExpectType number[]
12551 resultCurry // $ExpectType number[]
12552 })
12553})
12554```
12555
12556</details>
12557
12558[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#pluck)
12559
12560### prepend
12561
12562```typescript
12563
12564prepend<T>(x: T, input: T[]): T[]
12565```
12566
12567It adds element `x` at the beginning of `list`.
12568
12569<details>
12570
12571<summary>All Typescript definitions</summary>
12572
12573```typescript
12574prepend<T>(x: T, input: T[]): T[];
12575prepend<T>(x: T): (input: T[]) => T[];
12576```
12577
12578</details>
12579
12580<details>
12581
12582<summary><strong>R.prepend</strong> source</summary>
12583
12584```javascript
12585export function prepend(x, input) {
12586 if (arguments.length === 1) return _input => prepend(x, _input)
12587
12588 if (typeof input === 'string') return [x].concat(input.split(''))
12589
12590 return [x].concat(input)
12591}
12592```
12593
12594</details>
12595
12596<details>
12597
12598<summary><strong>Tests</strong></summary>
12599
12600```javascript
12601import {prepend} from './prepend'
12602
12603test('happy', () => {
12604 expect(prepend('yes', ['foo', 'bar', 'baz'])).toEqual([
12605 'yes',
12606 'foo',
12607 'bar',
12608 'baz',
12609 ])
12610})
12611
12612test('with empty list', () => {
12613 expect(prepend('foo')([])).toEqual(['foo'])
12614})
12615
12616test('with string instead of array', () => {
12617 expect(prepend('foo')('bar')).toEqual(['foo', 'b', 'a', 'r'])
12618})
12619```
12620
12621</details>
12622
12623<details>
12624
12625<summary><strong>Typescript</strong> test</summary>
12626
12627```typescript
12628import {prepend} from 'rambda'
12629
12630const list = [1, 2, 3]
12631
12632describe('R.prepend', () => {
12633 it('happy', () => {
12634 const result = prepend(4, list)
12635
12636 result // $ExpectType number[]
12637 })
12638 it('curried', () => {
12639 const result = prepend(4)(list)
12640
12641 result // $ExpectType number[]
12642 })
12643})
12644```
12645
12646</details>
12647
12648[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#prepend)
12649
12650### product
12651
12652```typescript
12653
12654product(list: number[]): number
12655```
12656
12657<details>
12658
12659<summary>All Typescript definitions</summary>
12660
12661```typescript
12662product(list: number[]): number;
12663```
12664
12665</details>
12666
12667<details>
12668
12669<summary><strong>R.product</strong> source</summary>
12670
12671```javascript
12672import {multiply} from './multiply'
12673import {reduce} from './reduce'
12674
12675export const product = reduce(multiply, 1)
12676```
12677
12678</details>
12679
12680<details>
12681
12682<summary><strong>Tests</strong></summary>
12683
12684```javascript
12685import {product} from './product'
12686
12687test('happy', () => {
12688 expect(product([2, 3, 4])).toEqual(24)
12689})
12690
12691test('bad input', () => {
12692 expect(product([null])).toEqual(0)
12693 expect(product([])).toEqual(1)
12694})
12695```
12696
12697</details>
12698
12699<details>
12700
12701<summary><strong>Typescript</strong> test</summary>
12702
12703```typescript
12704import {product} from 'rambda'
12705
12706describe('R.product', () => {
12707 it('happy', () => {
12708 const result = product([1, 2, 3])
12709
12710 result // $ExpectType number
12711 })
12712})
12713```
12714
12715</details>
12716
12717[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#product)
12718
12719### prop
12720
12721```typescript
12722
12723prop<P extends keyof T, T>(propToFind: P, obj: T): T[P]
12724```
12725
12726It returns the value of property `propToFind` in `obj`.
12727
12728If there is no such property, it returns `undefined`.
12729
12730<details>
12731
12732<summary>All Typescript definitions</summary>
12733
12734```typescript
12735prop<P extends keyof T, T>(propToFind: P, obj: T): T[P];
12736prop<P extends string | number>(p: P): <T>(propToFind: Record<P, T>) => T;
12737prop<P extends keyof T, T>(p: P): (propToFind: Record<P, T>) => T;
12738```
12739
12740</details>
12741
12742<details>
12743
12744<summary><strong>R.prop</strong> source</summary>
12745
12746```javascript
12747export function prop(propToFind, obj) {
12748 if (arguments.length === 1) return _obj => prop(propToFind, _obj)
12749
12750 if (!obj) return undefined
12751
12752 return obj[propToFind]
12753}
12754```
12755
12756</details>
12757
12758<details>
12759
12760<summary><strong>Tests</strong></summary>
12761
12762```javascript
12763import {prop} from './prop'
12764
12765test('prop', () => {
12766 expect(prop('foo')({foo: 'baz'})).toEqual('baz')
12767
12768 expect(prop('bar')({foo: 'baz'})).toEqual(undefined)
12769
12770 expect(prop('bar')(null)).toEqual(undefined)
12771})
12772```
12773
12774</details>
12775
12776<details>
12777
12778<summary><strong>Typescript</strong> test</summary>
12779
12780```typescript
12781import {prop} from 'rambda'
12782
12783const obj = {a: 1, b: 'foo'}
12784
12785describe('R.prop', () => {
12786 it('issue #553', () => {
12787 const result = prop('e', {e: 'test1', d: 'test2'})
12788 const curriedResult = prop<string>('e')({e: 'test1', d: 'test2'})
12789
12790 result // $ExpectType string
12791 curriedResult // $ExpectType string
12792 })
12793 it('happy', () => {
12794 const result = prop('a', obj)
12795
12796 result // $ExpectType number
12797 })
12798 it('curried', () => {
12799 const result = prop('b')(obj)
12800
12801 result // $ExpectType string
12802 })
12803})
12804
12805describe('with number as prop', () => {
12806 const list = [1, 2, 3]
12807 const index = 1
12808 it('happy', () => {
12809 const result = prop(index, list)
12810
12811 result // $ExpectType number
12812 })
12813 it('curried require explicit type', () => {
12814 const result = prop<number>(index)(list)
12815
12816 result // $ExpectType number
12817 })
12818})
12819```
12820
12821</details>
12822
12823<details>
12824
12825<summary>Rambda is faster than Ramda with 87.95%</summary>
12826
12827```text
12828const R = require('../../dist/rambda.js')
12829
12830const obj = {
12831 a: {c: 2},
12832 b: 1,
12833}
12834const propInput = 'b'
12835
12836const prop = [
12837 {
12838 label: 'Rambda',
12839 fn: () => {
12840 R.prop(propInput, obj)
12841 R.prop(propInput)(obj)
12842 },
12843 },
12844 {
12845 label: 'Ramda',
12846 fn: () => {
12847 Ramda.prop(propInput, obj)
12848 Ramda.prop(propInput)(obj)
12849 },
12850 },
12851]
12852```
12853
12854</details>
12855
12856[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#prop)
12857
12858### propEq
12859
12860```typescript
12861
12862propEq<K extends string | number>(propToFind: K, valueToMatch: any, obj: Record<K, any>): boolean
12863```
12864
12865It returns true if `obj` has property `propToFind` and its value is equal to `valueToMatch`.
12866
12867<details>
12868
12869<summary>All Typescript definitions</summary>
12870
12871```typescript
12872propEq<K extends string | number>(propToFind: K, valueToMatch: any, obj: Record<K, any>): boolean;
12873propEq<K extends string | number>(propToFind: K, valueToMatch: any): (obj: Record<K, any>) => boolean;
12874propEq<K extends string | number>(propToFind: K): {
12875 (valueToMatch: any, obj: Record<K, any>): boolean;
12876 (valueToMatch: any): (obj: Record<K, any>) => boolean;
12877};
12878```
12879
12880</details>
12881
12882<details>
12883
12884<summary><strong>R.propEq</strong> source</summary>
12885
12886```javascript
12887import {curry} from './curry'
12888
12889function propEqFn(propToFind, valueToMatch, obj) {
12890 if (!obj) return false
12891
12892 return obj[propToFind] === valueToMatch
12893}
12894
12895export const propEq = curry(propEqFn)
12896```
12897
12898</details>
12899
12900<details>
12901
12902<summary><strong>Tests</strong></summary>
12903
12904```javascript
12905import {propEq} from './propEq'
12906
12907test('happy', () => {
12908 expect(propEq('foo', 'bar')({foo: 'bar'})).toBeTrue()
12909 expect(propEq('foo', 'bar')({foo: 'baz'})).toBeFalse()
12910 expect(propEq('foo')('bar')({foo: 'baz'})).toBeFalse()
12911 expect(propEq('foo', 'bar', null)).toBeFalse()
12912})
12913```
12914
12915</details>
12916
12917<details>
12918
12919<summary><strong>Typescript</strong> test</summary>
12920
12921```typescript
12922import {propEq} from 'rambda'
12923
12924const property = 'foo'
12925const numberProperty = 1
12926const value = 'bar'
12927const obj = {[property]: value}
12928const objWithNumberIndex = {[numberProperty]: value}
12929
12930describe('R.propEq', () => {
12931 it('happy', () => {
12932 const result = propEq(property, value, obj)
12933 result // $ExpectType boolean
12934 })
12935
12936 it('number is property', () => {
12937 const result = propEq(1, value, objWithNumberIndex)
12938 result // $ExpectType boolean
12939 })
12940
12941 it('with optional property', () => {
12942 interface MyType {
12943 optional?: string | number,
12944 }
12945
12946 const myObject: MyType = {}
12947 const valueToFind = '1111'
12948 // $ExpectError
12949 propEq('optional', valueToFind, myObject)
12950
12951 // $ExpectError
12952 propEq('optional', valueToFind, myObject)
12953 })
12954
12955 it('imported from @types/ramda', () => {
12956 interface A {
12957 foo: string | null,
12958 }
12959 const obj: A = {
12960 foo: 'bar',
12961 }
12962 const value = ''
12963 const result = propEq('foo', value)(obj)
12964 result // $ExpectType boolean
12965
12966 // $ExpectError
12967 propEq('bar', value)(obj)
12968 })
12969})
12970```
12971
12972</details>
12973
12974<details>
12975
12976<summary>Rambda is faster than Ramda with 91.92%</summary>
12977
12978```text
12979const R = require('../../dist/rambda.js')
12980
12981const obj = {
12982 a: {c: 2},
12983 b: 1,
12984}
12985const propInput = 'b'
12986const expected = {c: 2}
12987
12988const propEq = [
12989 {
12990 label: 'Rambda',
12991 fn: () => {
12992 R.propEq('a')(expected)(obj)
12993
12994 R.propEq('a', expected)(obj)
12995
12996 R.propEq('a', expected, obj)
12997 },
12998 },
12999 {
13000 label: 'Ramda',
13001 fn: () => {
13002 Ramda.propEq('a')(expected)(obj)
13003
13004 Ramda.propEq('a', expected)(obj)
13005
13006 Ramda.propEq('a', expected, obj)
13007 },
13008 },
13009]
13010```
13011
13012</details>
13013
13014[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#propEq)
13015
13016### propIs
13017
13018```typescript
13019
13020propIs<C extends (...args: any[]) => any, K extends keyof any>(type: C, name: K, obj: any): obj is Record<K, ReturnType<C>>
13021```
13022
13023It returns `true` if `property` of `obj` is from `target` type.
13024
13025<details>
13026
13027<summary>All Typescript definitions</summary>
13028
13029```typescript
13030propIs<C extends (...args: any[]) => any, K extends keyof any>(type: C, name: K, obj: any): obj is Record<K, ReturnType<C>>;
13031propIs<C extends new (...args: any[]) => any, K extends keyof any>(type: C, name: K, obj: any): obj is Record<K, InstanceType<C>>;
13032propIs<C extends (...args: any[]) => any, K extends keyof any>(type: C, name: K): (obj: any) => obj is Record<K, ReturnType<C>>;
13033propIs<C extends new (...args: any[]) => any, K extends keyof any>(type: C, name: K): (obj: any) => obj is Record<K, InstanceType<C>>;
13034propIs<C extends (...args: any[]) => any>(type: C): {
13035 <K extends keyof any>(name: K, obj: any): obj is Record<K, ReturnType<C>>;
13036 <K extends keyof any>(name: K): (obj: any) => obj is Record<K, ReturnType<C>>;
13037};
13038propIs<C extends new (...args: any[]) => any>(type: C): {
13039 <K extends keyof any>(name: K, obj: any): obj is Record<K, InstanceType<C>>;
13040 <K extends keyof any>(name: K): (obj: any) => obj is Record<K, InstanceType<C>>;
13041};
13042```
13043
13044</details>
13045
13046<details>
13047
13048<summary><strong>R.propIs</strong> source</summary>
13049
13050```javascript
13051import {curry} from './curry'
13052import {is} from './is'
13053
13054function propIsFn(targetPrototype, property, obj) {
13055 return is(targetPrototype, obj[property])
13056}
13057
13058export const propIs = curry(propIsFn)
13059```
13060
13061</details>
13062
13063<details>
13064
13065<summary><strong>Tests</strong></summary>
13066
13067```javascript
13068import {propIs} from './propIs'
13069
13070const obj = {value: 1}
13071const property = 'value'
13072
13073test('when true', () => {
13074 expect(propIs(Number, property, obj)).toBeTrue()
13075})
13076
13077test('when false', () => {
13078 expect(propIs(String, property, obj)).toBeFalse()
13079 expect(propIs(String, property, {})).toBeFalse()
13080})
13081```
13082
13083</details>
13084
13085<details>
13086
13087<summary><strong>Typescript</strong> test</summary>
13088
13089```typescript
13090import {propIs} from 'rambda'
13091
13092const property = 'a'
13093const obj = {a: 1}
13094
13095describe('R.propIs', () => {
13096 it('happy', () => {
13097 const result = propIs(Number, property, obj)
13098 result // $ExpectType boolean
13099 })
13100
13101 it('curried', () => {
13102 const result = propIs(Number, property)(obj)
13103 result // $ExpectType boolean
13104 })
13105})
13106```
13107
13108</details>
13109
13110[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#propIs)
13111
13112### propOr
13113
13114```typescript
13115
13116propOr<T, P extends string>(defaultValue: T, property: P, obj: Partial<Record<P, T>> | undefined): T
13117```
13118
13119It returns either `defaultValue` or the value of `property` in `obj`.
13120
13121<details>
13122
13123<summary>All Typescript definitions</summary>
13124
13125```typescript
13126propOr<T, P extends string>(defaultValue: T, property: P, obj: Partial<Record<P, T>> | undefined): T;
13127propOr<T, P extends string>(defaultValue: T, property: P): (obj: Partial<Record<P, T>> | undefined) => T;
13128propOr<T>(defaultValue: T): {
13129 <P extends string>(property: P, obj: Partial<Record<P, T>> | undefined): T;
13130 <P extends string>(property: P): (obj: Partial<Record<P, T>> | undefined) => T;
13131}
13132```
13133
13134</details>
13135
13136<details>
13137
13138<summary><strong>R.propOr</strong> source</summary>
13139
13140```javascript
13141import {curry} from './curry'
13142import {defaultTo} from './defaultTo'
13143
13144function propOrFn(defaultValue, property, obj) {
13145 if (!obj) return defaultValue
13146
13147 return defaultTo(defaultValue, obj[property])
13148}
13149
13150export const propOr = curry(propOrFn)
13151```
13152
13153</details>
13154
13155<details>
13156
13157<summary><strong>Tests</strong></summary>
13158
13159```javascript
13160import {propOr} from './propOr'
13161
13162test('propOr (result)', () => {
13163 const obj = {a: 1}
13164 expect(propOr('default', 'a', obj)).toEqual(1)
13165 expect(propOr('default', 'notExist', obj)).toEqual('default')
13166 expect(propOr('default', 'notExist', null)).toEqual('default')
13167})
13168
13169test('propOr (currying)', () => {
13170 const obj = {a: 1}
13171 expect(propOr('default')('a', obj)).toEqual(1)
13172 expect(propOr('default', 'a')(obj)).toEqual(1)
13173 expect(propOr('default')('notExist', obj)).toEqual('default')
13174 expect(propOr('default', 'notExist')(obj)).toEqual('default')
13175})
13176```
13177
13178</details>
13179
13180<details>
13181
13182<summary><strong>Typescript</strong> test</summary>
13183
13184```typescript
13185import {propOr} from 'rambda'
13186
13187const obj = {foo: 'bar'}
13188const property = 'foo'
13189const fallback = 'fallback'
13190
13191describe('R.propOr', () => {
13192 it('happy', () => {
13193 const result = propOr(fallback, property, obj)
13194 result // $ExpectType string
13195 })
13196 it('curry 1', () => {
13197 const result = propOr(fallback)(property, obj)
13198 result // $ExpectType string
13199 })
13200 it('curry 2', () => {
13201 const result = propOr(fallback, property)(obj)
13202 result // $ExpectType string
13203 })
13204 it('curry 3', () => {
13205 const result = propOr(fallback)(property)(obj)
13206 result // $ExpectType string
13207 })
13208})
13209```
13210
13211</details>
13212
13213[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#propOr)
13214
13215### props
13216
13217```typescript
13218
13219props<P extends string, T>(propsToPick: P[], obj: Record<P, T>): T[]
13220```
13221
13222It takes list with properties `propsToPick` and returns a list with property values in `obj`.
13223
13224<details>
13225
13226<summary>All Typescript definitions</summary>
13227
13228```typescript
13229props<P extends string, T>(propsToPick: P[], obj: Record<P, T>): T[];
13230props<P extends string>(propsToPick: P[]): <T>(obj: Record<P, T>) => T[];
13231props<P extends string, T>(propsToPick: P[]): (obj: Record<P, T>) => T[];
13232```
13233
13234</details>
13235
13236<details>
13237
13238<summary><strong>R.props</strong> source</summary>
13239
13240```javascript
13241import {_isArray} from './_internals/_isArray'
13242import {mapArray} from './map'
13243
13244export function props(propsToPick, obj) {
13245 if (arguments.length === 1) {
13246 return _obj => props(propsToPick, _obj)
13247 }
13248 if (!_isArray(propsToPick)) {
13249 throw new Error('propsToPick is not a list')
13250 }
13251
13252 return mapArray(prop => obj[prop], propsToPick)
13253}
13254```
13255
13256</details>
13257
13258<details>
13259
13260<summary><strong>Tests</strong></summary>
13261
13262```javascript
13263import {props} from './props'
13264
13265const obj = {
13266 a: 1,
13267 b: 2,
13268}
13269const propsToPick = ['a', 'c']
13270
13271test('happy', () => {
13272 const result = props(propsToPick, obj)
13273 expect(result).toEqual([1, undefined])
13274})
13275
13276test('curried', () => {
13277 const result = props(propsToPick)(obj)
13278 expect(result).toEqual([1, undefined])
13279})
13280
13281test('wrong input', () => {
13282 expect(() => props(null)(obj)).toThrow()
13283})
13284```
13285
13286</details>
13287
13288<details>
13289
13290<summary><strong>Typescript</strong> test</summary>
13291
13292```typescript
13293import {props} from 'rambda'
13294
13295const obj = {a: 1, b: 2}
13296
13297describe('R.props', () => {
13298 it('happy', () => {
13299 const result = props(['a', 'b'], obj)
13300
13301 result // $ExpectType number[]
13302 })
13303 it('curried', () => {
13304 const result = props(['a', 'b'])(obj)
13305
13306 result // $ExpectType number[]
13307 })
13308})
13309```
13310
13311</details>
13312
13313[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#props)
13314
13315### range
13316
13317```typescript
13318
13319range(startInclusive: number, endExclusive: number): number[]
13320```
13321
13322It returns list of numbers between `startInclusive` to `endExclusive` markers.
13323
13324<details>
13325
13326<summary>All Typescript definitions</summary>
13327
13328```typescript
13329range(startInclusive: number, endExclusive: number): number[];
13330range(startInclusive: number): (endExclusive: number) => number[];
13331```
13332
13333</details>
13334
13335<details>
13336
13337<summary><strong>R.range</strong> source</summary>
13338
13339```javascript
13340export function range(start, end) {
13341 if (arguments.length === 1) return _end => range(start, _end)
13342
13343 if (Number.isNaN(Number(start)) || Number.isNaN(Number(end))) {
13344 throw new TypeError('Both arguments to range must be numbers')
13345 }
13346
13347 if (end < start) return []
13348
13349 const len = end - start
13350 const willReturn = Array(len)
13351
13352 for (let i = 0; i < len; i++) {
13353 willReturn[i] = start + i
13354 }
13355
13356 return willReturn
13357}
13358```
13359
13360</details>
13361
13362<details>
13363
13364<summary><strong>Tests</strong></summary>
13365
13366```javascript
13367import {range} from './range'
13368
13369test('happy', () => {
13370 expect(range(0, 10)).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
13371})
13372
13373test('end range is bigger than start range', () => {
13374 expect(range(7, 3)).toEqual([])
13375 expect(range(5, 5)).toEqual([])
13376})
13377
13378test('with bad input', () => {
13379 const throwMessage = 'Both arguments to range must be numbers'
13380 expect(() => range('a', 6)).toThrowWithMessage(Error, throwMessage)
13381 expect(() => range(6, 'z')).toThrowWithMessage(Error, throwMessage)
13382})
13383
13384test('curry', () => {
13385 expect(range(0)(10)).toEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
13386})
13387```
13388
13389</details>
13390
13391<details>
13392
13393<summary><strong>Typescript</strong> test</summary>
13394
13395```typescript
13396import {range} from 'rambda'
13397
13398describe('R.range', () => {
13399 it('happy', () => {
13400 const result = range(1, 4)
13401
13402 result // $ExpectType number[]
13403 })
13404 it('curried', () => {
13405 const result = range(1)(4)
13406
13407 result // $ExpectType number[]
13408 })
13409})
13410```
13411
13412</details>
13413
13414<details>
13415
13416<summary>Rambda is fastest. Ramda is 61.8% slower and Lodash is 57.44% slower</summary>
13417
13418```text
13419const R = require('../../dist/rambda.js')
13420
13421const start = 12
13422const end = 22
13423const range = [
13424 {
13425 label: 'Rambda',
13426 fn: () => {
13427 R.range(start, end)
13428 },
13429 },
13430 {
13431 label: 'Ramda',
13432 fn: () => {
13433 Ramda.range(start, end)
13434 },
13435 },
13436 {
13437 label: 'Lodash',
13438 fn: () => {
13439 _.range(start, end)
13440 },
13441 },
13442]
13443```
13444
13445</details>
13446
13447[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#range)
13448
13449### reduce
13450
13451```typescript
13452
13453reduce<T, TResult>(reducer: (prev: TResult, current: T, i: number) => TResult, initialValue: TResult, list: T[]): TResult
13454```
13455
13456<details>
13457
13458<summary>All Typescript definitions</summary>
13459
13460```typescript
13461reduce<T, TResult>(reducer: (prev: TResult, current: T, i: number) => TResult, initialValue: TResult, list: T[]): TResult;
13462reduce<T, TResult>(reducer: (prev: TResult, current: T) => TResult, initialValue: TResult, list: T[]): TResult;
13463reduce<T, TResult>(reducer: (prev: TResult, current: T, i?: number) => TResult): (initialValue: TResult, list: T[]) => TResult;
13464reduce<T, TResult>(reducer: (prev: TResult, current: T, i?: number) => TResult, initialValue: TResult): (list: T[]) => TResult;
13465```
13466
13467</details>
13468
13469<details>
13470
13471<summary><strong>R.reduce</strong> source</summary>
13472
13473```javascript
13474import {_isArray} from './_internals/_isArray'
13475import {_keys} from './_internals/_keys'
13476import {curry} from './curry'
13477
13478function reduceFn(reducer, acc, list) {
13479 if (!_isArray(list)) {
13480 throw new TypeError('reduce: list must be array or iterable')
13481 }
13482 let index = 0
13483 const len = list.length
13484
13485 while (index < len) {
13486 acc = reducer(acc, list[index], index, list)
13487 index++
13488 }
13489
13490 return acc
13491}
13492
13493export const reduce = curry(reduceFn)
13494```
13495
13496</details>
13497
13498<details>
13499
13500<summary><strong>Tests</strong></summary>
13501
13502```javascript
13503import {reduce} from './reduce'
13504
13505const reducer = (prev, current, i) => {
13506 expect(i).toBeNumber()
13507
13508 return prev + current
13509}
13510const initialValue = 1
13511const list = [1, 2, 3]
13512const ERROR = 'reduce: list must be array or iterable'
13513
13514test('happy', () => {
13515 expect(reduce(reducer, initialValue, list)).toEqual(7)
13516})
13517
13518test('with object as iterable', () => {
13519 expect(() =>
13520 reduce(reducer, initialValue, {
13521 a: 1,
13522 b: 2,
13523 })
13524 ).toThrowWithMessage(TypeError, ERROR)
13525})
13526
13527test('with undefined as iterable', () => {
13528 expect(() => reduce(reducer, 0, null)).toThrowWithMessage(TypeError, ERROR)
13529})
13530```
13531
13532</details>
13533
13534<details>
13535
13536<summary><strong>Typescript</strong> test</summary>
13537
13538```typescript
13539import {reduce} from 'rambda'
13540
13541describe('R.reduce', () => {
13542 it('happy', () => {
13543 const result = reduce<number, number>(
13544 (acc, elem) => {
13545 acc // $ExpectType number
13546 elem // $ExpectType number
13547 return acc + elem
13548 },
13549 1,
13550 [1, 2, 3]
13551 )
13552
13553 result // $ExpectType number
13554 })
13555
13556 it('with two types', () => {
13557 const result = reduce<number, string>(
13558 (acc, elem) => {
13559 acc // $ExpectType string
13560 elem // $ExpectType number
13561
13562 return `${acc}${elem}`
13563 },
13564 'foo',
13565 [1, 2, 3]
13566 )
13567
13568 result // $ExpectType string
13569 })
13570
13571 it('with index', () => {
13572 const result = reduce<number, number>(
13573 (acc, elem, i) => {
13574 acc // $ExpectType number
13575 elem // $ExpectType number
13576 i // $ExpectType number
13577 return acc + elem
13578 },
13579 1,
13580 [1, 2, 3]
13581 )
13582
13583 result // $ExpectType number
13584 })
13585
13586 it('fallback', () => {
13587 const result = reduce(
13588 (acc, val) => {
13589 acc // $ExpectType number
13590 return acc + val
13591 },
13592 1,
13593 [1, 2, 3]
13594 )
13595
13596 result // $ExpectType number
13597 })
13598
13599 it('fallback with index', () => {
13600 const result = reduce(
13601 (acc, val, i) => {
13602 acc // $ExpectType number
13603 i // $ExpectType number
13604 return acc + val
13605 },
13606 1,
13607 [1, 2, 3]
13608 )
13609
13610 result // $ExpectType number
13611 })
13612
13613 it('fallback with two types', () => {
13614 const result = reduce(
13615 (acc, val) => {
13616 acc // $ExpectType string
13617 return acc + val
13618 },
13619 'foo',
13620 [1, 2, 3]
13621 )
13622
13623 result // $ExpectType string
13624 })
13625})
13626```
13627
13628</details>
13629
13630<details>
13631
13632<summary>Lodash is fastest. Rambda is 60.48% slower and Ramda is 77.1% slower</summary>
13633
13634```text
13635const R = require('../../dist/rambda.js')
13636
13637const fn = (acc, value) => acc + value
13638const holder = [1, 2, 3]
13639const acc = ''
13640
13641const reduce = [
13642 {
13643 label: 'Rambda',
13644 fn: () => {
13645 R.reduce(fn, acc, holder)
13646 },
13647 },
13648 {
13649 label: 'Ramda',
13650 fn: () => {
13651 Ramda.reduce(fn, acc, holder)
13652 },
13653 },
13654 {
13655 label: 'Lodash',
13656 fn: () => {
13657 _.reduce(holder, fn, acc)
13658 },
13659 },
13660]
13661```
13662
13663</details>
13664
13665[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#reduce)
13666
13667### reject
13668
13669```typescript
13670
13671reject<T>(predicate: Predicate<T>, list: T[]): T[]
13672```
13673
13674It has the opposite effect of `R.filter`.
13675
13676<details>
13677
13678<summary>All Typescript definitions</summary>
13679
13680```typescript
13681reject<T>(predicate: Predicate<T>, list: T[]): T[];
13682reject<T>(predicate: Predicate<T>): (list: T[]) => T[];
13683reject<T>(predicate: Predicate<T>, obj: Dictionary<T>): Dictionary<T>;
13684reject<T, U>(predicate: Predicate<T>): (obj: Dictionary<T>) => Dictionary<T>;
13685```
13686
13687</details>
13688
13689<details>
13690
13691<summary><strong>R.reject</strong> source</summary>
13692
13693```javascript
13694import {filter} from './filter'
13695
13696export function reject(predicate, list) {
13697 if (arguments.length === 1) return _list => reject(predicate, _list)
13698
13699 return filter(x => !predicate(x), list)
13700}
13701```
13702
13703</details>
13704
13705<details>
13706
13707<summary><strong>Tests</strong></summary>
13708
13709```javascript
13710import {reject} from './reject'
13711
13712const isOdd = n => n % 2 === 1
13713
13714test('with array', () => {
13715 expect(reject(isOdd)([1, 2, 3, 4])).toEqual([2, 4])
13716})
13717
13718test('with object', () => {
13719 const obj = {
13720 a: 1,
13721 b: 2,
13722 c: 3,
13723 d: 4,
13724 }
13725 expect(reject(isOdd, obj)).toEqual({
13726 b: 2,
13727 d: 4,
13728 })
13729})
13730```
13731
13732</details>
13733
13734<details>
13735
13736<summary><strong>Typescript</strong> test</summary>
13737
13738```typescript
13739import {reject} from 'rambda'
13740
13741describe('R.reject with array', () => {
13742 it('happy', () => {
13743 const result = reject(
13744 x => {
13745 x // $ExpectType number
13746 return x > 1
13747 },
13748 [1, 2, 3]
13749 )
13750 result // $ExpectType number[]
13751 })
13752 it('curried require explicit type', () => {
13753 const result = reject<number>(x => {
13754 x // $ExpectType number
13755 return x > 1
13756 })([1, 2, 3])
13757 result // $ExpectType number[]
13758 })
13759})
13760
13761describe('R.reject with objects', () => {
13762 it('happy', () => {
13763 const result = reject(
13764 x => {
13765 x // $ExpectType number
13766
13767 return x > 1
13768 },
13769 {a: 1, b: 2}
13770 )
13771 result // $ExpectType Dictionary<number>
13772 })
13773 it('curried require dummy type', () => {
13774 const result = reject<number, any>(x => {
13775 return x > 1
13776 })({a: 1, b: 2})
13777 result // $ExpectType Dictionary<number>
13778 })
13779})
13780```
13781
13782</details>
13783
13784[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#reject)
13785
13786### repeat
13787
13788```typescript
13789
13790repeat<T>(x: T): (timesToRepeat: number) => T[]
13791```
13792
13793<details>
13794
13795<summary>All Typescript definitions</summary>
13796
13797```typescript
13798repeat<T>(x: T): (timesToRepeat: number) => T[];
13799repeat<T>(x: T, timesToRepeat: number): T[];
13800```
13801
13802</details>
13803
13804<details>
13805
13806<summary><strong>R.repeat</strong> source</summary>
13807
13808```javascript
13809export function repeat(x, timesToRepeat) {
13810 if (arguments.length === 1) {
13811 return _timesToRepeat => repeat(x, _timesToRepeat)
13812 }
13813
13814 return Array(timesToRepeat).fill(x)
13815}
13816```
13817
13818</details>
13819
13820<details>
13821
13822<summary><strong>Tests</strong></summary>
13823
13824```javascript
13825import {repeat} from './repeat'
13826
13827test('repeat', () => {
13828 expect(repeat('')(3)).toEqual(['', '', ''])
13829 expect(repeat('foo', 3)).toEqual(['foo', 'foo', 'foo'])
13830
13831 const obj = {}
13832 const arr = repeat(obj, 3)
13833
13834 expect(arr).toEqual([{}, {}, {}])
13835
13836 expect(arr[0] === arr[1]).toBeTrue()
13837})
13838```
13839
13840</details>
13841
13842<details>
13843
13844<summary><strong>Typescript</strong> test</summary>
13845
13846```typescript
13847import {repeat} from 'rambda'
13848
13849describe('R.repeat', () => {
13850 it('happy', () => {
13851 const result = repeat(4, 7)
13852
13853 result // $ExpectType number[]
13854 })
13855 it('curried', () => {
13856 const result = repeat(4)(7)
13857
13858 result // $ExpectType number[]
13859 })
13860})
13861```
13862
13863</details>
13864
13865<details>
13866
13867<summary>Lodash is fastest. Rambda is 48.57% slower and Ramda is 68.98% slower</summary>
13868
13869```text
13870const R = require('../../dist/rambda.js')
13871
13872const num = 10
13873const str = 'foo'
13874
13875const repeat = [
13876 {
13877 label: 'Rambda',
13878 fn: () => {
13879 R.repeat(str, num)
13880 },
13881 },
13882 {
13883 label: 'Ramda',
13884 fn: () => {
13885 Ramda.repeat(str, num)
13886 },
13887 },
13888 {
13889 label: 'Lodash',
13890 fn: () => {
13891 _.repeat(str, num)
13892 },
13893 },
13894]
13895```
13896
13897</details>
13898
13899[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#repeat)
13900
13901### replace
13902
13903```typescript
13904
13905replace(strOrRegex: RegExp | string, replacer: string, str: string): string
13906```
13907
13908It replaces `strOrRegex` found in `str` with `replacer`.
13909
13910<details>
13911
13912<summary>All Typescript definitions</summary>
13913
13914```typescript
13915replace(strOrRegex: RegExp | string, replacer: string, str: string): string;
13916replace(strOrRegex: RegExp | string, replacer: string): (str: string) => string;
13917replace(strOrRegex: RegExp | string): (replacer: string) => (str: string) => string;
13918```
13919
13920</details>
13921
13922<details>
13923
13924<summary><strong>R.replace</strong> source</summary>
13925
13926```javascript
13927import {curry} from './curry'
13928
13929function replaceFn(pattern, replacer, str) {
13930 return str.replace(pattern, replacer)
13931}
13932
13933export const replace = curry(replaceFn)
13934```
13935
13936</details>
13937
13938<details>
13939
13940<summary><strong>Tests</strong></summary>
13941
13942```javascript
13943import {replace} from './replace'
13944
13945test('happy', () => {
13946 expect(replace('foo', 'yes', 'foo bar baz')).toEqual('yes bar baz')
13947})
13948
13949test('1', () => {
13950 expect(replace(/\s/g)('|')('foo bar baz')).toEqual('foo|bar|baz')
13951})
13952
13953test('2', () => {
13954 expect(replace(/\s/g)('|', 'foo bar baz')).toEqual('foo|bar|baz')
13955})
13956
13957test('3', () => {
13958 expect(replace(/\s/g, '|')('foo bar baz')).toEqual('foo|bar|baz')
13959})
13960```
13961
13962</details>
13963
13964<details>
13965
13966<summary><strong>Typescript</strong> test</summary>
13967
13968```typescript
13969import {replace} from 'rambda'
13970
13971const str = 'foo bar foo'
13972const replacer = 'bar'
13973
13974describe('R.replace', () => {
13975 it('happy', () => {
13976 const result = replace(/foo/g, replacer, str)
13977
13978 result // $ExpectType string
13979 })
13980 it('with string as search pattern', () => {
13981 const result = replace('foo', replacer, str)
13982
13983 result // $ExpectType string
13984 })
13985})
13986
13987describe('R.replace - curried', () => {
13988 it('happy', () => {
13989 const result = replace(/foo/g, replacer)(str)
13990
13991 result // $ExpectType string
13992 })
13993 it('with string as search pattern', () => {
13994 const result = replace('foo', replacer)(str)
13995
13996 result // $ExpectType string
13997 })
13998})
13999```
14000
14001</details>
14002
14003<details>
14004
14005<summary>Lodash is fastest. Rambda is 33.45% slower and Ramda is 33.99% slower</summary>
14006
14007```text
14008const R = require('../../dist/rambda.js')
14009
14010const replace = [
14011 {
14012 label: 'Rambda',
14013 fn: () => {
14014 R.replace(/\s/g, '|', 'foo bar baz')
14015 },
14016 },
14017 {
14018 label: 'Ramda',
14019 fn: () => {
14020 Ramda.replace(/\s/g, '|', 'foo bar baz')
14021 },
14022 },
14023 {
14024 label: 'Lodash',
14025 fn: () => {
14026 _.replace('foo bar baz', /\s/g, '|')
14027 },
14028 },
14029]
14030```
14031
14032</details>
14033
14034[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#replace)
14035
14036### reverse
14037
14038```typescript
14039
14040reverse<T>(input: T[]): T[]
14041```
14042
14043It returns a reversed copy of list or string `input`.
14044
14045<details>
14046
14047<summary>All Typescript definitions</summary>
14048
14049```typescript
14050reverse<T>(input: T[]): T[];
14051reverse(input: string): string;
14052```
14053
14054</details>
14055
14056<details>
14057
14058<summary><strong>R.reverse</strong> source</summary>
14059
14060```javascript
14061export function reverse(listOrString) {
14062 if (typeof listOrString === 'string') {
14063 return listOrString.split('').reverse().join('')
14064 }
14065
14066 const clone = listOrString.slice()
14067
14068 return clone.reverse()
14069}
14070```
14071
14072</details>
14073
14074<details>
14075
14076<summary><strong>Tests</strong></summary>
14077
14078```javascript
14079import {reverse} from './reverse'
14080
14081test('happy', () => {
14082 expect(reverse([1, 2, 3])).toEqual([3, 2, 1])
14083})
14084
14085test('with string', () => {
14086 expect(reverse('baz')).toEqual('zab')
14087})
14088
14089test("it doesn't mutate", () => {
14090 const arr = [1, 2, 3]
14091
14092 expect(reverse(arr)).toEqual([3, 2, 1])
14093
14094 expect(arr).toEqual([1, 2, 3])
14095})
14096```
14097
14098</details>
14099
14100<details>
14101
14102<summary><strong>Typescript</strong> test</summary>
14103
14104```typescript
14105import {reverse} from 'rambda'
14106
14107const list = [1, 2, 3, 4, 5]
14108
14109describe('R.reverse', () => {
14110 it('happy', () => {
14111 const result = reverse(list)
14112 result // $ExpectType number[]
14113 })
14114})
14115```
14116
14117</details>
14118
14119[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#reverse)
14120
14121### set
14122
14123```typescript
14124
14125set<T, U>(lens: Lens, replacer: U, obj: T): T
14126```
14127
14128It returns a copied **Object** or **Array** with modified `lens` focus set to `replacer` value.
14129
14130<details>
14131
14132<summary>All Typescript definitions</summary>
14133
14134```typescript
14135set<T, U>(lens: Lens, replacer: U, obj: T): T;
14136set<U>(lens: Lens, replacer: U): <T>(obj: T) => T;
14137set(lens: Lens): <T, U>(replacer: U, obj: T) => T;
14138```
14139
14140</details>
14141
14142<details>
14143
14144<summary><strong>R.set</strong> source</summary>
14145
14146```javascript
14147import {always} from './always'
14148import {curry} from './curry'
14149import {over} from './over'
14150
14151function setFn(lens, replacer, x) {
14152 return over(lens, always(replacer), x)
14153}
14154
14155export const set = curry(setFn)
14156```
14157
14158</details>
14159
14160<details>
14161
14162<summary><strong>Tests</strong></summary>
14163
14164```javascript
14165import {assoc} from './assoc'
14166import {lens} from './lens'
14167import {lensIndex} from './lensIndex'
14168import {lensPath} from './lensPath'
14169import {prop} from './prop'
14170import {set} from './set'
14171
14172const testObject = {
14173 foo: 'bar',
14174 baz: {
14175 a: 'x',
14176 b: 'y',
14177 },
14178}
14179
14180test('assoc lens', () => {
14181 const assocLens = lens(prop('foo'), assoc('foo'))
14182 const result = set(assocLens, 'FOO', testObject)
14183 const expected = {
14184 ...testObject,
14185 foo: 'FOO',
14186 }
14187 expect(result).toEqual(expected)
14188})
14189
14190test('path lens', () => {
14191 const pathLens = lensPath('baz.a')
14192 const result = set(pathLens, 'z', testObject)
14193 const expected = {
14194 ...testObject,
14195 baz: {
14196 a: 'z',
14197 b: 'y',
14198 },
14199 }
14200 expect(result).toEqual(expected)
14201})
14202
14203test('index lens', () => {
14204 const indexLens = lensIndex(0)
14205
14206 const result = set(indexLens, 3, [1, 2])
14207 expect(result).toEqual([3, 2])
14208})
14209```
14210
14211</details>
14212
14213<details>
14214
14215<summary>Rambda is faster than Ramda with 50.35%</summary>
14216
14217```text
14218const R = require('../../dist/rambda.js')
14219
14220const testObj = {a: 1}
14221
14222const last = [
14223 {
14224 label: 'Rambda',
14225 fn: () => {
14226 R.set(R.lensProp('a'), 2, testObj)
14227 },
14228 },
14229 {
14230 label: 'Ramda',
14231 fn: () => {
14232 Ramda.set(Ramda.lensProp('a'), 2, testObj)
14233 },
14234 },
14235]
14236```
14237
14238</details>
14239
14240[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#set)
14241
14242### slice
14243
14244```typescript
14245
14246slice(from: number, to: number, input: string): string
14247```
14248
14249<details>
14250
14251<summary>All Typescript definitions</summary>
14252
14253```typescript
14254slice(from: number, to: number, input: string): string;
14255slice<T>(from: number, to: number, input: T[]): T[];
14256slice(from: number, to: number): {
14257 (input: string): string;
14258 <T>(input: T[]): T[];
14259};
14260slice(from: number): {
14261 (to: number, input: string): string;
14262 <T>(to: number, input: T[]): T[];
14263};
14264```
14265
14266</details>
14267
14268<details>
14269
14270<summary><strong>R.slice</strong> source</summary>
14271
14272```javascript
14273import {curry} from './curry'
14274
14275function sliceFn(from, to, list) {
14276 return list.slice(from, to)
14277}
14278
14279export const slice = curry(sliceFn)
14280```
14281
14282</details>
14283
14284<details>
14285
14286<summary><strong>Tests</strong></summary>
14287
14288```javascript
14289import {slice} from './slice'
14290
14291test('slice', () => {
14292 expect(slice(1, 3, ['a', 'b', 'c', 'd'])).toEqual(['b', 'c'])
14293 expect(slice(1, Infinity, ['a', 'b', 'c', 'd'])).toEqual(['b', 'c', 'd'])
14294 expect(slice(0, -1, ['a', 'b', 'c', 'd'])).toEqual(['a', 'b', 'c'])
14295 expect(slice(-3, -1, ['a', 'b', 'c', 'd'])).toEqual(['b', 'c'])
14296 expect(slice(0, 3, 'ramda')).toEqual('ram')
14297})
14298```
14299
14300</details>
14301
14302<details>
14303
14304<summary><strong>Typescript</strong> test</summary>
14305
14306```typescript
14307import {slice} from 'rambda'
14308
14309const list = [1, 2, 3, 4, 5]
14310
14311describe('R.slice', () => {
14312 it('happy', () => {
14313 const result = slice(1, 3, list)
14314 result // $ExpectType number[]
14315 })
14316 it('curried', () => {
14317 const result = slice(1, 3)(list)
14318 result // $ExpectType number[]
14319 })
14320})
14321```
14322
14323</details>
14324
14325[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#slice)
14326
14327### sort
14328
14329```typescript
14330
14331sort<T>(sortFn: (a: T, b: T) => number, list: T[]): T[]
14332```
14333
14334It returns copy of `list` sorted by `sortFn` function.
14335
14336<details>
14337
14338<summary>All Typescript definitions</summary>
14339
14340```typescript
14341sort<T>(sortFn: (a: T, b: T) => number, list: T[]): T[];
14342sort<T>(sortFn: (a: T, b: T) => number): (list: T[]) => T[];
14343```
14344
14345</details>
14346
14347<details>
14348
14349<summary><strong>R.sort</strong> source</summary>
14350
14351```javascript
14352import {cloneList} from './_internals/cloneList'
14353
14354export function sort(sortFn, list) {
14355 if (arguments.length === 1) return _list => sort(sortFn, _list)
14356
14357 return cloneList(list).sort(sortFn)
14358}
14359```
14360
14361</details>
14362
14363<details>
14364
14365<summary><strong>Tests</strong></summary>
14366
14367```javascript
14368import {sort} from './sort'
14369
14370const fn = (a, b) => (a > b ? 1 : -1)
14371
14372test('sort', () => {
14373 expect(sort((a, b) => a - b)([2, 3, 1])).toEqual([1, 2, 3])
14374})
14375
14376test("it doesn't mutate", () => {
14377 const list = ['foo', 'bar', 'baz']
14378
14379 expect(sort(fn, list)).toEqual(['bar', 'baz', 'foo'])
14380
14381 expect(list[0]).toBe('foo')
14382 expect(list[1]).toBe('bar')
14383 expect(list[2]).toBe('baz')
14384})
14385```
14386
14387</details>
14388
14389<details>
14390
14391<summary><strong>Typescript</strong> test</summary>
14392
14393```typescript
14394import {sort} from 'rambda'
14395
14396const list = [3, 0, 5, 2, 1]
14397
14398function sortFn(a: number, b: number): number {
14399 return a > b ? 1 : -1
14400}
14401
14402describe('R.sort', () => {
14403 it('happy', () => {
14404 const result = sort(sortFn, list)
14405 result // $ExpectType number[]
14406 })
14407 it('curried', () => {
14408 const result = sort(sortFn)(list)
14409 result // $ExpectType number[]
14410 })
14411})
14412```
14413
14414</details>
14415
14416<details>
14417
14418<summary>Rambda is faster than Ramda with 40.23%</summary>
14419
14420```text
14421const R = require('../../dist/rambda.js')
14422
14423const list = ['foo', 'bar', 'baz']
14424const fn = (a, b) => (a > b ? -1 : 1)
14425
14426const replace = [
14427 {
14428 label: 'Rambda',
14429 fn: () => {
14430 R.sort(fn, list)
14431 R.sort(fn)(list)
14432 },
14433 },
14434 {
14435 label: 'Ramda',
14436 fn: () => {
14437 Ramda.sort(fn, list)
14438 Ramda.sort(fn)(list)
14439 },
14440 },
14441]
14442```
14443
14444</details>
14445
14446[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#sort)
14447
14448### sortBy
14449
14450```typescript
14451
14452sortBy<T>(sortFn: (a: T) => Ord, list: T[]): T[]
14453```
14454
14455It returns copy of `list` sorted by `sortFn` function.
14456
14457<details>
14458
14459<summary>All Typescript definitions</summary>
14460
14461```typescript
14462sortBy<T>(sortFn: (a: T) => Ord, list: T[]): T[];
14463sortBy<T>(sortFn: (a: T) => Ord): (list: T[]) => T[];
14464sortBy(sortFn: (a: any) => Ord): <T>(list: T[]) => T[];
14465```
14466
14467</details>
14468
14469<details>
14470
14471<summary><strong>R.sortBy</strong> source</summary>
14472
14473```javascript
14474import {cloneList} from './_internals/cloneList'
14475
14476export function sortBy(sortFn, list) {
14477 if (arguments.length === 1) return _list => sortBy(sortFn, _list)
14478
14479 const clone = cloneList(list)
14480
14481 return clone.sort((a, b) => {
14482 const aSortResult = sortFn(a)
14483 const bSortResult = sortFn(b)
14484
14485 if (aSortResult === bSortResult) return 0
14486
14487 return aSortResult < bSortResult ? -1 : 1
14488 })
14489}
14490```
14491
14492</details>
14493
14494<details>
14495
14496<summary><strong>Tests</strong></summary>
14497
14498```javascript
14499import {compose} from './compose'
14500import {prop} from './prop'
14501import {sortBy} from './sortBy'
14502import {toLower} from './toLower'
14503
14504test('happy', () => {
14505 const input = [{a: 2}, {a: 1}, {a: 1}, {a: 3}]
14506 const expected = [{a: 1}, {a: 1}, {a: 2}, {a: 3}]
14507
14508 const result = sortBy(x => x.a)(input)
14509 expect(result).toEqual(expected)
14510})
14511
14512test('with compose', () => {
14513 const alice = {
14514 name: 'ALICE',
14515 age: 101,
14516 }
14517 const bob = {
14518 name: 'Bob',
14519 age: -10,
14520 }
14521 const clara = {
14522 name: 'clara',
14523 age: 314.159,
14524 }
14525 const people = [clara, bob, alice]
14526 const sortByNameCaseInsensitive = sortBy(compose(toLower, prop('name')))
14527
14528 expect(sortByNameCaseInsensitive(people)).toEqual([alice, bob, clara])
14529})
14530```
14531
14532</details>
14533
14534<details>
14535
14536<summary><strong>Typescript</strong> test</summary>
14537
14538```typescript
14539import {sortBy, pipe} from 'rambda'
14540
14541interface Input {
14542 a: number,
14543}
14544
14545describe('R.sortBy', () => {
14546 it('passing type to sort function', () => {
14547 function fn(x: any): number {
14548 return x.a
14549 }
14550 function fn2(x: Input): number {
14551 return x.a
14552 }
14553
14554 const input = [{a: 2}, {a: 1}, {a: 0}]
14555 const result = sortBy(fn, input)
14556 const curriedResult = sortBy(fn2)(input)
14557
14558 result // $ExpectType { a: number; }[]
14559 curriedResult // $ExpectType Input[]
14560 result[0].a // $ExpectType number
14561 curriedResult[0].a // $ExpectType number
14562 })
14563 it('passing type to sort function and list', () => {
14564 function fn(x: Input): number {
14565 return x.a
14566 }
14567
14568 const input: Input[] = [{a: 2}, {a: 1}, {a: 0}]
14569 const result = sortBy(fn, input)
14570 const curriedResult = sortBy(fn)(input)
14571
14572 result // $ExpectType Input[]
14573 curriedResult // $ExpectType Input[]
14574 result[0].a // $ExpectType number
14575 })
14576 it('with R.pipe', () => {
14577 interface Obj {
14578 value: number,
14579 }
14580 const fn = pipe(sortBy<Obj>(x => x.value))
14581
14582 const result = fn([{value: 1}, {value: 2}])
14583 result // $ExpectType Obj[]
14584 })
14585})
14586```
14587
14588</details>
14589
14590<details>
14591
14592<summary>Rambda is fastest. Ramda is 25.29% slower and Lodash is 56.88% slower</summary>
14593
14594```text
14595const R = require('../../dist/rambda.js')
14596
14597const list = [{a: 2}, {a: 1}, {a: 0}]
14598const fn = x => x.a
14599
14600const replace = [
14601 {
14602 label: 'Rambda',
14603 fn: () => {
14604 R.sortBy(fn, list)
14605 },
14606 },
14607 {
14608 label: 'Ramda',
14609 fn: () => {
14610 Ramda.sortBy(fn, list)
14611 },
14612 },
14613 {
14614 label: 'Lodash',
14615 fn: () => {
14616 _.sortBy(list, fn)
14617 },
14618 },
14619]
14620```
14621
14622</details>
14623
14624[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#sortBy)
14625
14626### split
14627
14628```typescript
14629
14630split(separator: string | RegExp): (str: string) => string[]
14631```
14632
14633Curried version of `String.prototype.split`
14634
14635<details>
14636
14637<summary>All Typescript definitions</summary>
14638
14639```typescript
14640split(separator: string | RegExp): (str: string) => string[];
14641split(separator: string | RegExp, str: string): string[];
14642```
14643
14644</details>
14645
14646<details>
14647
14648<summary><strong>R.split</strong> source</summary>
14649
14650```javascript
14651export function split(separator, str) {
14652 if (arguments.length === 1) return _str => split(separator, _str)
14653
14654 return str.split(separator)
14655}
14656```
14657
14658</details>
14659
14660<details>
14661
14662<summary><strong>Tests</strong></summary>
14663
14664```javascript
14665import {split} from './split'
14666
14667const str = 'foo|bar|baz'
14668const splitChar = '|'
14669const expected = ['foo', 'bar', 'baz']
14670
14671test('happy', () => {
14672 expect(split(splitChar, str)).toEqual(expected)
14673})
14674
14675test('curried', () => {
14676 expect(split(splitChar)(str)).toEqual(expected)
14677})
14678```
14679
14680</details>
14681
14682<details>
14683
14684<summary><strong>Typescript</strong> test</summary>
14685
14686```typescript
14687import {split} from 'rambda'
14688
14689const str = 'foo|bar|baz'
14690const splitChar = '|'
14691
14692describe('R.split', () => {
14693 it('happy', () => {
14694 const result = split(splitChar, str)
14695
14696 result // $ExpectType string[]
14697 })
14698 it('curried', () => {
14699 const result = split(splitChar)(str)
14700
14701 result // $ExpectType string[]
14702 })
14703})
14704```
14705
14706</details>
14707
14708<details>
14709
14710<summary>Rambda is fastest. Ramda is 55.37% slower and Lodash is 17.64% slower</summary>
14711
14712```text
14713const R = require('../../dist/rambda.js')
14714
14715const str = 'foo|bar|baz'
14716const sep = '|'
14717
14718const split = [
14719 {
14720 label: 'Rambda',
14721 fn: () => {
14722 R.split(sep, str)
14723 },
14724 },
14725 {
14726 label: 'Ramda',
14727 fn: () => {
14728 Ramda.split(sep, str)
14729 },
14730 },
14731 {
14732 label: 'Lodash',
14733 fn: () => {
14734 _.split(str, sep)
14735 },
14736 },
14737]
14738```
14739
14740</details>
14741
14742[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#split)
14743
14744### splitAt
14745
14746```typescript
14747
14748splitAt<T>(index: number, input: T[]): [T[], T[]]
14749```
14750
14751It splits string or array at a given index.
14752
14753<details>
14754
14755<summary>All Typescript definitions</summary>
14756
14757```typescript
14758splitAt<T>(index: number, input: T[]): [T[], T[]];
14759splitAt(index: number, input: string): [string, string];
14760splitAt(index: number): {
14761 <T>(input: T[]): [T[], T[]];
14762 (input: string): [string, string];
14763};
14764```
14765
14766</details>
14767
14768<details>
14769
14770<summary><strong>R.splitAt</strong> source</summary>
14771
14772```javascript
14773import {_isArray} from './_internals/_isArray'
14774import {drop} from './drop'
14775import {maybe} from './maybe'
14776import {take} from './take'
14777
14778export function splitAt(index, input) {
14779 if (arguments.length === 1) {
14780 return _list => splitAt(index, _list)
14781 }
14782 if (!input) throw new TypeError(`Cannot read property 'slice' of ${input}`)
14783
14784 if (!_isArray(input) && typeof input !== 'string') return [[], []]
14785
14786 const correctIndex = maybe(
14787 index < 0,
14788 input.length + index < 0 ? 0 : input.length + index,
14789 index
14790 )
14791
14792 return [take(correctIndex, input), drop(correctIndex, input)]
14793}
14794```
14795
14796</details>
14797
14798<details>
14799
14800<summary><strong>Tests</strong></summary>
14801
14802```javascript
14803import {splitAt as splitAtRamda} from 'ramda'
14804
14805import {splitAt} from './splitAt'
14806
14807const list = [1, 2, 3]
14808const str = 'foo bar'
14809
14810test('with array', () => {
14811 const result = splitAt(2, list)
14812 expect(result).toEqual([[1, 2], [3]])
14813})
14814
14815test('with array - index is negative number', () => {
14816 const result = splitAt(-6, list)
14817 expect(result).toEqual([[], list])
14818})
14819
14820test('with array - index is out of scope', () => {
14821 const result = splitAt(4, list)
14822 expect(result).toEqual([[1, 2, 3], []])
14823})
14824
14825test('with string', () => {
14826 const result = splitAt(4, str)
14827 expect(result).toEqual(['foo ', 'bar'])
14828})
14829
14830test('with string - index is negative number', () => {
14831 const result = splitAt(-2, str)
14832 expect(result).toEqual(['foo b', 'ar'])
14833})
14834
14835test('with string - index is out of scope', () => {
14836 const result = splitAt(10, str)
14837 expect(result).toEqual([str, ''])
14838})
14839
14840test('with array - index is out of scope', () => {
14841 const result = splitAt(4)(list)
14842 expect(result).toEqual([[1, 2, 3], []])
14843})
14844
14845const badInputs = [1, true, /foo/g, {}]
14846const throwingBadInputs = [null, undefined]
14847
14848test('with bad inputs', () => {
14849 throwingBadInputs.forEach(badInput => {
14850 expect(() => splitAt(1, badInput)).toThrowWithMessage(
14851 TypeError,
14852 `Cannot read property 'slice' of ${badInput}`
14853 )
14854 expect(() => splitAtRamda(1, badInput)).toThrowWithMessage(
14855 TypeError,
14856 `Cannot read properties of ${badInput} (reading 'slice')`
14857 )
14858 })
14859
14860 badInputs.forEach(badInput => {
14861 const result = splitAt(1, badInput)
14862 const ramdaResult = splitAtRamda(1, badInput)
14863 expect(result).toEqual(ramdaResult)
14864 })
14865})
14866```
14867
14868</details>
14869
14870<details>
14871
14872<summary><strong>Typescript</strong> test</summary>
14873
14874```typescript
14875import {splitAt} from 'ramda'
14876
14877const index = 1
14878const str = 'foo'
14879const list = [1, 2, 3]
14880
14881describe('R.splitAt with array', () => {
14882 it('happy', () => {
14883 const result = splitAt(index, list)
14884
14885 result // $ExpectType [number[], number[]]
14886 })
14887 it('curried', () => {
14888 const result = splitAt(index)(list)
14889
14890 result // $ExpectType [number[], number[]]
14891 })
14892})
14893
14894describe('R.splitAt with string', () => {
14895 it('happy', () => {
14896 const result = splitAt(index, str)
14897
14898 result // $ExpectType [string, string]
14899 })
14900 it('curried', () => {
14901 const result = splitAt(index)(str)
14902
14903 result // $ExpectType [string, string]
14904 })
14905})
14906```
14907
14908</details>
14909
14910[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#splitAt)
14911
14912### splitEvery
14913
14914```typescript
14915
14916splitEvery<T>(sliceLength: number, input: T[]): (T[])[]
14917```
14918
14919It splits `input` into slices of `sliceLength`.
14920
14921<details>
14922
14923<summary>All Typescript definitions</summary>
14924
14925```typescript
14926splitEvery<T>(sliceLength: number, input: T[]): (T[])[];
14927splitEvery(sliceLength: number, input: string): string[];
14928splitEvery(sliceLength: number): {
14929 (input: string): string[];
14930 <T>(input: T[]): (T[])[];
14931};
14932```
14933
14934</details>
14935
14936<details>
14937
14938<summary><strong>R.splitEvery</strong> source</summary>
14939
14940```javascript
14941export function splitEvery(sliceLength, listOrString) {
14942 if (arguments.length === 1) {
14943 return _listOrString => splitEvery(sliceLength, _listOrString)
14944 }
14945
14946 if (sliceLength < 1) {
14947 throw new Error(
14948 'First argument to splitEvery must be a positive integer'
14949 )
14950 }
14951
14952 const willReturn = []
14953 let counter = 0
14954
14955 while (counter < listOrString.length) {
14956 willReturn.push(listOrString.slice(counter, (counter += sliceLength)))
14957 }
14958
14959 return willReturn
14960}
14961```
14962
14963</details>
14964
14965<details>
14966
14967<summary><strong>Tests</strong></summary>
14968
14969```javascript
14970import {splitEvery} from './splitEvery'
14971
14972test('happy', () => {
14973 expect(splitEvery(3, [1, 2, 3, 4, 5, 6, 7])).toEqual([
14974 [1, 2, 3],
14975 [4, 5, 6],
14976 [7],
14977 ])
14978
14979 expect(splitEvery(3)('foobarbaz')).toEqual(['foo', 'bar', 'baz'])
14980})
14981
14982test('with bad input', () => {
14983 expect(() =>
14984 expect(splitEvery(0)('foo')).toEqual(['f', 'o', 'o'])
14985 ).toThrowWithMessage(
14986 Error,
14987 'First argument to splitEvery must be a positive integer'
14988 )
14989})
14990```
14991
14992</details>
14993
14994<details>
14995
14996<summary><strong>Typescript</strong> test</summary>
14997
14998```typescript
14999import {splitEvery} from 'rambda'
15000
15001const list = [1, 2, 3, 4, 5, 6, 7]
15002
15003describe('R.splitEvery', () => {
15004 it('happy', () => {
15005 const result = splitEvery(3, list)
15006
15007 result // $ExpectType number[][]
15008 })
15009 it('curried', () => {
15010 const result = splitEvery(3)(list)
15011
15012 result // $ExpectType number[][]
15013 })
15014})
15015```
15016
15017</details>
15018
15019<details>
15020
15021<summary>Rambda is faster than Ramda with 71.98%</summary>
15022
15023```text
15024const R = require('../../dist/rambda.js')
15025
15026const list = [1, 2, 3, 4, 5, 6, 7]
15027
15028const splitEvery = [
15029 {
15030 label: 'Rambda',
15031 fn: () => {
15032 R.splitEvery(3, list)
15033 },
15034 },
15035 {
15036 label: 'Ramda',
15037 fn: () => {
15038 Ramda.splitEvery(3, list)
15039 },
15040 },
15041]
15042```
15043
15044</details>
15045
15046[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#splitEvery)
15047
15048### splitWhen
15049
15050```typescript
15051
15052splitWhen<T, U>(predicate: Predicate<T>, list: U[]): (U[])[]
15053```
15054
15055It splits `list` to two arrays according to a `predicate` function.
15056
15057The first array contains all members of `list` before `predicate` returns `true`.
15058
15059<details>
15060
15061<summary>All Typescript definitions</summary>
15062
15063```typescript
15064splitWhen<T, U>(predicate: Predicate<T>, list: U[]): (U[])[];
15065splitWhen<T>(predicate: Predicate<T>): <U>(list: U[]) => (U[])[];
15066```
15067
15068</details>
15069
15070<details>
15071
15072<summary><strong>R.splitWhen</strong> source</summary>
15073
15074```javascript
15075export function splitWhen(predicate, input) {
15076 if (arguments.length === 1) {
15077 return _input => splitWhen(predicate, _input)
15078 }
15079 if (!input)
15080 throw new TypeError(`Cannot read property 'length' of ${input}`)
15081
15082 const preFound = []
15083 const postFound = []
15084 let found = false
15085 let counter = -1
15086
15087 while (counter++ < input.length - 1) {
15088 if (found) {
15089 postFound.push(input[counter])
15090 } else if (predicate(input[counter])) {
15091 postFound.push(input[counter])
15092 found = true
15093 } else {
15094 preFound.push(input[counter])
15095 }
15096 }
15097
15098 return [preFound, postFound]
15099}
15100```
15101
15102</details>
15103
15104<details>
15105
15106<summary><strong>Tests</strong></summary>
15107
15108```javascript
15109import {splitWhen as splitWhenRamda} from 'ramda'
15110
15111import {equals} from './equals'
15112import {splitWhen} from './splitWhen'
15113
15114const list = [1, 2, 1, 2]
15115
15116test('happy', () => {
15117 const result = splitWhen(equals(2), list)
15118 expect(result).toEqual([[1], [2, 1, 2]])
15119})
15120
15121test('when predicate returns false', () => {
15122 const result = splitWhen(equals(3))(list)
15123 expect(result).toEqual([list, []])
15124})
15125
15126const badInputs = [1, true, /foo/g, {}]
15127const throwingBadInputs = [null, undefined]
15128
15129test('with bad inputs', () => {
15130 throwingBadInputs.forEach(badInput => {
15131 expect(() => splitWhen(equals(2), badInput)).toThrowWithMessage(
15132 TypeError,
15133 `Cannot read property 'length' of ${badInput}`
15134 )
15135 expect(() => splitWhenRamda(equals(2), badInput)).toThrowWithMessage(
15136 TypeError,
15137 `Cannot read properties of ${badInput} (reading 'length')`
15138 )
15139 })
15140
15141 badInputs.forEach(badInput => {
15142 const result = splitWhen(equals(2), badInput)
15143 const ramdaResult = splitWhenRamda(equals(2), badInput)
15144 expect(result).toEqual(ramdaResult)
15145 })
15146})
15147```
15148
15149</details>
15150
15151<details>
15152
15153<summary><strong>Typescript</strong> test</summary>
15154
15155```typescript
15156import {splitWhen} from 'rambda'
15157
15158const list = [1, 2, 1, 2]
15159const predicate = (x: number) => x === 2
15160
15161describe('R.splitWhen', () => {
15162 it('happy', () => {
15163 const result = splitWhen(predicate, list)
15164
15165 result // $ExpectType number[][]
15166 })
15167 it('curried', () => {
15168 const result = splitWhen(predicate)(list)
15169
15170 result // $ExpectType number[][]
15171 })
15172})
15173```
15174
15175</details>
15176
15177[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#splitWhen)
15178
15179### startsWith
15180
15181```typescript
15182
15183startsWith(target: string, str: string): boolean
15184```
15185
15186When iterable is a string, then it behaves as `String.prototype.startsWith`.
15187When iterable is a list, then it uses R.equals to determine if the target list starts in the same way as the given target.
15188
15189<details>
15190
15191<summary>All Typescript definitions</summary>
15192
15193```typescript
15194startsWith(target: string, str: string): boolean;
15195startsWith(target: string): (str: string) => boolean;
15196startsWith<T>(target: T[], list: T[]): boolean;
15197startsWith<T>(target: T[]): (list: T[]) => boolean;
15198```
15199
15200</details>
15201
15202<details>
15203
15204<summary><strong>R.startsWith</strong> source</summary>
15205
15206```javascript
15207import {equals} from './equals.js'
15208import {_isArray} from './_internals/_isArray.js'
15209
15210export function startsWith(target, iterable) {
15211 if (arguments.length === 1)
15212 return _iterable => startsWith(target, _iterable)
15213
15214 if (typeof iterable === 'string') {
15215 return iterable.startsWith(target)
15216 }
15217 if (!_isArray(target)) return false
15218
15219 let correct = true
15220 const filtered = target.filter((x, index) => {
15221 if (!correct) return false
15222 const result = equals(x, iterable[index])
15223 if (!result) correct = false
15224 return result
15225 })
15226
15227 return filtered.length === target.length
15228}
15229```
15230
15231</details>
15232
15233<details>
15234
15235<summary><strong>Tests</strong></summary>
15236
15237```javascript
15238import {startsWith} from './startsWith'
15239import {possibleTargets, possibleIterables} from './endsWith.spec'
15240import {startsWith as startsWithRamda} from 'ramda'
15241import {compareCombinations} from './_internals/testUtils'
15242
15243test('with string', () => {
15244 expect(startsWith('foo', 'foo-bar')).toBeTrue()
15245 expect(startsWith('baz')('foo-bar')).toBeFalse()
15246})
15247
15248test('use R.equals with array', () => {
15249 const list = [{a: 1}, {a: 2}, {a: 3}]
15250 expect(startsWith({a: 1}, list)).toBeFalse()
15251 expect(startsWith([{a: 1}], list)).toBeTrue()
15252 expect(startsWith([{a: 1}, {a: 2}], list)).toBeTrue()
15253 expect(startsWith(list, list)).toBeTrue()
15254 expect(startsWith([{a: 2}], list)).toBeFalse()
15255})
15256
15257describe('brute force', () => {
15258 compareCombinations({
15259 fn: startsWith,
15260 fnRamda: startsWithRamda,
15261 firstInput: possibleTargets,
15262 secondInput: possibleIterables,
15263 callback: errorsCounters => {
15264 expect(errorsCounters).toMatchInlineSnapshot(`
15265 Object {
15266 "ERRORS_MESSAGE_MISMATCH": 0,
15267 "ERRORS_TYPE_MISMATCH": 0,
15268 "RESULTS_MISMATCH": 0,
15269 "SHOULD_NOT_THROW": 0,
15270 "SHOULD_THROW": 0,
15271 "TOTAL_TESTS": 32,
15272 }
15273 `)
15274 },
15275 })
15276})
15277```
15278
15279</details>
15280
15281<details>
15282
15283<summary><strong>Typescript</strong> test</summary>
15284
15285```typescript
15286import {startsWith} from 'rambda'
15287
15288describe('R.startsWith - array as iterable', () => {
15289 const target = [{a: 1}]
15290 const iterable = [{a: 1}, {a: 2}]
15291 it('happy', () => {
15292 const result = startsWith(target, iterable)
15293
15294 result // $ExpectType boolean
15295 })
15296 it('curried', () => {
15297 const result = startsWith(target)(iterable)
15298
15299 result // $ExpectType boolean
15300 })
15301})
15302
15303describe('R.startsWith - string as iterable', () => {
15304 const target = 'foo'
15305 const iterable = 'foo bar'
15306 it('happy', () => {
15307 const result = startsWith(target, iterable)
15308
15309 result // $ExpectType boolean
15310 })
15311 it('curried', () => {
15312 const result = startsWith(target)(iterable)
15313
15314 result // $ExpectType boolean
15315 })
15316})
15317```
15318
15319</details>
15320
15321[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#startsWith)
15322
15323### subtract
15324
15325Curried version of `x - y`
15326
15327[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#subtract)
15328
15329### sum
15330
15331```typescript
15332
15333sum(list: number[]): number
15334```
15335
15336<details>
15337
15338<summary>All Typescript definitions</summary>
15339
15340```typescript
15341sum(list: number[]): number;
15342```
15343
15344</details>
15345
15346<details>
15347
15348<summary><strong>R.sum</strong> source</summary>
15349
15350```javascript
15351export function sum(list) {
15352 return list.reduce((prev, current) => prev + current, 0)
15353}
15354```
15355
15356</details>
15357
15358<details>
15359
15360<summary><strong>Tests</strong></summary>
15361
15362```javascript
15363import {sum} from './sum'
15364
15365test('happy', () => {
15366 expect(sum([1, 2, 3, 4, 5])).toBe(15)
15367})
15368```
15369
15370</details>
15371
15372[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#sum)
15373
15374### symmetricDifference
15375
15376```typescript
15377
15378symmetricDifference<T>(x: T[], y: T[]): T[]
15379```
15380
15381It returns a merged list of `x` and `y` with all equal elements removed.
15382
15383`R.equals` is used to determine equality.
15384
15385<details>
15386
15387<summary>All Typescript definitions</summary>
15388
15389```typescript
15390symmetricDifference<T>(x: T[], y: T[]): T[];
15391symmetricDifference<T>(x: T[]): <T>(y: T[]) => T[];
15392```
15393
15394</details>
15395
15396<details>
15397
15398<summary><strong>R.symmetricDifference</strong> source</summary>
15399
15400```javascript
15401import {concat} from './concat'
15402import {filter} from './filter'
15403import {includes} from './includes'
15404
15405export function symmetricDifference(x, y) {
15406 if (arguments.length === 1) {
15407 return _y => symmetricDifference(x, _y)
15408 }
15409
15410 return concat(
15411 filter(value => !includes(value, y), x),
15412 filter(value => !includes(value, x), y)
15413 )
15414}
15415```
15416
15417</details>
15418
15419<details>
15420
15421<summary><strong>Tests</strong></summary>
15422
15423```javascript
15424import {symmetricDifference} from './symmetricDifference'
15425
15426test('symmetricDifference', () => {
15427 const list1 = [1, 2, 3, 4]
15428 const list2 = [3, 4, 5, 6]
15429 expect(symmetricDifference(list1)(list2)).toEqual([1, 2, 5, 6])
15430
15431 expect(symmetricDifference([], [])).toEqual([])
15432})
15433
15434test('symmetricDifference with objects', () => {
15435 const list1 = [{id: 1}, {id: 2}, {id: 3}, {id: 4}]
15436 const list2 = [{id: 3}, {id: 4}, {id: 5}, {id: 6}]
15437 expect(symmetricDifference(list1)(list2)).toEqual([
15438 {id: 1},
15439 {id: 2},
15440 {id: 5},
15441 {id: 6},
15442 ])
15443})
15444```
15445
15446</details>
15447
15448<details>
15449
15450<summary><strong>Typescript</strong> test</summary>
15451
15452```typescript
15453import {symmetricDifference} from 'rambda'
15454
15455describe('R.symmetricDifference', () => {
15456 it('happy', () => {
15457 const list1 = [1, 2, 3, 4]
15458 const list2 = [3, 4, 5, 6]
15459 const result = symmetricDifference(list1, list2)
15460
15461 result // $ExpectType number[]
15462 })
15463
15464 it('curried', () => {
15465 const list1 = [{id: 1}, {id: 2}, {id: 3}, {id: 4}]
15466 const list2 = [{id: 3}, {id: 4}, {id: 5}, {id: 6}]
15467 const result = symmetricDifference(list1)(list2)
15468
15469 result // $ExpectType { id: number; }[]
15470 })
15471})
15472```
15473
15474</details>
15475
15476[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#symmetricDifference)
15477
15478### T
15479
15480```typescript
15481
15482T(): boolean
15483```
15484
15485<details>
15486
15487<summary>All Typescript definitions</summary>
15488
15489```typescript
15490T(): boolean;
15491```
15492
15493</details>
15494
15495<details>
15496
15497<summary><strong>R.T</strong> source</summary>
15498
15499```javascript
15500export function T() {
15501 return true
15502}
15503```
15504
15505</details>
15506
15507[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#T)
15508
15509### tail
15510
15511```typescript
15512
15513tail<T>(input: T[]): T[]
15514```
15515
15516It returns all but the first element of `input`.
15517
15518<details>
15519
15520<summary>All Typescript definitions</summary>
15521
15522```typescript
15523tail<T>(input: T[]): T[];
15524tail(input: string): string;
15525```
15526
15527</details>
15528
15529<details>
15530
15531<summary><strong>R.tail</strong> source</summary>
15532
15533```javascript
15534import {drop} from './drop'
15535
15536export function tail(listOrString) {
15537 return drop(1, listOrString)
15538}
15539```
15540
15541</details>
15542
15543<details>
15544
15545<summary><strong>Tests</strong></summary>
15546
15547```javascript
15548import {tail} from './tail'
15549
15550test('tail', () => {
15551 expect(tail([1, 2, 3])).toEqual([2, 3])
15552 expect(tail([1, 2])).toEqual([2])
15553 expect(tail([1])).toEqual([])
15554 expect(tail([])).toEqual([])
15555
15556 expect(tail('abc')).toEqual('bc')
15557 expect(tail('ab')).toEqual('b')
15558 expect(tail('a')).toEqual('')
15559 expect(tail('')).toEqual('')
15560})
15561```
15562
15563</details>
15564
15565<details>
15566
15567<summary><strong>Typescript</strong> test</summary>
15568
15569```typescript
15570import {tail} from 'rambda'
15571
15572describe('R.tail', () => {
15573 it('with string', () => {
15574 const result = tail('foo')
15575
15576 result // $ExpectType string
15577 })
15578 it('with list', () => {
15579 const result = tail([1, 2, 3])
15580
15581 result // $ExpectType number[]
15582 })
15583})
15584```
15585
15586</details>
15587
15588[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#tail)
15589
15590### take
15591
15592```typescript
15593
15594take<T>(howMany: number, input: T[]): T[]
15595```
15596
15597It returns the first `howMany` elements of `input`.
15598
15599<details>
15600
15601<summary>All Typescript definitions</summary>
15602
15603```typescript
15604take<T>(howMany: number, input: T[]): T[];
15605take(howMany: number, input: string): string;
15606take<T>(howMany: number): {
15607 <T>(input: T[]): T[];
15608 (input: string): string;
15609};
15610```
15611
15612</details>
15613
15614<details>
15615
15616<summary><strong>R.take</strong> source</summary>
15617
15618```javascript
15619import baseSlice from './_internals/baseSlice'
15620
15621export function take(howMany, listOrString) {
15622 if (arguments.length === 1)
15623 return _listOrString => take(howMany, _listOrString)
15624 if (howMany < 0) return listOrString.slice()
15625 if (typeof listOrString === 'string') return listOrString.slice(0, howMany)
15626
15627 return baseSlice(listOrString, 0, howMany)
15628}
15629```
15630
15631</details>
15632
15633<details>
15634
15635<summary><strong>Tests</strong></summary>
15636
15637```javascript
15638import {take} from './take'
15639
15640test('happy', () => {
15641 const arr = ['foo', 'bar', 'baz']
15642
15643 expect(take(1, arr)).toEqual(['foo'])
15644
15645 expect(arr).toEqual(['foo', 'bar', 'baz'])
15646
15647 expect(take(2)(['foo', 'bar', 'baz'])).toEqual(['foo', 'bar'])
15648 expect(take(3, ['foo', 'bar', 'baz'])).toEqual(['foo', 'bar', 'baz'])
15649 expect(take(4, ['foo', 'bar', 'baz'])).toEqual(['foo', 'bar', 'baz'])
15650 expect(take(3)('rambda')).toEqual('ram')
15651})
15652
15653test('with negative index', () => {
15654 expect(take(-1, [1, 2, 3])).toEqual([1, 2, 3])
15655 expect(take(-Infinity, [1, 2, 3])).toEqual([1, 2, 3])
15656})
15657
15658test('with zero index', () => {
15659 expect(take(0, [1, 2, 3])).toEqual([])
15660})
15661```
15662
15663</details>
15664
15665<details>
15666
15667<summary><strong>Typescript</strong> test</summary>
15668
15669```typescript
15670import {take} from 'rambda'
15671
15672const list = [1, 2, 3, 4]
15673const str = 'foobar'
15674const howMany = 2
15675
15676describe('R.take - array', () => {
15677 it('happy', () => {
15678 const result = take(howMany, list)
15679
15680 result // $ExpectType number[]
15681 })
15682 it('curried', () => {
15683 const result = take(howMany)(list)
15684
15685 result // $ExpectType number[]
15686 })
15687})
15688
15689describe('R.take - string', () => {
15690 it('happy', () => {
15691 const result = take(howMany, str)
15692
15693 result // $ExpectType string
15694 })
15695 it('curried', () => {
15696 const result = take(howMany)(str)
15697
15698 result // $ExpectType string
15699 })
15700})
15701```
15702
15703</details>
15704
15705<details>
15706
15707<summary>Rambda is fastest. Ramda is 91.96% slower and Lodash is 4.72% slower</summary>
15708
15709```text
15710const R = require('../../dist/rambda.js')
15711
15712const list = [1, 2, 3, 4]
15713const num = 2
15714
15715const take = [
15716 {
15717 label: 'Rambda',
15718 fn: () => {
15719 R.take(num, list)
15720 },
15721 },
15722 {
15723 label: 'Ramda',
15724 fn: () => {
15725 Ramda.take(num, list)
15726 },
15727 },
15728 {
15729 label: 'Lodash',
15730 fn: () => {
15731 _.take(list, num)
15732 },
15733 },
15734]
15735```
15736
15737</details>
15738
15739[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#take)
15740
15741### takeLast
15742
15743```typescript
15744
15745takeLast<T>(howMany: number, input: T[]): T[]
15746```
15747
15748It returns the last `howMany` elements of `input`.
15749
15750<details>
15751
15752<summary>All Typescript definitions</summary>
15753
15754```typescript
15755takeLast<T>(howMany: number, input: T[]): T[];
15756takeLast(howMany: number, input: string): string;
15757takeLast<T>(howMany: number): {
15758 <T>(input: T[]): T[];
15759 (input: string): string;
15760};
15761```
15762
15763</details>
15764
15765<details>
15766
15767<summary><strong>R.takeLast</strong> source</summary>
15768
15769```javascript
15770import baseSlice from './_internals/baseSlice'
15771
15772export function takeLast(howMany, listOrString) {
15773 if (arguments.length === 1)
15774 return _listOrString => takeLast(howMany, _listOrString)
15775
15776 const len = listOrString.length
15777 if (howMany < 0) return listOrString.slice()
15778 let numValue = howMany > len ? len : howMany
15779
15780 if (typeof listOrString === 'string')
15781 return listOrString.slice(len - numValue)
15782
15783 numValue = len - numValue
15784
15785 return baseSlice(listOrString, numValue, len)
15786}
15787```
15788
15789</details>
15790
15791<details>
15792
15793<summary><strong>Tests</strong></summary>
15794
15795```javascript
15796import {takeLast} from './takeLast'
15797
15798test('with arrays', () => {
15799 expect(takeLast(1, ['foo', 'bar', 'baz'])).toEqual(['baz'])
15800
15801 expect(takeLast(2)(['foo', 'bar', 'baz'])).toEqual(['bar', 'baz'])
15802
15803 expect(takeLast(3, ['foo', 'bar', 'baz'])).toEqual(['foo', 'bar', 'baz'])
15804
15805 expect(takeLast(4, ['foo', 'bar', 'baz'])).toEqual(['foo', 'bar', 'baz'])
15806
15807 expect(takeLast(10, ['foo', 'bar', 'baz'])).toEqual(['foo', 'bar', 'baz'])
15808})
15809
15810test('with strings', () => {
15811 expect(takeLast(3, 'rambda')).toEqual('bda')
15812
15813 expect(takeLast(7, 'rambda')).toEqual('rambda')
15814})
15815
15816test('with negative index', () => {
15817 expect(takeLast(-1, [1, 2, 3])).toEqual([1, 2, 3])
15818 expect(takeLast(-Infinity, [1, 2, 3])).toEqual([1, 2, 3])
15819})
15820```
15821
15822</details>
15823
15824<details>
15825
15826<summary><strong>Typescript</strong> test</summary>
15827
15828```typescript
15829import {takeLast} from 'rambda'
15830
15831const list = [1, 2, 3, 4]
15832const str = 'foobar'
15833const howMany = 2
15834
15835describe('R.takeLast - array', () => {
15836 it('happy', () => {
15837 const result = takeLast(howMany, list)
15838
15839 result // $ExpectType number[]
15840 })
15841 it('curried', () => {
15842 const result = takeLast(howMany)(list)
15843
15844 result // $ExpectType number[]
15845 })
15846})
15847
15848describe('R.takeLast - string', () => {
15849 it('happy', () => {
15850 const result = takeLast(howMany, str)
15851
15852 result // $ExpectType string
15853 })
15854 it('curried', () => {
15855 const result = takeLast(howMany)(str)
15856
15857 result // $ExpectType string
15858 })
15859})
15860```
15861
15862</details>
15863
15864<details>
15865
15866<summary>Rambda is fastest. Ramda is 93.39% slower and Lodash is 19.22% slower</summary>
15867
15868```text
15869const R = require('../../dist/rambda.js')
15870
15871const list = [1, 2, 3, 4]
15872const num = 2
15873
15874const takeLast = [
15875 {
15876 label: 'Rambda',
15877 fn: () => {
15878 R.takeLast(num, list)
15879 },
15880 },
15881 {
15882 label: 'Ramda',
15883 fn: () => {
15884 Ramda.takeLast(num, list)
15885 },
15886 },
15887 {
15888 label: 'Lodash',
15889 fn: () => {
15890 _.takeRight(list, num)
15891 },
15892 },
15893]
15894```
15895
15896</details>
15897
15898[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#takeLast)
15899
15900### takeLastWhile
15901
15902```typescript
15903
15904takeLastWhile(predicate: (x: string) => boolean, input: string): string
15905```
15906
15907<details>
15908
15909<summary>All Typescript definitions</summary>
15910
15911```typescript
15912takeLastWhile(predicate: (x: string) => boolean, input: string): string;
15913takeLastWhile(predicate: (x: string) => boolean): (input: string) => string;
15914takeLastWhile<T>(predicate: (x: T) => boolean, input: T[]): T[];
15915takeLastWhile<T>(predicate: (x: T) => boolean): <T>(input: T[]) => T[];
15916```
15917
15918</details>
15919
15920<details>
15921
15922<summary><strong>R.takeLastWhile</strong> source</summary>
15923
15924```javascript
15925import {_isArray} from './_internals/_isArray'
15926
15927export function takeLastWhile(predicate, input) {
15928 if (arguments.length === 1) {
15929 return _input => takeLastWhile(predicate, _input)
15930 }
15931 if (input.length === 0) return input
15932 let found = false
15933 const toReturn = []
15934 let counter = input.length
15935
15936 while (!found || counter === 0) {
15937 counter--
15938 if (predicate(input[counter]) === false) {
15939 found = true
15940 } else if (!found) {
15941 toReturn.push(input[counter])
15942 }
15943 }
15944
15945 return _isArray(input) ? toReturn.reverse() : toReturn.reverse().join('')
15946}
15947```
15948
15949</details>
15950
15951<details>
15952
15953<summary><strong>Tests</strong></summary>
15954
15955```javascript
15956import {takeLastWhile} from './takeLastWhile'
15957const assert = require('assert')
15958
15959const list = [1, 2, 3, 4]
15960
15961test('happy', () => {
15962 const predicate = x => x > 2
15963 const result = takeLastWhile(predicate, list)
15964 expect(result).toEqual([3, 4])
15965})
15966
15967test('predicate is always true', () => {
15968 const predicate = x => x > 0
15969 const result = takeLastWhile(predicate)(list)
15970 expect(result).toEqual(list)
15971})
15972
15973test('predicate is always false', () => {
15974 const predicate = x => x < 0
15975 const result = takeLastWhile(predicate, list)
15976 expect(result).toEqual([])
15977})
15978
15979test('with string', () => {
15980 const result = takeLastWhile(x => x !== 'F', 'FOOBAR')
15981 expect(result).toEqual('OOBAR')
15982})
15983```
15984
15985</details>
15986
15987<details>
15988
15989<summary><strong>Typescript</strong> test</summary>
15990
15991```typescript
15992import {takeLastWhile} from 'rambda'
15993
15994const list = [1, 2, 3]
15995const str = 'FOO'
15996
15997describe('R.takeLastWhile', () => {
15998 it('with array', () => {
15999 const result = takeLastWhile(x => x > 1, list)
16000
16001 result // $ExpectType number[]
16002 })
16003 it('with array - curried', () => {
16004 const result = takeLastWhile(x => x > 1, list)
16005
16006 result // $ExpectType number[]
16007 })
16008 it('with string', () => {
16009 const result = takeLastWhile(x => x !== 'F', str)
16010
16011 result // $ExpectType string
16012 })
16013 it('with string - curried', () => {
16014 const result = takeLastWhile(x => x !== 'F')(str)
16015
16016 result // $ExpectType string
16017 })
16018})
16019```
16020
16021</details>
16022
16023[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#takeLastWhile)
16024
16025### takeWhile
16026
16027[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#takeWhile)
16028
16029### tap
16030
16031```typescript
16032
16033tap<T>(fn: (x: T) => void, input: T): T
16034```
16035
16036It applies function `fn` to input `x` and returns `x`.
16037
16038One use case is debuging in the middle of `R.compose`.
16039
16040<details>
16041
16042<summary>All Typescript definitions</summary>
16043
16044```typescript
16045tap<T>(fn: (x: T) => void, input: T): T;
16046tap<T>(fn: (x: T) => void): (input: T) => T;
16047```
16048
16049</details>
16050
16051<details>
16052
16053<summary><strong>R.tap</strong> source</summary>
16054
16055```javascript
16056export function tap(fn, x) {
16057 if (arguments.length === 1) return _x => tap(fn, _x)
16058
16059 fn(x)
16060
16061 return x
16062}
16063```
16064
16065</details>
16066
16067<details>
16068
16069<summary><strong>Tests</strong></summary>
16070
16071```javascript
16072import {tap} from './tap'
16073
16074test('tap', () => {
16075 let a = 1
16076 const sayX = x => (a = x)
16077
16078 expect(tap(sayX, 100)).toEqual(100)
16079 expect(tap(sayX)(100)).toEqual(100)
16080 expect(a).toEqual(100)
16081})
16082```
16083
16084</details>
16085
16086<details>
16087
16088<summary><strong>Typescript</strong> test</summary>
16089
16090```typescript
16091import {tap, pipe} from 'rambda'
16092
16093describe('R.tap', () => {
16094 it('happy', () => {
16095 pipe(
16096 tap(x => {
16097 x // $ExpectType number[]
16098 }),
16099 (x: number[]) => x.length
16100 )([1, 2])
16101 })
16102})
16103```
16104
16105</details>
16106
16107[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#tap)
16108
16109### test
16110
16111```typescript
16112
16113test(regExpression: RegExp): (str: string) => boolean
16114```
16115
16116It determines whether `str` matches `regExpression`.
16117
16118<details>
16119
16120<summary>All Typescript definitions</summary>
16121
16122```typescript
16123test(regExpression: RegExp): (str: string) => boolean;
16124test(regExpression: RegExp, str: string): boolean;
16125```
16126
16127</details>
16128
16129<details>
16130
16131<summary><strong>R.test</strong> source</summary>
16132
16133```javascript
16134export function test(pattern, str) {
16135 if (arguments.length === 1) return _str => test(pattern, _str)
16136
16137 if (typeof pattern === 'string') {
16138 throw new TypeError(
16139 `‘test’ requires a value of type RegExp as its first argument; received "${pattern}"`
16140 )
16141 }
16142
16143 return str.search(pattern) !== -1
16144}
16145```
16146
16147</details>
16148
16149<details>
16150
16151<summary><strong>Tests</strong></summary>
16152
16153```javascript
16154import {test as testMethod} from './test'
16155
16156test('happy', () => {
16157 expect(testMethod(/^x/, 'xyz')).toBeTrue()
16158
16159 expect(testMethod(/^y/)('xyz')).toBeFalse()
16160})
16161
16162test('throws if first argument is not regex', () => {
16163 expect(() => testMethod('foo', 'bar')).toThrowWithMessage(
16164 TypeError,
16165 '‘test’ requires a value of type RegExp as its first argument; received "foo"'
16166 )
16167})
16168```
16169
16170</details>
16171
16172<details>
16173
16174<summary><strong>Typescript</strong> test</summary>
16175
16176```typescript
16177import {test} from 'rambda'
16178
16179const input = 'foo '
16180const regex = /foo/
16181
16182describe('R.test', () => {
16183 it('happy', () => {
16184 const result = test(regex, input)
16185
16186 result // $ExpectType boolean
16187 })
16188 it('curried', () => {
16189 const result = test(regex)(input)
16190
16191 result // $ExpectType boolean
16192 })
16193})
16194```
16195
16196</details>
16197
16198<details>
16199
16200<summary>Rambda is faster than Ramda with 82.34%</summary>
16201
16202```text
16203const R = require('../../dist/rambda.js')
16204
16205const test = [
16206 {
16207 label: 'Rambda',
16208 fn: () => {
16209 R.test(/\s/g, 'x y z')
16210 R.test(/\s/g)('x y z')
16211 },
16212 },
16213 {
16214 label: 'Ramda',
16215 fn: () => {
16216 Ramda.test(/\s/g, 'x y z')
16217 Ramda.test(/\s/g)('x y z')
16218 },
16219 },
16220]
16221```
16222
16223</details>
16224
16225[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#test)
16226
16227### times
16228
16229```typescript
16230
16231times<T>(fn: (i: number) => T, howMany: number): T[]
16232```
16233
16234It returns the result of applying function `fn` over members of range array.
16235
16236The range array includes numbers between `0` and `howMany`(exclusive).
16237
16238<details>
16239
16240<summary>All Typescript definitions</summary>
16241
16242```typescript
16243times<T>(fn: (i: number) => T, howMany: number): T[];
16244times<T>(fn: (i: number) => T): (howMany: number) => T[];
16245```
16246
16247</details>
16248
16249<details>
16250
16251<summary><strong>R.times</strong> source</summary>
16252
16253```javascript
16254import {map} from './map'
16255import {range} from './range'
16256
16257export function times(fn, howMany) {
16258 if (arguments.length === 1) return _howMany => times(fn, _howMany)
16259 if (!Number.isInteger(howMany) || howMany < 0) {
16260 throw new RangeError('n must be an integer')
16261 }
16262
16263 return map(fn, range(0, howMany))
16264}
16265```
16266
16267</details>
16268
16269<details>
16270
16271<summary><strong>Tests</strong></summary>
16272
16273```javascript
16274import assert from 'assert'
16275
16276import {identity} from './identity'
16277import {times} from './times'
16278
16279test('happy', () => {
16280 const result = times(identity, 5)
16281
16282 expect(result).toEqual([0, 1, 2, 3, 4])
16283})
16284
16285test('with bad input', () => {
16286 assert.throws(() => {
16287 times(3)('cheers!')
16288 }, RangeError)
16289 assert.throws(() => {
16290 times(identity, -1)
16291 }, RangeError)
16292})
16293
16294test('curry', () => {
16295 const result = times(identity)(5)
16296
16297 expect(result).toEqual([0, 1, 2, 3, 4])
16298})
16299```
16300
16301</details>
16302
16303<details>
16304
16305<summary><strong>Typescript</strong> test</summary>
16306
16307```typescript
16308import {times, identity} from 'rambda'
16309
16310describe('R.times', () => {
16311 it('happy', () => {
16312 const result = times(identity, 5)
16313 result // $ExpectType number[]
16314 })
16315})
16316```
16317
16318</details>
16319
16320[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#times)
16321
16322### toLower
16323
16324```typescript
16325
16326toLower<S extends string>(str: S): Lowercase<S>
16327```
16328
16329<details>
16330
16331<summary>All Typescript definitions</summary>
16332
16333```typescript
16334toLower<S extends string>(str: S): Lowercase<S>;
16335toLower(str: string): string;
16336```
16337
16338</details>
16339
16340<details>
16341
16342<summary><strong>R.toLower</strong> source</summary>
16343
16344```javascript
16345export function toLower(str) {
16346 return str.toLowerCase()
16347}
16348```
16349
16350</details>
16351
16352<details>
16353
16354<summary><strong>Tests</strong></summary>
16355
16356```javascript
16357import {toLower} from './toLower'
16358
16359test('toLower', () => {
16360 expect(toLower('FOO|BAR|BAZ')).toEqual('foo|bar|baz')
16361})
16362```
16363
16364</details>
16365
16366[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#toLower)
16367
16368### toPairs
16369
16370```typescript
16371
16372toPairs<O extends object, K extends Extract<keyof O, string | number>>(obj: O): Array<{ [key in K]: [`${key}`, O[key]] }[K]>
16373```
16374
16375It transforms an object to a list.
16376
16377<details>
16378
16379<summary>All Typescript definitions</summary>
16380
16381```typescript
16382toPairs<O extends object, K extends Extract<keyof O, string | number>>(obj: O): Array<{ [key in K]: [`${key}`, O[key]] }[K]>;
16383toPairs<S>(obj: Record<string | number, S>): Array<[string, S]>;
16384```
16385
16386</details>
16387
16388<details>
16389
16390<summary><strong>R.toPairs</strong> source</summary>
16391
16392```javascript
16393export function toPairs(obj) {
16394 return Object.entries(obj)
16395}
16396```
16397
16398</details>
16399
16400<details>
16401
16402<summary><strong>Tests</strong></summary>
16403
16404```javascript
16405import {toPairs} from './toPairs'
16406
16407const obj = {
16408 a: 1,
16409 b: 2,
16410 c: [3, 4],
16411}
16412const expected = [
16413 ['a', 1],
16414 ['b', 2],
16415 ['c', [3, 4]],
16416]
16417
16418test('happy', () => {
16419 expect(toPairs(obj)).toEqual(expected)
16420})
16421```
16422
16423</details>
16424
16425<details>
16426
16427<summary><strong>Typescript</strong> test</summary>
16428
16429```typescript
16430import {toPairs} from 'rambda'
16431
16432const obj = {
16433 a: 1,
16434 b: 2,
16435 c: [3, 4],
16436}
16437
16438describe('R.toPairs', () => {
16439 it('happy', () => {
16440 const result = toPairs(obj)
16441
16442 result // $ExpectType (["b", number] | ["a", number] | ["c", number[]])[]
16443 })
16444})
16445```
16446
16447</details>
16448
16449[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#toPairs)
16450
16451### toString
16452
16453```typescript
16454
16455toString(x: unknown): string
16456```
16457
16458<details>
16459
16460<summary>All Typescript definitions</summary>
16461
16462```typescript
16463toString(x: unknown): string;
16464```
16465
16466</details>
16467
16468<details>
16469
16470<summary><strong>R.toString</strong> source</summary>
16471
16472```javascript
16473export function toString(x) {
16474 return x.toString()
16475}
16476```
16477
16478</details>
16479
16480<details>
16481
16482<summary><strong>Tests</strong></summary>
16483
16484```javascript
16485import {toString} from './toString'
16486
16487test('happy', () => {
16488 expect(toString([1, 2, 3])).toEqual('1,2,3')
16489})
16490```
16491
16492</details>
16493
16494[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#toString)
16495
16496### toUpper
16497
16498```typescript
16499
16500toUpper<S extends string>(str: S): Uppercase<S>
16501```
16502
16503<details>
16504
16505<summary>All Typescript definitions</summary>
16506
16507```typescript
16508toUpper<S extends string>(str: S): Uppercase<S>;
16509toUpper(str: string): string;
16510```
16511
16512</details>
16513
16514<details>
16515
16516<summary><strong>R.toUpper</strong> source</summary>
16517
16518```javascript
16519export function toUpper(str) {
16520 return str.toUpperCase()
16521}
16522```
16523
16524</details>
16525
16526<details>
16527
16528<summary><strong>Tests</strong></summary>
16529
16530```javascript
16531import {toUpper} from './toUpper'
16532
16533test('toUpper', () => {
16534 expect(toUpper('foo|bar|baz')).toEqual('FOO|BAR|BAZ')
16535})
16536```
16537
16538</details>
16539
16540[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#toUpper)
16541
16542### transpose
16543
16544```typescript
16545
16546transpose<T>(list: (T[])[]): (T[])[]
16547```
16548
16549<details>
16550
16551<summary>All Typescript definitions</summary>
16552
16553```typescript
16554transpose<T>(list: (T[])[]): (T[])[];
16555```
16556
16557</details>
16558
16559<details>
16560
16561<summary><strong>R.transpose</strong> source</summary>
16562
16563```javascript
16564import {_isArray} from './_internals/_isArray'
16565
16566export function transpose(array) {
16567 return array.reduce((acc, el) => {
16568 el.forEach((nestedEl, i) =>
16569 _isArray(acc[i]) ? acc[i].push(nestedEl) : acc.push([nestedEl])
16570 )
16571
16572 return acc
16573 }, [])
16574}
16575```
16576
16577</details>
16578
16579<details>
16580
16581<summary><strong>Tests</strong></summary>
16582
16583```javascript
16584import {transpose} from './transpose'
16585
16586test('happy', () => {
16587 const input = [
16588 ['a', 1],
16589 ['b', 2],
16590 ['c', 3],
16591 ]
16592
16593 expect(transpose(input)).toEqual([
16594 ['a', 'b', 'c'],
16595 [1, 2, 3],
16596 ])
16597})
16598
16599test('when rows are shorter', () => {
16600 const actual = transpose([[10, 11], [20], [], [30, 31, 32]])
16601 const expected = [[10, 20, 30], [11, 31], [32]]
16602 expect(actual).toEqual(expected)
16603})
16604
16605test('with empty array', () => {
16606 expect(transpose([])).toEqual([])
16607})
16608
16609test('array with falsy values', () => {
16610 const actual = transpose([
16611 [true, false, undefined, null],
16612 [null, undefined, false, true],
16613 ])
16614 const expected = [
16615 [true, null],
16616 [false, undefined],
16617 [undefined, false],
16618 [null, true],
16619 ]
16620 expect(actual).toEqual(expected)
16621})
16622```
16623
16624</details>
16625
16626<details>
16627
16628<summary><strong>Typescript</strong> test</summary>
16629
16630```typescript
16631import {transpose} from 'rambda'
16632
16633const input = [
16634 ['a', 1],
16635 ['b', 2],
16636 ['c', 3],
16637]
16638
16639describe('R.transpose', () => {
16640 it('happy', () => {
16641 const result = transpose(input)
16642
16643 result // $ExpectType (string | number)[][]
16644 })
16645})
16646```
16647
16648</details>
16649
16650[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#transpose)
16651
16652### trim
16653
16654```typescript
16655
16656trim(str: string): string
16657```
16658
16659<details>
16660
16661<summary>All Typescript definitions</summary>
16662
16663```typescript
16664trim(str: string): string;
16665```
16666
16667</details>
16668
16669<details>
16670
16671<summary><strong>R.trim</strong> source</summary>
16672
16673```javascript
16674export function trim(str) {
16675 return str.trim()
16676}
16677```
16678
16679</details>
16680
16681<details>
16682
16683<summary><strong>Tests</strong></summary>
16684
16685```javascript
16686import {trim} from './trim'
16687
16688test('trim', () => {
16689 expect(trim(' foo ')).toEqual('foo')
16690})
16691```
16692
16693</details>
16694
16695[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#trim)
16696
16697### tryCatch
16698
16699```typescript
16700
16701tryCatch<T, U>(
16702 fn: (input: T) => U,
16703 fallback: U
16704): (input: T) => U
16705```
16706
16707It returns function that runs `fn` in `try/catch` block. If there was an error, then `fallback` is used to return the result. Note that `fn` can be value or asynchronous/synchronous function(unlike `Ramda` where fallback can only be a synchronous function).
16708
16709<details>
16710
16711<summary>All Typescript definitions</summary>
16712
16713```typescript
16714tryCatch<T, U>(
16715 fn: (input: T) => U,
16716 fallback: U
16717): (input: T) => U;
16718tryCatch<T, U>(
16719 fn: (input: T) => U,
16720 fallback: (input: T) => U
16721): (input: T) => U;
16722tryCatch<T>(
16723 fn: (input: any) => Promise<any>,
16724 fallback: T
16725): (input: any) => Promise<T>;
16726tryCatch<T>(
16727 fn: (input: any) => Promise<any>,
16728 fallback: (input: any) => Promise<any>,
16729): (input: any) => Promise<T>;
16730```
16731
16732</details>
16733
16734<details>
16735
16736<summary><strong>R.tryCatch</strong> source</summary>
16737
16738```javascript
16739import {isFunction} from './isFunction'
16740
16741export function tryCatch(fn, fallback) {
16742 if (!isFunction(fn)) {
16743 throw new Error(`R.tryCatch | fn '${fn}'`)
16744 }
16745 const passFallback = isFunction(fallback)
16746
16747 return (...inputs) => {
16748 try {
16749 return fn(...inputs)
16750 } catch (e) {
16751 return passFallback ? fallback(e, ...inputs) : fallback
16752 }
16753 }
16754}
16755```
16756
16757</details>
16758
16759<details>
16760
16761<summary><strong>Tests</strong></summary>
16762
16763```javascript
16764import {tryCatch as tryCatchRamda} from 'ramda'
16765
16766import {compareCombinations} from './_internals/testUtils'
16767import {prop} from './prop'
16768import {tryCatch} from './tryCatch'
16769
16770test('happy', () => {
16771 const fn = () => {
16772 throw new Error('foo')
16773 }
16774 const result = tryCatch(fn, () => true)()
16775 expect(result).toBeTrue()
16776})
16777
16778test('when fallback is used', () => {
16779 const fn = x => x.x
16780
16781 expect(tryCatch(fn, false)(null)).toBeFalse()
16782})
16783
16784test('with json parse', () => {
16785 const good = () => JSON.parse(JSON.stringify({a: 1}))
16786 const bad = () => JSON.parse('a{a')
16787
16788 expect(tryCatch(good, 1)()).toEqual({a: 1})
16789 expect(tryCatch(bad, 1)()).toBe(1)
16790})
16791
16792test('when fallback is function', () => {
16793 const fn = x => x.x
16794
16795 expect(tryCatch(fn, () => 1)(null)).toBe(1)
16796})
16797
16798test('when fn is used', () => {
16799 const fn = prop('x')
16800
16801 expect(tryCatch(fn, false)({})).toBe(undefined)
16802 expect(tryCatch(fn, false)({x: 1})).toBe(1)
16803})
16804
16805test('fallback receives error object and all initial inputs', () => {
16806 function thrower(a, b, c) {
16807 void c
16808 throw new Error('throwerError')
16809 }
16810
16811 function catchFn(e, a, b, c) {
16812 return [e.message, a, b, c].join('|')
16813 }
16814
16815 const willThrow = tryCatch(thrower, catchFn)
16816 const result = willThrow('A', 'B', 'C')
16817 expect(result).toBe('throwerError|A|B|C')
16818})
16819
16820test('fallback receives error object', () => {
16821 function throwFn() {
16822 throw new Error(10)
16823 }
16824
16825 function eCatcher(e, a, b) {
16826 return e.message
16827 }
16828
16829 const willThrow = tryCatch(throwFn, eCatcher)
16830 expect(willThrow([])).toBe('10')
16831 expect(willThrow([{}, {}, {}])).toBe('10')
16832})
16833
16834const possibleFns = [
16835 null,
16836 () => 1,
16837 () => 0,
16838 () => JSON.parse('{a:1'),
16839 () => {
16840 const x = {}
16841
16842 return x.x
16843 },
16844 x => x.foo,
16845 () => {
16846 throw new Error('foo')
16847 },
16848]
16849
16850const possibleCatchers = [
16851 null,
16852 e => e.message.length,
16853 (e, ...inputs) => `${e.message.length} ${inputs.length}`,
16854 () => {
16855 throw new Error('bar')
16856 },
16857]
16858
16859const possibleInputs = [null, {}, {foo: 1}]
16860
16861describe('brute force', () => {
16862 compareCombinations({
16863 returnsFunctionFlag: true,
16864 firstInput: possibleFns,
16865 callback: errorsCounters => {
16866 expect(errorsCounters).toMatchInlineSnapshot(`
16867 Object {
16868 "ERRORS_MESSAGE_MISMATCH": 0,
16869 "ERRORS_TYPE_MISMATCH": 12,
16870 "RESULTS_MISMATCH": 0,
16871 "SHOULD_NOT_THROW": 0,
16872 "SHOULD_THROW": 7,
16873 "TOTAL_TESTS": 84,
16874 }
16875 `)
16876 },
16877 secondInput: possibleCatchers,
16878 thirdInput: possibleInputs,
16879 fn: tryCatch,
16880 fnRamda: tryCatchRamda,
16881 })
16882})
16883```
16884
16885</details>
16886
16887<details>
16888
16889<summary><strong>Typescript</strong> test</summary>
16890
16891```typescript
16892import {tryCatch, delay} from 'rambda'
16893
16894describe('R.tryCatch', () => {
16895 it('synchronous', () => {
16896 const fn = (x: any) => x.x === 1
16897
16898 const result = tryCatch(fn, false)(null)
16899 result // $ExpectType boolean
16900 })
16901 it('synchronous + fallback is function', () => {
16902 const fn = (x: any) => typeof x.x
16903 const fallback = (x: any) => typeof x
16904 const result = tryCatch<any, string>(fn, fallback)(null)
16905 result // $ExpectType string
16906 })
16907
16908 it('asynchronous', async() => {
16909 const fn = async(input: any) => {
16910 return typeof JSON.parse('{a:')
16911 }
16912 const result = await tryCatch<string>(fn, 'fallback')(100)
16913 result // $ExpectType string
16914 })
16915
16916 it('asynchronous + fallback is asynchronous', async() => {
16917 const fn = async(input: any) => {
16918 await delay(100)
16919 return JSON.parse(`{a:${input}`)
16920 }
16921 const fallback = async(input: any) => {
16922 await delay(100)
16923 return 'foo'
16924 }
16925 const result = await tryCatch<string>(fn, fallback)(100)
16926 result // $ExpectType string
16927 })
16928})
16929```
16930
16931</details>
16932
16933[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#tryCatch)
16934
16935### type
16936
16937```typescript
16938
16939type(x: any): RambdaTypes
16940```
16941
16942It accepts any input and it returns its type.
16943
16944<details>
16945
16946<summary>All Typescript definitions</summary>
16947
16948```typescript
16949type(x: any): RambdaTypes;
16950```
16951
16952</details>
16953
16954<details>
16955
16956<summary><strong>R.type</strong> source</summary>
16957
16958```javascript
16959export function type(input) {
16960 if (input === null) {
16961 return 'Null'
16962 } else if (input === undefined) {
16963 return 'Undefined'
16964 } else if (Number.isNaN(input)) {
16965 return 'NaN'
16966 }
16967 const typeResult = Object.prototype.toString.call(input).slice(8, -1)
16968
16969 return typeResult === 'AsyncFunction' ? 'Async' : typeResult
16970}
16971```
16972
16973</details>
16974
16975<details>
16976
16977<summary><strong>Tests</strong></summary>
16978
16979```javascript
16980import {type} from './type'
16981import {type as typeRamda} from 'ramda'
16982
16983test('with symbol', () => {
16984 expect(type(Symbol())).toBe('Symbol')
16985})
16986
16987test('with simple promise', () => {
16988 expect(type(Promise.resolve(1))).toBe('Promise')
16989})
16990
16991test('with new Boolean', () => {
16992 expect(type(new Boolean(true))).toBe('Boolean')
16993})
16994
16995test('with new String', () => {
16996 expect(type(new String('I am a String object'))).toEqual('String')
16997})
16998
16999test('with new Number', () => {
17000 expect(type(new Number(1))).toBe('Number')
17001})
17002
17003test('with error', () => {
17004 expect(type(Error(`foo`))).toBe('Error')
17005 expect(typeRamda(Error(`foo`))).toBe('Error')
17006})
17007
17008test('with error - wrong @types/ramda test', () => {
17009 // @types/ramda expect the result to be 'Error' but it is not
17010 class ExtendedError extends Error {}
17011 expect(type(ExtendedError)).toBe('Function')
17012 expect(typeRamda(ExtendedError)).toBe('Function')
17013})
17014
17015test('with new promise', () => {
17016 const delay = ms =>
17017 new Promise(resolve => {
17018 setTimeout(() => {
17019 resolve(ms + 110)
17020 }, ms)
17021 })
17022
17023 expect(type(delay(10))).toEqual('Promise')
17024})
17025
17026test('async function', () => {
17027 expect(type(async () => {})).toEqual('Async')
17028})
17029
17030test('async arrow', () => {
17031 const asyncArrow = async () => {}
17032 expect(type(asyncArrow)).toBe('Async')
17033})
17034
17035test('function', () => {
17036 const fn1 = () => {}
17037 const fn2 = function () {}
17038
17039 function fn3() {}
17040
17041 ;[() => {}, fn1, fn2, fn3].map(val => {
17042 expect(type(val)).toEqual('Function')
17043 })
17044})
17045
17046test('object', () => {
17047 expect(type({})).toEqual('Object')
17048})
17049
17050test('number', () => {
17051 expect(type(1)).toEqual('Number')
17052})
17053
17054test('boolean', () => {
17055 expect(type(false)).toEqual('Boolean')
17056})
17057
17058test('string', () => {
17059 expect(type('foo')).toEqual('String')
17060})
17061
17062test('null', () => {
17063 expect(type(null)).toEqual('Null')
17064})
17065
17066test('array', () => {
17067 expect(type([])).toEqual('Array')
17068 expect(type([1, 2, 3])).toEqual('Array')
17069})
17070
17071test('regex', () => {
17072 expect(type(/\s/g)).toEqual('RegExp')
17073})
17074
17075test('undefined', () => {
17076 expect(type(undefined)).toEqual('Undefined')
17077})
17078
17079test('not a number', () => {
17080 expect(type(Number('s'))).toBe('NaN')
17081})
17082
17083test('set', () => {
17084 const exampleSet = new Set([1, 2, 3])
17085 expect(type(exampleSet)).toBe('Set')
17086 expect(typeRamda(exampleSet)).toBe('Set')
17087})
17088
17089test('function inside object 1', () => {
17090 const obj = {
17091 f() {
17092 return 4
17093 },
17094 }
17095
17096 expect(type(obj.f)).toBe('Function')
17097 expect(typeRamda(obj.f)).toBe('Function')
17098})
17099
17100test('function inside object 2', () => {
17101 const name = 'f'
17102 const obj = {
17103 [name]() {
17104 return 4
17105 },
17106 }
17107 expect(type(obj.f)).toBe('Function')
17108 expect(typeRamda(obj.f)).toBe('Function')
17109})
17110```
17111
17112</details>
17113
17114<details>
17115
17116<summary><strong>Typescript</strong> test</summary>
17117
17118```typescript
17119import {type} from 'rambda'
17120
17121describe('R.type', () => {
17122 it('happy', () => {
17123 const result = type(4)
17124
17125 result // $ExpectType RambdaTypes
17126 })
17127})
17128```
17129
17130</details>
17131
17132<details>
17133
17134<summary>Rambda is faster than Ramda with 48.6%</summary>
17135
17136```text
17137const R = require('../../dist/rambda.js')
17138
17139const {listOfVariousTypes} = require('./_utils')
17140
17141const limit = 1000
17142
17143function applyBenchmark(fn) {
17144 listOfVariousTypes.forEach(mode => {
17145 Array(limit)
17146 .fill(mode)
17147 .forEach(x => fn(x))
17148 })
17149}
17150
17151const test = [
17152 {
17153 label: 'Rambda',
17154 fn: () => {
17155 applyBenchmark(R.type)
17156 },
17157 },
17158 {
17159 label: 'Ramda',
17160 fn: () => {
17161 applyBenchmark(Ramda.type)
17162 },
17163 },
17164]
17165```
17166
17167</details>
17168
17169[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#type)
17170
17171### unapply
17172
17173```typescript
17174
17175unapply<T = any>(fn: (args: any[]) => T): (...args: any[]) => T
17176```
17177
17178It calls a function `fn` with the list of values of the returned function.
17179
17180`R.unapply` is the opposite of `R.apply` method.
17181
17182<details>
17183
17184<summary>All Typescript definitions</summary>
17185
17186```typescript
17187unapply<T = any>(fn: (args: any[]) => T): (...args: any[]) => T;
17188```
17189
17190</details>
17191
17192<details>
17193
17194<summary><strong>R.unapply</strong> source</summary>
17195
17196```javascript
17197export function unapply(fn) {
17198 return function (...args) {
17199 return fn.call(this, args)
17200 }
17201}
17202```
17203
17204</details>
17205
17206<details>
17207
17208<summary><strong>Tests</strong></summary>
17209
17210```javascript
17211import {apply} from './apply'
17212import {unapply} from './unapply'
17213import {identity} from './identity'
17214import {converge} from './converge'
17215import {prop} from './prop'
17216import {sum} from './sum'
17217
17218test('happy', () => {
17219 const fn = unapply(identity)
17220 expect(fn(1, 2, 3)).toEqual([1, 2, 3])
17221 expect(fn()).toEqual([])
17222})
17223
17224test('returns a function which is always passed one argument', function () {
17225 const fn = unapply(function () {
17226 return arguments.length
17227 })
17228 expect(fn('x')).toEqual(1)
17229 expect(fn('x', 'y')).toEqual(1)
17230 expect(fn('x', 'y', 'z')).toEqual(1)
17231})
17232
17233test('forwards arguments to decorated function as an array', function () {
17234 const fn = unapply(function (xs) {
17235 return '[' + xs + ']'
17236 })
17237 expect(fn(2)).toEqual('[2]')
17238 expect(fn(2, 4)).toEqual('[2,4]')
17239 expect(fn(2, 4, 6)).toEqual('[2,4,6]')
17240})
17241
17242test('returns a function with length 0', function () {
17243 const fn = unapply(identity)
17244 expect(fn.length).toEqual(0)
17245})
17246
17247test('is the inverse of R.apply', function () {
17248 let a, b, c, d, e, f, g, n
17249 const rand = function () {
17250 return Math.floor(200 * Math.random()) - 100
17251 }
17252
17253 f = Math.max
17254 g = unapply(apply(f))
17255 n = 1
17256 while (n <= 100) {
17257 a = rand()
17258 b = rand()
17259 c = rand()
17260 d = rand()
17261 e = rand()
17262 expect(f(a, b, c, d, e)).toEqual(g(a, b, c, d, e))
17263 n += 1
17264 }
17265
17266 f = function (xs) {
17267 return '[' + xs + ']'
17268 }
17269 g = apply(unapply(f))
17270 n = 1
17271 while (n <= 100) {
17272 a = rand()
17273 b = rand()
17274 c = rand()
17275 d = rand()
17276 e = rand()
17277 expect(f([a, b, c, d, e])).toEqual(g([a, b, c, d, e]))
17278 n += 1
17279 }
17280})
17281
17282test('it works with converge', () => {
17283 const fn = unapply(sum)
17284 const convergeFn = converge(fn, [prop('a'), prop('b'), prop('c')])
17285 const obj = {
17286 a: 1337,
17287 b: 42,
17288 c: 1,
17289 }
17290 const expected = 1337 + 42 + 1
17291 expect(convergeFn(obj)).toEqual(expected)
17292})
17293```
17294
17295</details>
17296
17297<details>
17298
17299<summary><strong>Typescript</strong> test</summary>
17300
17301```typescript
17302import {join, unapply, sum} from 'rambda'
17303
17304describe('R.unapply', () => {
17305 it('happy', () => {
17306 const fn = unapply(sum)
17307
17308 fn(1, 2, 3) // $ExpectType number
17309 })
17310
17311 it('joins a string', () => {
17312 const fn = unapply(join(''))
17313
17314 fn('s', 't', 'r', 'i', 'n', 'g') // $ExpectType string
17315 })
17316})
17317```
17318
17319</details>
17320
17321[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#unapply)
17322
17323### union
17324
17325```typescript
17326
17327union<T>(x: T[], y: T[]): T[]
17328```
17329
17330It takes two lists and return a new list containing a merger of both list with removed duplicates.
17331
17332`R.equals` is used to compare for duplication.
17333
17334<details>
17335
17336<summary>All Typescript definitions</summary>
17337
17338```typescript
17339union<T>(x: T[], y: T[]): T[];
17340union<T>(x: T[]): (y: T[]) => T[];
17341```
17342
17343</details>
17344
17345<details>
17346
17347<summary><strong>R.union</strong> source</summary>
17348
17349```javascript
17350import {includes} from './includes'
17351import {cloneList} from './_internals/cloneList'
17352
17353export function union(x, y) {
17354 if (arguments.length === 1) return _y => union(x, _y)
17355
17356 const toReturn = cloneList(x)
17357
17358 y.forEach(yInstance => {
17359 if (!includes(yInstance, x)) toReturn.push(yInstance)
17360 })
17361
17362 return toReturn
17363}
17364```
17365
17366</details>
17367
17368<details>
17369
17370<summary><strong>Tests</strong></summary>
17371
17372```javascript
17373import {union} from './union'
17374
17375test('happy', () => {
17376 expect(union([1, 2], [2, 3])).toEqual([1, 2, 3])
17377})
17378
17379test('with list of objects', () => {
17380 const list1 = [{a: 1}, {a: 2}]
17381 const list2 = [{a: 2}, {a: 3}]
17382 const result = union(list1)(list2)
17383})
17384```
17385
17386</details>
17387
17388<details>
17389
17390<summary><strong>Typescript</strong> test</summary>
17391
17392```typescript
17393import {union} from 'rambda'
17394
17395describe('R.union', () => {
17396 it('happy', () => {
17397 const result = union([1, 2], [2, 3])
17398
17399 result // $ExpectType number[]
17400 })
17401 it('with array of objects - case 1', () => {
17402 const list1 = [{a: 1}, {a: 2}]
17403 const list2 = [{a: 2}, {a: 3}]
17404 const result = union(list1, list2)
17405 result // $ExpectType { a: number; }[]
17406 })
17407 it('with array of objects - case 2', () => {
17408 const list1 = [{a: 1, b: 1}, {a: 2}]
17409 const list2 = [{a: 2}, {a: 3, b: 3}]
17410 const result = union(list1, list2)
17411 result[0].a // $ExpectType number
17412 result[0].b // $ExpectType number | undefined
17413 })
17414})
17415
17416describe('R.union - curried', () => {
17417 it('happy', () => {
17418 const result = union([1, 2])([2, 3])
17419
17420 result // $ExpectType number[]
17421 })
17422 it('with array of objects - case 1', () => {
17423 const list1 = [{a: 1}, {a: 2}]
17424 const list2 = [{a: 2}, {a: 3}]
17425 const result = union(list1)(list2)
17426 result // $ExpectType { a: number; }[]
17427 })
17428 it('with array of objects - case 2', () => {
17429 const list1 = [{a: 1, b: 1}, {a: 2}]
17430 const list2 = [{a: 2}, {a: 3, b: 3}]
17431 const result = union(list1)(list2)
17432 result[0].a // $ExpectType number
17433 result[0].b // $ExpectType number | undefined
17434 })
17435})
17436```
17437
17438</details>
17439
17440[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#union)
17441
17442### uniq
17443
17444```typescript
17445
17446uniq<T>(list: T[]): T[]
17447```
17448
17449It returns a new array containing only one copy of each element of `list`.
17450
17451`R.equals` is used to determine equality.
17452
17453<details>
17454
17455<summary>All Typescript definitions</summary>
17456
17457```typescript
17458uniq<T>(list: T[]): T[];
17459```
17460
17461</details>
17462
17463<details>
17464
17465<summary><strong>R.uniq</strong> source</summary>
17466
17467```javascript
17468import {_Set} from './_internals/set'
17469
17470export function uniq(list) {
17471 const set = new _Set()
17472 const willReturn = []
17473 list.forEach(item => {
17474 if (set.checkUniqueness(item)) {
17475 willReturn.push(item)
17476 }
17477 })
17478
17479 return willReturn
17480}
17481```
17482
17483</details>
17484
17485<details>
17486
17487<summary><strong>Tests</strong></summary>
17488
17489```javascript
17490import {uniq} from './uniq'
17491import {uniq as uniqRamda} from 'ramda'
17492
17493test('happy', () => {
17494 const list = [1, 2, 3, 3, 3, 1, 2, 0]
17495 expect(uniq(list)).toEqual([1, 2, 3, 0])
17496})
17497
17498test('with object', () => {
17499 const list = [{a: 1}, {a: 2}, {a: 1}, {a: 2}]
17500 expect(uniq(list)).toEqual([{a: 1}, {a: 2}])
17501})
17502
17503test('with nested array', () => {
17504 expect(uniq([[42], [42]])).toEqual([[42]])
17505})
17506test('with booleans', () => {
17507 expect(uniq([[false], [false], [true]])).toEqual([[false], [true]])
17508})
17509
17510test('with falsy values', () => {
17511 expect(uniq([undefined, null])).toEqual([undefined, null])
17512})
17513
17514test('can distinct between string and number', () => {
17515 expect(uniq([1, '1'])).toEqual([1, '1'])
17516})
17517```
17518
17519</details>
17520
17521<details>
17522
17523<summary><strong>Typescript</strong> test</summary>
17524
17525```typescript
17526import {uniq} from 'rambda'
17527
17528describe('R.uniq', () => {
17529 it('happy', () => {
17530 const result = uniq([1, 2, 3, 3, 3, 1, 2, 0])
17531 result // $ExpectType number[]
17532 })
17533})
17534```
17535
17536</details>
17537
17538<details>
17539
17540<summary>Rambda is faster than Ramda with 90.24%</summary>
17541
17542```text
17543const R = require('../../dist/rambda.js')
17544
17545const {
17546 uniqListOfStrings,
17547 uniqListOfBooleans,
17548 uniqListOfNumbers,
17549 uniqListOfLists,
17550 uniqListOfObjects,
17551} = require('./_utils.js')
17552
17553const limit = 100
17554
17555const modes = [
17556 uniqListOfStrings(limit),
17557 uniqListOfBooleans(limit),
17558 uniqListOfNumbers(limit),
17559 uniqListOfLists(limit),
17560 uniqListOfObjects(limit),
17561]
17562
17563function applyBenchmark(fn, input) {
17564 fn(input)
17565}
17566
17567const tests = [
17568 {
17569 label: 'Rambda',
17570 fn: R.uniq,
17571 },
17572 {
17573 label: 'Ramda',
17574 fn: Ramda.uniq,
17575 },
17576]
17577```
17578
17579</details>
17580
17581[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#uniq)
17582
17583### uniqWith
17584
17585```typescript
17586
17587uniqWith<T, U>(predicate: (x: T, y: T) => boolean, list: T[]): T[]
17588```
17589
17590It returns a new array containing only one copy of each element in `list` according to `predicate` function.
17591
17592This predicate should return true, if two elements are equal.
17593
17594<details>
17595
17596<summary>All Typescript definitions</summary>
17597
17598```typescript
17599uniqWith<T, U>(predicate: (x: T, y: T) => boolean, list: T[]): T[];
17600uniqWith<T, U>(predicate: (x: T, y: T) => boolean): (list: T[]) => T[];
17601```
17602
17603</details>
17604
17605<details>
17606
17607<summary><strong>R.uniqWith</strong> source</summary>
17608
17609```javascript
17610function includesWith(predicate, target, list) {
17611 let willReturn = false
17612 let index = -1
17613
17614 while (++index < list.length && !willReturn) {
17615 const value = list[index]
17616
17617 if (predicate(target, value)) {
17618 willReturn = true
17619 }
17620 }
17621
17622 return willReturn
17623}
17624
17625export function uniqWith(predicate, list) {
17626 if (arguments.length === 1) return _list => uniqWith(predicate, _list)
17627
17628 let index = -1
17629 const willReturn = []
17630
17631 while (++index < list.length) {
17632 const value = list[index]
17633
17634 if (!includesWith(predicate, value, willReturn)) {
17635 willReturn.push(value)
17636 }
17637 }
17638
17639 return willReturn
17640}
17641```
17642
17643</details>
17644
17645<details>
17646
17647<summary><strong>Tests</strong></summary>
17648
17649```javascript
17650import {uniqWith} from './uniqWith'
17651import {uniqWith as uniqWithRamda} from 'ramda'
17652
17653const list = [{a: 1}, {a: 1}]
17654
17655test('happy', () => {
17656 const fn = (x, y) => x.a === y.a
17657
17658 const result = uniqWith(fn, list)
17659 expect(result).toEqual([{a: 1}])
17660})
17661
17662test('with list of strings', () => {
17663 const fn = (x, y) => x.length === y.length
17664 const list = ['0', '11', '222', '33', '4', '55']
17665 const result = uniqWith(fn)(list)
17666 const resultRamda = uniqWithRamda(fn, list)
17667 expect(result).toEqual(['0', '11', '222'])
17668 expect(resultRamda).toEqual(['0', '11', '222'])
17669})
17670```
17671
17672</details>
17673
17674<details>
17675
17676<summary><strong>Typescript</strong> test</summary>
17677
17678```typescript
17679import {uniqWith} from 'rambda'
17680
17681describe('R.uniqWith', () => {
17682 it('happy', () => {
17683 const list = [{a: 1}, {a: 1}]
17684
17685 const fn = (x: any, y: any) => x.a === y.a
17686
17687 const result = uniqWith(fn, list)
17688 result // $ExpectType { a: number; }[]
17689 })
17690})
17691```
17692
17693</details>
17694
17695<details>
17696
17697<summary>Rambda is slower than Ramda with 25.38%</summary>
17698
17699```text
17700const R = require('../../dist/rambda.js')
17701
17702const {
17703 uniqListOfStrings,
17704 uniqListOfBooleans,
17705 uniqListOfNumbers,
17706 uniqListOfLists,
17707 uniqListOfObjects,
17708} = require('./_utils.js')
17709
17710const limit = 100
17711
17712const modes = [
17713 [uniqListOfStrings(limit), (x, y) => x.length === y.length],
17714 [uniqListOfBooleans(limit), (x, y) => x === y],
17715 [uniqListOfNumbers(limit), (x, y) => x > y],
17716 [uniqListOfLists(limit), (x, y) => x.length === y.length],
17717 [
17718 uniqListOfObjects(limit),
17719 x => (x, y) => Object.keys(x).length === Object.keys(y).length,
17720 ],
17721]
17722
17723function applyBenchmark(fn, input) {
17724 return fn(input[1], input[0])
17725}
17726
17727const tests = [
17728 {
17729 label: 'Rambda',
17730 fn: R.uniqWith,
17731 },
17732 {
17733 label: 'Ramda',
17734 fn: Ramda.uniqWith,
17735 },
17736]
17737```
17738
17739</details>
17740
17741[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#uniqWith)
17742
17743### unless
17744
17745```typescript
17746
17747unless<T, U>(predicate: (x: T) => boolean, whenFalseFn: (x: T) => U, x: T): T | U
17748```
17749
17750The method returns function that will be called with argument `input`.
17751
17752If `predicate(input)` returns `false`, then the end result will be the outcome of `whenFalse(input)`.
17753
17754In the other case, the final output will be the `input` itself.
17755
17756<details>
17757
17758<summary>All Typescript definitions</summary>
17759
17760```typescript
17761unless<T, U>(predicate: (x: T) => boolean, whenFalseFn: (x: T) => U, x: T): T | U;
17762unless<T, U>(predicate: (x: T) => boolean, whenFalseFn: (x: T) => U): (x: T) => T | U;
17763unless<T>(predicate: (x: T) => boolean, whenFalseFn: (x: T) => T, x: T): T;
17764unless<T>(predicate: (x: T) => boolean, whenFalseFn: (x: T) => T): (x: T) => T;
17765```
17766
17767</details>
17768
17769<details>
17770
17771<summary><strong>R.unless</strong> source</summary>
17772
17773```javascript
17774export function unless(predicate, whenFalse) {
17775 if (arguments.length === 1) {
17776 return _whenFalse => unless(predicate, _whenFalse)
17777 }
17778
17779 return input => (predicate(input) ? input : whenFalse(input))
17780}
17781```
17782
17783</details>
17784
17785<details>
17786
17787<summary><strong>Tests</strong></summary>
17788
17789```javascript
17790import {inc} from './inc'
17791import {isNil} from './isNil'
17792import {unless} from './unless'
17793
17794test('happy', () => {
17795 const safeInc = unless(isNil, inc)
17796 expect(safeInc(null)).toBeNull()
17797 expect(safeInc(1)).toBe(2)
17798})
17799
17800test('curried', () => {
17801 const safeIncCurried = unless(isNil)(inc)
17802 expect(safeIncCurried(null)).toBeNull()
17803})
17804```
17805
17806</details>
17807
17808<details>
17809
17810<summary><strong>Typescript</strong> test</summary>
17811
17812```typescript
17813import {unless, inc} from 'rambda'
17814
17815describe('R.unless', () => {
17816 it('happy', () => {
17817 const fn = unless(x => x > 5, inc)
17818 const result = fn(1)
17819 result // $ExpectType number
17820 })
17821 it('with one explicit type', () => {
17822 const result = unless(
17823 x => {
17824 x // $ExpectType number
17825 return x > 5
17826 },
17827 x => {
17828 x // $ExpectType number
17829 return x + 1
17830 },
17831 1
17832 )
17833 result // $ExpectType number
17834 })
17835 it('with two different explicit types', () => {
17836 const result = unless(
17837 x => {
17838 x // $ExpectType number
17839 return x > 5
17840 },
17841 x => {
17842 x // $ExpectType number
17843 return `${x}-foo`
17844 },
17845 1
17846 )
17847 result // $ExpectType string | number
17848 })
17849})
17850
17851describe('R.unless - curried', () => {
17852 it('happy', () => {
17853 const fn = unless(x => x > 5, inc)
17854 const result = fn(1)
17855 result // $ExpectType number
17856 })
17857 it('with one explicit type', () => {
17858 const fn = unless<number>(
17859 x => {
17860 x // $ExpectType number
17861 return x > 5
17862 },
17863 x => {
17864 x // $ExpectType number
17865 return x + 1
17866 }
17867 )
17868 const result = fn(1)
17869 result // $ExpectType number
17870 })
17871 it('with two different explicit types', () => {
17872 const fn = unless<number, string>(
17873 x => {
17874 x // $ExpectType number
17875 return x > 5
17876 },
17877 x => {
17878 x // $ExpectType number
17879 return `${x}-foo`
17880 }
17881 )
17882 const result = fn(1)
17883 result // $ExpectType string | number
17884 })
17885})
17886```
17887
17888</details>
17889
17890[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#unless)
17891
17892### update
17893
17894```typescript
17895
17896update<T>(index: number, newValue: T, list: T[]): T[]
17897```
17898
17899It returns a copy of `list` with updated element at `index` with `newValue`.
17900
17901<details>
17902
17903<summary>All Typescript definitions</summary>
17904
17905```typescript
17906update<T>(index: number, newValue: T, list: T[]): T[];
17907update<T>(index: number, newValue: T): (list: T[]) => T[];
17908```
17909
17910</details>
17911
17912<details>
17913
17914<summary><strong>R.update</strong> source</summary>
17915
17916```javascript
17917import {curry} from './curry'
17918import {cloneList} from './_internals/cloneList'
17919
17920function updateFn(index, newValue, list) {
17921 const clone = cloneList(list)
17922 if (index === -1) return clone.fill(newValue, index)
17923
17924 return clone.fill(newValue, index, index + 1)
17925}
17926
17927export const update = curry(updateFn)
17928```
17929
17930</details>
17931
17932<details>
17933
17934<summary><strong>Tests</strong></summary>
17935
17936```javascript
17937import {update} from './update'
17938
17939const list = [1, 2, 3]
17940
17941test('happy', () => {
17942 const newValue = 8
17943 const index = 1
17944 const result = update(index, newValue, list)
17945 const curriedResult = update(index, newValue)(list)
17946 const tripleCurriedResult = update(index)(newValue)(list)
17947
17948 const expected = [1, 8, 3]
17949 expect(result).toEqual(expected)
17950 expect(curriedResult).toEqual(expected)
17951 expect(tripleCurriedResult).toEqual(expected)
17952})
17953
17954test('list has no such index', () => {
17955 const newValue = 8
17956 const index = 10
17957 const result = update(index, newValue, list)
17958
17959 expect(result).toEqual(list)
17960})
17961
17962test('with negative index', () => {
17963 expect(update(-1, 10, [1])).toEqual([10])
17964 expect(update(-1, 10, [])).toEqual([])
17965 expect(update(-1, 10, list)).toEqual([1, 2, 10])
17966 expect(update(-2, 10, list)).toEqual([1, 10, 3])
17967 expect(update(-3, 10, list)).toEqual([10, 2, 3])
17968})
17969```
17970
17971</details>
17972
17973<details>
17974
17975<summary><strong>Typescript</strong> test</summary>
17976
17977```typescript
17978import {update} from 'rambda'
17979
17980describe('R.update', () => {
17981 it('happy', () => {
17982 const result = update(1, 0, [1, 2, 3])
17983 result // $ExpectType number[]
17984 })
17985})
17986```
17987
17988</details>
17989
17990<details>
17991
17992<summary>Rambda is faster than Ramda with 52.35%</summary>
17993
17994```text
17995const R = require('../../dist/rambda.js')
17996
17997const list = [0, 1, 2]
17998const index = 1
17999const replacer = 7
18000
18001const update = [
18002 {
18003 label: 'Rambda',
18004 fn: () => {
18005 R.update(replacer, index, list)
18006 R.update(replacer, index)(list)
18007 R.update(replacer)(index)(list)
18008 },
18009 },
18010 {
18011 label: 'Ramda',
18012 fn: () => {
18013 Ramda.update(replacer, index, list)
18014 Ramda.update(replacer, index)(list)
18015 Ramda.update(replacer)(index)(list)
18016 },
18017 },
18018]
18019```
18020
18021</details>
18022
18023[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#update)
18024
18025### values
18026
18027```typescript
18028
18029values<T extends object, K extends keyof T>(obj: T): T[K][]
18030```
18031
18032With correct input, this is nothing more than `Object.values(obj)`. If `obj` is not an object, then it returns an empty array.
18033
18034<details>
18035
18036<summary>All Typescript definitions</summary>
18037
18038```typescript
18039values<T extends object, K extends keyof T>(obj: T): T[K][];
18040```
18041
18042</details>
18043
18044<details>
18045
18046<summary><strong>R.values</strong> source</summary>
18047
18048```javascript
18049import {type} from './type'
18050
18051export function values(obj) {
18052 if (type(obj) !== 'Object') return []
18053
18054 return Object.values(obj)
18055}
18056```
18057
18058</details>
18059
18060<details>
18061
18062<summary><strong>Tests</strong></summary>
18063
18064```javascript
18065import {values} from './values'
18066
18067test('happy', () => {
18068 expect(
18069 values({
18070 a: 1,
18071 b: 2,
18072 c: 3,
18073 })
18074 ).toEqual([1, 2, 3])
18075})
18076
18077test('with bad input', () => {
18078 expect(values(null)).toEqual([])
18079 expect(values(undefined)).toEqual([])
18080 expect(values(55)).toEqual([])
18081 expect(values('foo')).toEqual([])
18082 expect(values(true)).toEqual([])
18083 expect(values(false)).toEqual([])
18084 expect(values(NaN)).toEqual([])
18085 expect(values(Infinity)).toEqual([])
18086 expect(values([])).toEqual([])
18087})
18088```
18089
18090</details>
18091
18092<details>
18093
18094<summary><strong>Typescript</strong> test</summary>
18095
18096```typescript
18097import {values} from 'rambda'
18098
18099describe('R.values', () => {
18100 it('happy', () => {
18101 const result = values({
18102 a: 1,
18103 b: 2,
18104 c: 3,
18105 })
18106 result // $ExpectType number[]
18107 })
18108})
18109```
18110
18111</details>
18112
18113[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#values)
18114
18115### view
18116
18117```typescript
18118
18119view<T, U>(lens: Lens): (target: T) => U
18120```
18121
18122It returns the value of `lens` focus over `target` object.
18123
18124<details>
18125
18126<summary>All Typescript definitions</summary>
18127
18128```typescript
18129view<T, U>(lens: Lens): (target: T) => U;
18130view<T, U>(lens: Lens, target: T): U;
18131```
18132
18133</details>
18134
18135<details>
18136
18137<summary><strong>R.view</strong> source</summary>
18138
18139```javascript
18140const Const = x => ({
18141 x,
18142 map: fn => Const(x),
18143})
18144
18145export function view(lens, target) {
18146 if (arguments.length === 1) return _target => view(lens, _target)
18147
18148 return lens(Const)(target).x
18149}
18150```
18151
18152</details>
18153
18154<details>
18155
18156<summary><strong>Tests</strong></summary>
18157
18158```javascript
18159import {assoc} from './assoc'
18160import {lens} from './lens'
18161import {prop} from './prop'
18162import {view} from './view'
18163
18164const testObject = {foo: 'Led Zeppelin'}
18165const assocLens = lens(prop('foo'), assoc('foo'))
18166
18167test('happy', () => {
18168 expect(view(assocLens, testObject)).toEqual('Led Zeppelin')
18169})
18170```
18171
18172</details>
18173
18174<details>
18175
18176<summary><strong>Typescript</strong> test</summary>
18177
18178```typescript
18179import {lens, view, assoc} from 'rambda'
18180
18181interface Input {
18182 foo: string,
18183}
18184
18185const testObject: Input = {
18186 foo: 'Led Zeppelin',
18187}
18188
18189const fooLens = lens<Input, string, string>((x: Input) => {
18190 return x.foo
18191}, assoc('foo'))
18192
18193describe('R.view', () => {
18194 it('happt', () => {
18195 const result = view<Input, string>(fooLens, testObject)
18196 result // $ExpectType string
18197 })
18198})
18199```
18200
18201</details>
18202
18203<details>
18204
18205<summary>Rambda is faster than Ramda with 76.15%</summary>
18206
18207```text
18208const R = require('../../dist/rambda.js')
18209
18210const testObj = {a: 1}
18211
18212const last = [
18213 {
18214 label: 'Rambda',
18215 fn: () => {
18216 R.view(R.lensProp('a'), testObj)
18217 },
18218 },
18219 {
18220 label: 'Ramda',
18221 fn: () => {
18222 Ramda.view(Ramda.lensProp('a'), testObj)
18223 },
18224 },
18225]
18226```
18227
18228</details>
18229
18230[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#view)
18231
18232### when
18233
18234```typescript
18235
18236when<T, U>(predicate: (x: T) => boolean, whenTrueFn: (a: T) => U, input: T): T | U
18237```
18238
18239<details>
18240
18241<summary>All Typescript definitions</summary>
18242
18243```typescript
18244when<T, U>(predicate: (x: T) => boolean, whenTrueFn: (a: T) => U, input: T): T | U;
18245when<T, U>(predicate: (x: T) => boolean, whenTrueFn: (a: T) => U): (input: T) => T | U;
18246when<T, U>(predicate: (x: T) => boolean): ((whenTrueFn: (a: T) => U) => (input: T) => T | U);
18247```
18248
18249</details>
18250
18251<details>
18252
18253<summary><strong>R.when</strong> source</summary>
18254
18255```javascript
18256import {curry} from './curry'
18257
18258function whenFn(predicate, whenTrueFn, input) {
18259 if (!predicate(input)) return input
18260
18261 return whenTrueFn(input)
18262}
18263
18264export const when = curry(whenFn)
18265```
18266
18267</details>
18268
18269<details>
18270
18271<summary><strong>Tests</strong></summary>
18272
18273```javascript
18274import {add} from './add'
18275import {when} from './when'
18276
18277const predicate = x => typeof x === 'number'
18278
18279test('happy', () => {
18280 const fn = when(predicate, add(11))
18281 expect(fn(11)).toBe(22)
18282 expect(fn('foo')).toBe('foo')
18283})
18284```
18285
18286</details>
18287
18288<details>
18289
18290<summary><strong>Typescript</strong> test</summary>
18291
18292```typescript
18293import {when} from 'rambda'
18294
18295const predicate = (x: number) => x > 2
18296const whenTrueFn = (x: number) => String(x)
18297
18298describe('R.when', () => {
18299 it('happy', () => {
18300 const result = when(predicate, whenTrueFn, 1)
18301 result // $ExpectType string | 1
18302 })
18303
18304 it('curry 1', () => {
18305 const fn = when(predicate, whenTrueFn)
18306 const result = fn(1)
18307 result // $ExpectType string | number
18308 })
18309
18310 it('curry 2 require explicit types', () => {
18311 const fn = when<number, string>(predicate)(whenTrueFn)
18312 const result = fn(1)
18313 result // $ExpectType string | number
18314 })
18315})
18316```
18317
18318</details>
18319
18320[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#when)
18321
18322### where
18323
18324```typescript
18325
18326where<T, U>(conditions: T, input: U): boolean
18327```
18328
18329It returns `true` if all each property in `conditions` returns `true` when applied to corresponding property in `input` object.
18330
18331<details>
18332
18333<summary>All Typescript definitions</summary>
18334
18335```typescript
18336where<T, U>(conditions: T, input: U): boolean;
18337where<T>(conditions: T): <U>(input: U) => boolean;
18338where<ObjFunc2, U>(conditions: ObjFunc2, input: U): boolean;
18339where<ObjFunc2>(conditions: ObjFunc2): <U>(input: U) => boolean;
18340```
18341
18342</details>
18343
18344<details>
18345
18346<summary><strong>R.where</strong> source</summary>
18347
18348```javascript
18349export function where(conditions, input) {
18350 if (input === undefined) {
18351 return _input => where(conditions, _input)
18352 }
18353 let flag = true
18354 for (const prop in conditions) {
18355 const result = conditions[prop](input[prop])
18356 if (flag && result === false) {
18357 flag = false
18358 }
18359 }
18360
18361 return flag
18362}
18363```
18364
18365</details>
18366
18367<details>
18368
18369<summary><strong>Tests</strong></summary>
18370
18371```javascript
18372import {equals} from './equals'
18373import {where} from './where'
18374
18375test('when true', () => {
18376 const predicate = where({
18377 a: equals('foo'),
18378 b: equals('bar'),
18379 })
18380 expect(
18381 predicate({
18382 a: 'foo',
18383 b: 'bar',
18384 x: 11,
18385 y: 19,
18386 })
18387 ).toEqual(true)
18388})
18389
18390test('when false', () => {
18391 const predicate = where({
18392 a: equals('foo'),
18393 b: equals('baz'),
18394 })
18395 expect(
18396 predicate({
18397 a: 'foo',
18398 b: 'bar',
18399 x: 11,
18400 y: 19,
18401 })
18402 ).toEqual(false)
18403})
18404```
18405
18406</details>
18407
18408<details>
18409
18410<summary><strong>Typescript</strong> test</summary>
18411
18412```typescript
18413import {where, equals} from 'rambda'
18414
18415describe('R.where', () => {
18416 it('happy', () => {
18417 const input = {
18418 a: 'foo',
18419 b: 'bar',
18420 x: 11,
18421 y: 19,
18422 }
18423 const conditions = {
18424 a: equals('foo'),
18425 b: equals('bar'),
18426 }
18427 const result = where(conditions, input)
18428 const curriedResult = where(conditions)(input)
18429 result // $ExpectType boolean
18430 curriedResult // $ExpectType boolean
18431 })
18432})
18433```
18434
18435</details>
18436
18437[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#where)
18438
18439### whereEq
18440
18441```typescript
18442
18443whereEq<T, U>(condition: T, input: U): boolean
18444```
18445
18446It will return `true` if all of `input` object fully or partially include `rule` object.
18447
18448`R.equals` is used to determine equality.
18449
18450<details>
18451
18452<summary>All Typescript definitions</summary>
18453
18454```typescript
18455whereEq<T, U>(condition: T, input: U): boolean;
18456whereEq<T>(condition: T): <U>(input: U) => boolean;
18457```
18458
18459</details>
18460
18461<details>
18462
18463<summary><strong>R.whereEq</strong> source</summary>
18464
18465```javascript
18466import {equals} from './equals'
18467import {filter} from './filter'
18468
18469export function whereEq(condition, input) {
18470 if (arguments.length === 1) {
18471 return _input => whereEq(condition, _input)
18472 }
18473
18474 const result = filter(
18475 (conditionValue, conditionProp) =>
18476 equals(conditionValue, input[conditionProp]),
18477 condition
18478 )
18479
18480 return Object.keys(result).length === Object.keys(condition).length
18481}
18482```
18483
18484</details>
18485
18486<details>
18487
18488<summary><strong>Tests</strong></summary>
18489
18490```javascript
18491import {whereEq} from './whereEq'
18492
18493test('when true', () => {
18494 const condition = {a: 1}
18495 const input = {
18496 a: 1,
18497 b: 2,
18498 }
18499
18500 const result = whereEq(condition, input)
18501 const expectedResult = true
18502
18503 expect(result).toEqual(expectedResult)
18504})
18505
18506test('when false', () => {
18507 const condition = {a: 1}
18508 const input = {b: 2}
18509
18510 const result = whereEq(condition, input)
18511 const expectedResult = false
18512
18513 expect(result).toEqual(expectedResult)
18514})
18515
18516test('with nested object', () => {
18517 const condition = {a: {b: 1}}
18518 const input = {
18519 a: {b: 1},
18520 c: 2,
18521 }
18522
18523 const result = whereEq(condition)(input)
18524 const expectedResult = true
18525
18526 expect(result).toEqual(expectedResult)
18527})
18528
18529test('with wrong input', () => {
18530 const condition = {a: {b: 1}}
18531
18532 expect(() => whereEq(condition, null)).toThrowWithMessage(
18533 TypeError,
18534 `Cannot read properties of null (reading 'a')`
18535 )
18536})
18537```
18538
18539</details>
18540
18541<details>
18542
18543<summary><strong>Typescript</strong> test</summary>
18544
18545```typescript
18546import {whereEq} from 'rambda'
18547
18548describe('R.whereEq', () => {
18549 it('happy', () => {
18550 const result = whereEq({a: {b: 2}}, {b: 2})
18551 const curriedResult = whereEq({a: {b: 2}})({b: 2})
18552 result // $ExpectType boolean
18553 curriedResult // $ExpectType boolean
18554 })
18555})
18556```
18557
18558</details>
18559
18560[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#whereEq)
18561
18562### without
18563
18564```typescript
18565
18566without<T>(matchAgainst: T[], source: T[]): T[]
18567```
18568
18569It will return a new array, based on all members of `source` list that are not part of `matchAgainst` list.
18570
18571`R.equals` is used to determine equality.
18572
18573<details>
18574
18575<summary>All Typescript definitions</summary>
18576
18577```typescript
18578without<T>(matchAgainst: T[], source: T[]): T[];
18579without<T>(matchAgainst: T[]): (source: T[]) => T[];
18580```
18581
18582</details>
18583
18584<details>
18585
18586<summary><strong>R.without</strong> source</summary>
18587
18588```javascript
18589import {reduce} from './reduce'
18590import {_indexOf} from './equals'
18591
18592export function without(matchAgainst, source) {
18593 if (source === undefined) {
18594 return _source => without(matchAgainst, _source)
18595 }
18596
18597 return reduce(
18598 (prev, current) =>
18599 _indexOf(current, matchAgainst) > -1 ? prev : prev.concat(current),
18600 [],
18601 source
18602 )
18603}
18604```
18605
18606</details>
18607
18608<details>
18609
18610<summary><strong>Tests</strong></summary>
18611
18612```javascript
18613import {without} from './without'
18614import {without as withoutRamda} from 'ramda'
18615
18616test('should return a new list without values in the first argument', () => {
18617 const itemsToOmit = ['A', 'B', 'C']
18618 const collection = ['A', 'B', 'C', 'D', 'E', 'F']
18619
18620 expect(without(itemsToOmit, collection)).toEqual(['D', 'E', 'F'])
18621 expect(without(itemsToOmit)(collection)).toEqual(['D', 'E', 'F'])
18622})
18623
18624test('with list of objects', () => {
18625 const itemsToOmit = [{a: 1}, {c: 3}]
18626 const collection = [{a: 1}, {b: 2}, {c: 3}, {d: 4}]
18627 const expected = [{b: 2}, {d: 4}]
18628
18629 expect(without(itemsToOmit, collection)).toEqual(expected)
18630 expect(withoutRamda(itemsToOmit, collection)).toEqual(expected)
18631})
18632
18633test('ramda accepts string as target input while rambda throws', () => {
18634 expect(withoutRamda('0:1', ['0', '0:1'])).toEqual([])
18635 expect(() => without('0:1', ['0', '0:1'])).toThrow()
18636 expect(without(['0:1'], ['0', '0:1'])).toEqual(['0'])
18637})
18638
18639test('ramda test', () => {
18640 expect(without([1, 2])([1, 2, 1, 3, 4])).toEqual([3, 4])
18641})
18642```
18643
18644</details>
18645
18646<details>
18647
18648<summary><strong>Typescript</strong> test</summary>
18649
18650```typescript
18651import {without} from 'rambda'
18652
18653const itemsToOmit = ['A', 'B', 'C']
18654const collection = ['A', 'B', 'C', 'D', 'E', 'F']
18655
18656describe('R.without', () => {
18657 it('happy', () => {
18658 const result = without(itemsToOmit, collection)
18659
18660 result // $ExpectType string[]
18661 })
18662 it('curried', () => {
18663 const result = without(itemsToOmit)(collection)
18664
18665 result // $ExpectType string[]
18666 })
18667})
18668```
18669
18670</details>
18671
18672[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#without)
18673
18674### xor
18675
18676```typescript
18677
18678xor(x: boolean, y: boolean): boolean
18679```
18680
18681Logical XOR
18682
18683<details>
18684
18685<summary>All Typescript definitions</summary>
18686
18687```typescript
18688xor(x: boolean, y: boolean): boolean;
18689xor(y: boolean): (y: boolean) => boolean;
18690```
18691
18692</details>
18693
18694<details>
18695
18696<summary><strong>R.xor</strong> source</summary>
18697
18698```javascript
18699export function xor(a, b) {
18700 if (arguments.length === 1) return _b => xor(a, _b)
18701
18702 return (Boolean(a) && !b) || (Boolean(b) && !a)
18703}
18704```
18705
18706</details>
18707
18708<details>
18709
18710<summary><strong>Tests</strong></summary>
18711
18712```javascript
18713import {xor} from './xor'
18714
18715test('compares two values with exclusive or', () => {
18716 expect(xor(true, true)).toEqual(false)
18717 expect(xor(true, false)).toEqual(true)
18718 expect(xor(false, true)).toEqual(true)
18719 expect(xor(false, false)).toEqual(false)
18720})
18721
18722test('when both values are truthy, it should return false', () => {
18723 expect(xor(true, 'foo')).toEqual(false)
18724 expect(xor(42, true)).toEqual(false)
18725 expect(xor('foo', 42)).toEqual(false)
18726 expect(xor({}, true)).toEqual(false)
18727 expect(xor(true, [])).toEqual(false)
18728 expect(xor([], {})).toEqual(false)
18729 expect(xor(new Date(), true)).toEqual(false)
18730 expect(xor(true, Infinity)).toEqual(false)
18731 expect(xor(Infinity, new Date())).toEqual(false)
18732})
18733
18734test('when both values are falsy, it should return false', () => {
18735 expect(xor(null, false)).toEqual(false)
18736 expect(xor(false, undefined)).toEqual(false)
18737 expect(xor(undefined, null)).toEqual(false)
18738 expect(xor(0, false)).toEqual(false)
18739 expect(xor(false, NaN)).toEqual(false)
18740 expect(xor(NaN, 0)).toEqual(false)
18741 expect(xor('', false)).toEqual(false)
18742})
18743
18744test('when one argument is truthy and the other is falsy, it should return true', () => {
18745 expect(xor('foo', null)).toEqual(true)
18746 expect(xor(null, 'foo')).toEqual(true)
18747 expect(xor(undefined, 42)).toEqual(true)
18748 expect(xor(42, undefined)).toEqual(true)
18749 expect(xor(Infinity, NaN)).toEqual(true)
18750 expect(xor(NaN, Infinity)).toEqual(true)
18751 expect(xor({}, '')).toEqual(true)
18752 expect(xor('', {})).toEqual(true)
18753 expect(xor(new Date(), 0)).toEqual(true)
18754 expect(xor(0, new Date())).toEqual(true)
18755 expect(xor([], null)).toEqual(true)
18756 expect(xor(undefined, [])).toEqual(true)
18757})
18758```
18759
18760</details>
18761
18762<details>
18763
18764<summary><strong>Typescript</strong> test</summary>
18765
18766```typescript
18767import {xor} from 'rambda'
18768
18769describe('R.xor', () => {
18770 it('happy', () => {
18771 xor(true, false) // $ExpectType boolean
18772 })
18773 it('curry', () => {
18774 xor(true)(false) // $ExpectType boolean
18775 })
18776})
18777```
18778
18779</details>
18780
18781[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#xor)
18782
18783### zip
18784
18785```typescript
18786
18787zip<K, V>(x: K[], y: V[]): KeyValuePair<K, V>[]
18788```
18789
18790It will return a new array containing tuples of equally positions items from both `x` and `y` lists.
18791
18792The returned list will be truncated to match the length of the shortest supplied list.
18793
18794<details>
18795
18796<summary>All Typescript definitions</summary>
18797
18798```typescript
18799zip<K, V>(x: K[], y: V[]): KeyValuePair<K, V>[];
18800zip<K>(x: K[]): <V>(y: V[]) => KeyValuePair<K, V>[];
18801```
18802
18803</details>
18804
18805<details>
18806
18807<summary><strong>R.zip</strong> source</summary>
18808
18809```javascript
18810export function zip(left, right) {
18811 if (arguments.length === 1) return _right => zip(left, _right)
18812
18813 const result = []
18814 const length = Math.min(left.length, right.length)
18815
18816 for (let i = 0; i < length; i++) {
18817 result[i] = [left[i], right[i]]
18818 }
18819
18820 return result
18821}
18822```
18823
18824</details>
18825
18826<details>
18827
18828<summary><strong>Tests</strong></summary>
18829
18830```javascript
18831import {zip} from './zip'
18832
18833const array1 = [1, 2, 3]
18834const array2 = ['A', 'B', 'C']
18835
18836test('should return an array', () => {
18837 const actual = zip(array1)(array2)
18838 expect(actual).toBeInstanceOf(Array)
18839})
18840
18841test('should return and array or tuples', () => {
18842 const expected = [
18843 [1, 'A'],
18844 [2, 'B'],
18845 [3, 'C'],
18846 ]
18847 const actual = zip(array1, array2)
18848 expect(actual).toEqual(expected)
18849})
18850
18851test('should truncate result to length of shorted input list', () => {
18852 const expectedA = [
18853 [1, 'A'],
18854 [2, 'B'],
18855 ]
18856 const actualA = zip([1, 2], array2)
18857 expect(actualA).toEqual(expectedA)
18858
18859 const expectedB = [
18860 [1, 'A'],
18861 [2, 'B'],
18862 ]
18863 const actualB = zip(array1, ['A', 'B'])
18864 expect(actualB).toEqual(expectedB)
18865})
18866```
18867
18868</details>
18869
18870<details>
18871
18872<summary><strong>Typescript</strong> test</summary>
18873
18874```typescript
18875import {zip} from 'rambda'
18876
18877describe('R.zip', () => {
18878 it('happy', () => {
18879 const array1 = [1, 2, 3]
18880 const array2 = ['A', 'B', 'C']
18881
18882 const result = zip(array1)(array2)
18883 result // $ExpectType KeyValuePair<number, string>[]
18884 })
18885})
18886```
18887
18888</details>
18889
18890[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#zip)
18891
18892### zipObj
18893
18894```typescript
18895
18896zipObj<T, K extends string>(keys: K[], values: T[]): { [P in K]: T }
18897```
18898
18899It will return a new object with keys of `keys` array and values of `values` array.
18900
18901<details>
18902
18903<summary>All Typescript definitions</summary>
18904
18905```typescript
18906zipObj<T, K extends string>(keys: K[], values: T[]): { [P in K]: T };
18907zipObj<K extends string>(keys: K[]): <T>(values: T[]) => { [P in K]: T };
18908zipObj<T, K extends number>(keys: K[], values: T[]): { [P in K]: T };
18909zipObj<K extends number>(keys: K[]): <T>(values: T[]) => { [P in K]: T };
18910```
18911
18912</details>
18913
18914<details>
18915
18916<summary><strong>R.zipObj</strong> source</summary>
18917
18918```javascript
18919import {take} from './take'
18920
18921export function zipObj(keys, values) {
18922 if (arguments.length === 1) return yHolder => zipObj(keys, yHolder)
18923
18924 return take(values.length, keys).reduce((prev, xInstance, i) => {
18925 prev[xInstance] = values[i]
18926
18927 return prev
18928 }, {})
18929}
18930```
18931
18932</details>
18933
18934<details>
18935
18936<summary><strong>Tests</strong></summary>
18937
18938```javascript
18939import {equals} from './equals'
18940import {zipObj} from './zipObj'
18941
18942test('zipObj', () => {
18943 expect(zipObj(['a', 'b', 'c'], [1, 2, 3])).toEqual({
18944 a: 1,
18945 b: 2,
18946 c: 3,
18947 })
18948})
18949
18950test('0', () => {
18951 expect(zipObj(['a', 'b'])([1, 2, 3])).toEqual({
18952 a: 1,
18953 b: 2,
18954 })
18955})
18956
18957test('1', () => {
18958 expect(zipObj(['a', 'b', 'c'])([1, 2])).toEqual({
18959 a: 1,
18960 b: 2,
18961 })
18962})
18963
18964test('ignore extra keys', () => {
18965 const result = zipObj(['a', 'b', 'c', 'd', 'e', 'f'], [1, 2, 3])
18966 const expected = {
18967 a: 1,
18968 b: 2,
18969 c: 3,
18970 }
18971
18972 expect(equals(result, expected)).toBeTrue()
18973})
18974```
18975
18976</details>
18977
18978<details>
18979
18980<summary><strong>Typescript</strong> test</summary>
18981
18982```typescript
18983import {zipObj} from 'rambda'
18984
18985describe('R.zipObj', () => {
18986 it('happy', () => {
18987 // this is wrong since 24.10.2020 `@types/ramda` changes
18988 const result = zipObj(['a', 'b', 'c', 'd'], [1, 2, 3])
18989 result // $ExpectType { b: number; a: number; c: number; d: number; }
18990 })
18991 it('imported from @types/ramda', () => {
18992 const result = zipObj(['a', 'b', 'c'], [1, 2, 3])
18993 const curriedResult = zipObj(['a', 'b', 'c'])([1, 2, 3])
18994 result // $ExpectType { b: number; a: number; c: number; }
18995 curriedResult // $ExpectType { b: number; a: number; c: number; }
18996 })
18997})
18998```
18999
19000</details>
19001
19002[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#zipObj)
19003
19004### zipWith
19005
19006```typescript
19007
19008zipWith<T, U, TResult>(fn: (x: T, y: U) => TResult, list1: T[], list2: U[]): TResult[]
19009```
19010
19011<details>
19012
19013<summary>All Typescript definitions</summary>
19014
19015```typescript
19016zipWith<T, U, TResult>(fn: (x: T, y: U) => TResult, list1: T[], list2: U[]): TResult[];
19017zipWith<T, U, TResult>(fn: (x: T, y: U) => TResult, list1: T[]): (list2: U[]) => TResult[];
19018zipWith<T, U, TResult>(fn: (x: T, y: U) => TResult): (list1: T[], list2: U[]) => TResult[];
19019```
19020
19021</details>
19022
19023<details>
19024
19025<summary><strong>R.zipWith</strong> source</summary>
19026
19027```javascript
19028import {curry} from './curry'
19029import {take} from './take'
19030
19031function zipWithFn(fn, x, y) {
19032 return take(x.length > y.length ? y.length : x.length, x).map(
19033 (xInstance, i) => fn(xInstance, y[i])
19034 )
19035}
19036
19037export const zipWith = curry(zipWithFn)
19038```
19039
19040</details>
19041
19042<details>
19043
19044<summary><strong>Tests</strong></summary>
19045
19046```javascript
19047import {add} from './add'
19048import {zipWith} from './zipWith'
19049
19050const list1 = [1, 2, 3]
19051const list2 = [10, 20, 30, 40]
19052const list3 = [100, 200]
19053
19054test('when second list is shorter', () => {
19055 const result = zipWith(add, list1, list3)
19056 expect(result).toEqual([101, 202])
19057})
19058
19059test('when second list is longer', () => {
19060 const result = zipWith(add, list1, list2)
19061 expect(result).toEqual([11, 22, 33])
19062})
19063```
19064
19065</details>
19066
19067<details>
19068
19069<summary><strong>Typescript</strong> test</summary>
19070
19071```typescript
19072import {zipWith} from 'rambda'
19073
19074const list1 = [1, 2]
19075const list2 = [10, 20, 30]
19076
19077describe('R.zipWith', () => {
19078 it('happy', () => {
19079 const result = zipWith(
19080 (x, y) => {
19081 x // $ExpectType number
19082 y // $ExpectType number
19083 return `${x}-${y}`
19084 },
19085 list1,
19086 list2
19087 )
19088
19089 result // $ExpectType string[]
19090 })
19091 it('curried', () => {
19092 const result = zipWith((x, y) => {
19093 x // $ExpectType unknown
19094 y // $ExpectType unknown
19095 return `${x}-${y}`
19096 })(list1, list2)
19097
19098 result // $ExpectType string[]
19099 })
19100})
19101```
19102
19103</details>
19104
19105[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#zipWith)
19106
19107## ❯ CHANGELOG
19108
191097.0.0
19110
19111- Braking change - sync `R.compose`/`R.pipe` with `@types/ramda`. That is significant change so as safeguard, it will lead a major bump. Important - this lead to raising required Typescript version to `4.2.2`. In other words, to use `Rambda` you'll need Typescript version `4.2.2` or newer.
19112
19113Related commit in `@types/ramda` - https://github.com/DefinitelyTyped/DefinitelyTyped/commit/286eff4f76d41eb8f091e7437eabd8a60d97fc1f#diff-4f74803fa83a81e47cb17a7d8a4e46a7e451f4d9e5ce2f1bd7a70a72d91f4bc1
19114
19115There are several other changes in `@types/ramda` as stated in [this comment](https://github.com/ramda/ramda/issues/2976#issuecomment-990408945). This leads to change of typings for the following methods in **Rambda**:
19116
19117-- R.unless
19118
19119-- R.toString
19120
19121-- R.ifElse
19122
19123-- R.always
19124
19125-- R.complement
19126
19127-- R.cond
19128
19129-- R.is
19130
19131-- R.sortBy
19132
19133-- R.dissoc
19134
19135-- R.toPairs
19136
19137-- R.assoc
19138
19139-- R.toLower
19140
19141-- R.toUpper
19142
19143- One more reason for the braking change is changing of export declarations in `package.json` based on [this blog post](https://devblogs.microsoft.com/typescript/announcing-typescript-4-5-beta/#packagejson-exports-imports-and-self-referencing) and [this merged Ramda's PR](https://github.com/ramda/ramda/pull/2999). This also led to renaming of `babel.config.js` to `babel.config.cjs`.
19144
19145- Add `R.apply`, `R.bind` and `R.unapply`
19146
19147- `R.startsWith/R.endsWith` now support lists as inputs. This way, it matches current Ramda behavior.
19148
19149- Remove unused typing for `R.chain`.
19150
19151- `R.map`/`R.filter` no longer accept bad inputs as iterable. This way, Rambda behaves more like Ramda, which also throws.
19152
19153- Make `R.lastIndexOf` follow the logic of `R.indexOf`.
19154
19155- Change `R.type` logic to Ramda logic. This way, `R.type` can return `Error` and `Set` as results.
19156
19157- Add missing logic in `R.equals` to compare sets - [Issue #599](https://github.com/selfrefactor/rambda/issues/599)
19158
19159- Improve list cloning - [Issue #595](https://github.com/selfrefactor/rambda/issues/595)
19160
19161- Handle multiple inputs with `R.allPass` and `R.anyPass` - [Issue #604](https://github.com/selfrefactor/rambda/issues/604)
19162
19163- Fix `R.length` wrong logic with inputs as `{length: 123}` - [Issue #606](https://github.com/selfrefactor/rambda/issues/606).
19164
19165- Improve non-curry typings of `R.merge` by using types from [mobily/ts-belt](https://github.com/mobily/ts-belt).
19166
19167- Improve performance of `R.uniqWith`.
19168
19169- Wrong `R.update` if index is `-1` - [PR #593](https://github.com/selfrefactor/rambda/pull/593)
19170
19171- Make `R.eqProps` safe for falsy inputs - based on [this opened Ramda PR](https://github.com/ramda/ramda/pull/2943).
19172
19173- Incorrect benchmarks for `R.pipe/R.compose` - [Issue #608](https://github.com/selfrefactor/rambda/issues/608)
19174
19175- Fix `R.last/R.head` typings - [Issue #609](https://github.com/selfrefactor/rambda/issues/609)
19176
191776.9.0
19178
19179- Fix slow `R.uniq` methods - [Issue #581](https://github.com/selfrefactor/rambda/issues/581)
19180
19181Fixing `R.uniq` was done by improving `R.indexOf` which has performance implication to all methods importing `R.indexOf`:
19182
19183- R.includes
19184- R.intersection
19185- R.difference
19186- R.excludes
19187- R.symmetricDifference
19188- R.union
19189
19190- R.without no longer support the following case - `without('0:1', ['0', '0:1']) // => ['0']`. Now it throws as the first argument should be a list, not a string. Ramda, on the other hand, returns an empty list - https://github.com/ramda/ramda/issues/3086.
19191
191926.8.3
19193
19194- Fix Typescript build process with `rambda/immutable` - [Issue #572](https://github.com/selfrefactor/rambda/issues/572)
19195
19196- Add `R.objOf` method
19197
19198- Add `R.mapObjIndexed` method
19199
19200- Publish shorter README.md version to NPM
19201
192026.8.0
19203
19204- `R.has` use `Object.prototype.hasOwnProperty`- [Issue #572](https://github.com/selfrefactor/rambda/issues/572)
19205
19206- Expose `immutable.ts` typings which are Rambda typings with `readonly` statements - [Issue #565](https://github.com/selfrefactor/rambda/issues/565)
19207
19208- Fix `R.intersection` wrong order compared to Ramda.
19209
19210- `R.path` wrong return of `null` instead of `undefined` when path value is `null` - [PR #577](https://github.com/selfrefactor/rambda/pull/577)
19211
192126.7.0
19213
19214- Remove `ts-toolbelt` types from Typescript definitions. Most affected are the following methods, which lose one of its curried definitions:
19215
192161. R.maxBy
192172. R.minBy
192183. R.pathEq
192194. R.viewOr
192205. R.when
192216. R.merge
192227. R.mergeDeepRight
192238. R.mergeLeft
19224
192256.6.0
19226
19227- Change `R.piped` typings to mimic that of `R.pipe`. Main difference is that `R.pipe` is focused on unary functions.
19228
19229- Fix wrong logic when `R.without` use `R.includes` while it should use array version of `R.includes`.
19230
19231- Use uglify plugin for UMD bundle.
19232
19233- Remove `dist` folder from `.gitignore` in order to fix `Deno` broken package. [Issue #570](https://github.com/selfrefactor/rambda/issues/570)
19234
19235- Improve `R.fromPairs` typings - [Issue #567](https://github.com/selfrefactor/rambda/issues/567)
19236
192376.5.3
19238
19239- Wrong logic where `R.without` use `R.includes` while it should use the array version of `R.includes`
19240
19241This is Ramda bug, that Rambda also has before this release - https://github.com/ramda/ramda/issues/3086
19242
192436.5.2
19244
19245- Wrong `R.defaultTo` typings - changes introduced in v6.5.0 are missing their TS equivalent.
19246
19247- Update dependencies
19248
192496.5.1
19250
19251Fix wrong versions in changelog
19252
192536.5.0
19254
19255- `R.defaultTo` no longer accepts infinite inputs, thus it follows Ramda implementation.
19256
19257- `R.equals` supports equality of functions.
19258
19259- `R.pipe` doesn't use `R.compose`.
19260
19261- Close [Issue #561](https://github.com/selfrefactor/rambda/issues/561) - export several internal TS interfaces and types
19262
19263- Close [Issue #559](https://github.com/selfrefactor/rambda/issues/559) - improve `R.propOr` typings
19264
19265- Add `CHANGELOG.md` file in release files list
19266
192676.4.0
19268
19269- Close [Issue #560](https://github.com/selfrefactor/rambda/issues/560) - apply immutable lint to Typescript definitions
19270
19271- Close [Issue #553](https://github.com/selfrefactor/rambda/issues/553) - fix problem with curried typings of `R.prop`
19272
19273- Fix wrong `R.last` typing
19274
19275- Upgrade all `rollup` related dependencies
19276
19277- `R.type` supports `Symbol` just like *Ramda*.
19278
19279- Remove file extension in `main` property in `package.json` in order to allow `experimental-modules`. See also this Ramda's PR - https://github.com/ramda/ramda/pull/2678/files
19280
19281- Import `R.indexBy`/`R.when`/`R.zipObj`/`R.propEq`/`R.complement` changes from recent `@types/ramda` release.
19282
19283- `R.tryCatch` stop supporting asynchronous functions; the previous behaviour is exported to *Rambdax* as `R.tryCatchAsync`
19284
192856.3.1
19286
19287- Fix missing `Evolved` declaration in Typescript definition
19288
192896.3.0
19290
19291- Add `R.takeLastWhile`
19292
19293- Add `R.dropWhile`
19294
19295- Add `R.eqProps`
19296
19297- Add `R.dropLastWhile`
19298
19299- Add `R.dropRepeats`
19300
19301- Add `R.dropRepeatsWith`
19302
19303- Add `R.evolve`
19304
19305- Add typings for `R.takeWhile` when iterable is a string
19306
193076.2.0
19308
19309- Add `R.props`
19310
19311- Add `R.zipWith`
19312
19313- Add `R.splitAt`
19314
19315- Add `R.splitWhen`
19316
19317- Close [Issue #547](https://github.com/selfrefactor/rambda/issues/547) - restore `readonly` declaration in Typescript definitions.
19318
19319- `R.append`/`R.prepend` now work only with arrays just like Ramda. Previous behaviour was for them to work with both arrays and strings.
19320
19321- Sync `R.pluck` typings with `@types/ramda` as there was a tiny difference.
19322
193236.1.0
19324
19325- Fix `R.and` wrong definition, because the function doesn't convert the result to boolean. This introduce another difference with `@types/ramda`.
19326
19327- Add `R.once`
19328
19329- Add `R.or`
19330
193316.0.1
19332
19333- Fix typing of `R.reject` as it wrongly declares that with object, it pass property to predicate.
19334
193356.0.0
19336
19337- Breaking change - `R.map`/`R.filter`/`R.reject`/`R.forEach`/`R.partition` doesn't pass index as second argument to the predicate, when looping over arrays. The old behaviour of *map*, *filter* and *forEach* can be found in Rambdax methods *R.mapIndexed*, *R.filterIndexed* and *R.forEachIndexed*.
19338
19339- Breaking change - `R.all`/`R.none`/`R.any`/`R.find`/`R.findLast`/`R.findIndex`/`R.findLastIndex` doesn't pass index as second argument to the predicate.
19340
19341- Change `R.assocPath` typings so the user can explicitly sets type of the new object
19342
19343- Typings of `R.assoc` match its `@types/ramda` counterpart.
19344
19345- Simplify `R.forEach` typings
19346
19347- Remove `ReadonlyArray<T>` pattern from Typescript definitions - not enough value for the noise it adds.
19348
193495.13.1
19350
19351- Fix wrong `R.takeWhile`
19352
193535.13.0
19354
19355- Add `R.takeWhile` method
19356
19357- Fix `R.lensPath` issue when using string as path input. The issue was introduced when fixing [Issue #524](https://github.com/selfrefactor/rambda/issues/524) in the previous release.
19358
193595.12.1
19360
19361- Close [Issue #524](https://github.com/selfrefactor/rambda/issues/524) -
19362 wrong `R.assocPath` when path includes numbers
19363
19364- `R.includes` throws on wrong input, i.e. `R.includes(1, null)`
19365
193665.12.0
19367
19368- Add `R.move` method
19369
19370- Add `R.union` method
19371
19372- Close [Issue #519](https://github.com/selfrefactor/rambda/issues/519) -
19373`ts-toolbelt` needs other type of export with `--isolatedModules` flag
19374
19375- Change `R.when` implementation and typings to match those of `Ramda`
19376
19377- `R.over` and `R.set` use `R.curry` instead of manual currying
19378
19379- `R.lensPath` typings support string as path, i.e. `'a.b'` instead of `['a', 'b']`
19380
19381- `R.equals` now supports negative zero just like `Ramda.equals`
19382
19383- `R.replace` uses `R.curry`
19384
193855.11.0
19386
19387Forgot to export `R.of` because of wrong marker in `files/index.d.ts`
19388
193895.10.0
19390
19391Close [Issue #514](https://github.com/selfrefactor/rambda/issues/514) -
19392wrong `R.length` with empty string
19393
19394Close [Issue #511](https://github.com/selfrefactor/rambda/issues/511) - error in `ts-toolbelt` library
19395
19396Close [Issue #510](https://github.com/selfrefactor/rambda/issues/510) - `R.clamp` should throw if min argument is greater than max argument
19397
19398- [PR #508](https://github.com/selfrefactor/rambda/pull/508) - add `R.of`
19399
19400- Definition of `R.curry` are not same as those of `@types/ramda`
19401
19402- Definitions of `R.either` is same as that of `R.both`
19403
19404- Definitions of `R.ifElse` no longer use `any` type
19405
19406- Definition of `R.flatten` requires passing type for the output
19407
19408- Fix definition of `R.propOr`, `R.dissoc`
19409
19410- Fix curried definitions of `R.take`, `R.takeLast`, `R.drop` and `R.dropLast`
19411
19412- 5.9.0
19413
19414- `R.pickAll` definition allows passing string as path to search.
19415
19416- `R.propEq` definition is now similar to that in `@types/ramda`.
19417
19418- `R.none` matches `R.all` implementation and pass index as second argument to predicate input.
19419
19420- `R.reduce` - drop support for object as iterable. Now it throws the same error as Ramda. Also instead of returning the initial value when iterable is `undefined`, now it throws.
19421
19422Add index as additional argument to the Typescript definitions of the following methods:
19423
19424- R.all
19425- R.find
19426- R.findLast
19427- R.findIndex
19428- R.findLastIndex
19429
19430- 5.8.0
19431
19432Add `R.mergeAll`
19433Add `R.mergeDeepRight`
19434Add `R.mergeLeft`
19435Add `R.partition`
19436Add `R.pathEq`
19437Add `R.tryCatch`
19438Add `R.unless`
19439Add `R.whereEq`
19440Add `R.where`
19441
19442- Add `R.last` typing for empty array
19443
19444- 5.7.0 Revert [PR #469](https://github.com/selfrefactor/rambda/pull/469) as `R.curry` was slow | Also now `R.flip` throws if arity is greater than or equal to 5
19445
19446- 5.6.3 Merge several PRs of [@farwayer](https://github.com/farwayer)
19447
19448- [PR #482](https://github.com/selfrefactor/rambda/pull/482) - improve `R.forEach` performance by not using `R.map`
19449
19450- [PR #485](https://github.com/selfrefactor/rambda/pull/485) - improve `R.map` performance
19451
19452- [PR #482](https://github.com/selfrefactor/rambda/pull/486) - improve `R.reduce` performance
19453
19454- Fix missing high arity typings for `R.compose/pipe`
19455
19456- `R.merge` definitions match those of `@types/ramda`
19457
19458- Remove `dist` folder from Rambda repo
19459
19460- 5.6.2
19461
19462Close [Issue #476](https://github.com/selfrefactor/rambda/issues/476) - typesafe `R.propEq` definitions
19463
19464Approve [PR #477](https://github.com/selfrefactor/rambda/pull/477) - fix `R.groupWith` when list length is 1
19465
19466- 5.6.1
19467
19468Update `ts-toolbelt` files as now there is update pipeline for it.
19469
19470Approve [PR #474](https://github.com/selfrefactor/rambda/pull/474) - intruduce internal `isArray` helper
19471
19472- 5.6.0
19473
19474Approve [PR #469](https://github.com/selfrefactor/rambda/pull/469) - R.flip supports any arity | implement `R.curry` with `R.curryN` add `R.applySpec`
19475
19476- 5.5.0
19477
19478Close [Issue #464](https://github.com/selfrefactor/rambda/issues/464) - `R.flip` should handle functions with arity above 2
19479
19480Close [Issue #468](https://github.com/selfrefactor/rambda/issues/468) - `fs-extra` should be dev dependency as it was wrongly added as production dependency in `5.2.0`
19481
19482`R.flip` typings now match `@types/ramda` typings
19483
19484Add `R.hasPath` method
19485
19486Add `R.mathMod` typings
19487
19488- 5.4.3
19489
19490Fix `R.omit` typings
19491
19492- 5.4.2
19493
19494Fix `R.pick` typings
19495
19496> Close [Issue #460](https://github.com/selfrefactor/rambda/issues/460) - `R.paths` should be curried
19497
19498- 5.4.1
19499
19500> Close [Issue #458](https://github.com/selfrefactor/rambda/issues/458) - wrong `R.propIs` typing
19501
19502- 5.4.0
19503
19504> Close [Issue #408](https://github.com/selfrefactor/rambda/issues/408) - add `R.chain`
19505
19506- 5.3.0
19507
19508> Close [Issue #430](https://github.com/selfrefactor/rambda/issues/430) - add `R.when`
19509
19510Also restore `R.converge`, `R.findLast`, `R.findLastIndex` and `R.curryN` as I have forgotten to export them when releasing `5.2.0`.
19511
19512- 5.2.1
19513
19514Fix Typescript comment for every method
19515
19516- 5.2.0
19517
19518Release new documentation site
19519
19520`Ramda` repo now holds all `Rambdax` methods and tests
19521
19522- 5.1.1
19523
19524Add `R.converge` and `R.curryN` from [PR #412](https://github.com/selfrefactor/rambda/pull/412)
19525
19526Close [Issue #410](https://github.com/selfrefactor/rambda/issues/410) - wrong implementation of `R.groupWith`
19527
19528Close [Issue #411](https://github.com/selfrefactor/rambda/issues/411) - change the order of declared `R.map` typings rules
19529
19530- 5.0.0
19531
19532Move `R.partialCurry` to Rambdax(reason for major bump).
19533
19534Use new type of export in Typescript definitions.
19535
19536Approve [PR #381](https://github.com/selfrefactor/rambda/pull/381) - add `R.applySpec`
19537
19538- 4.6.0
19539
19540Approve [PR #375](https://github.com/selfrefactor/rambda/pull/375) - add lenses(Thank you [@synthet1c](https://github.com/synthet1c))
19541
19542Add `R.lens`
19543
19544Add `R.lensIndex`
19545
19546Add `R.lensPath`
19547
19548Add `R.lensProp`
19549
19550Add `R.over`
19551
19552Add `R.set`
19553
19554Add `R.view`
19555
19556> Sync with Ramda 0.27
19557
19558Add `R.paths`
19559
19560Add `R.xor`
19561
19562> Close [Issue #373](https://github.com/selfrefactor/rambda/issues/373)
19563
19564Add `R.cond`
19565
19566- 4.5.0 Add `R.clamp`
19567
19568- 4.4.2 Improve `R.propOr` typings
19569
19570- 4.4.1 Make `R.reject` has the same typing as `R.filter`
19571
19572- 4.4.0 Several changes:
19573
19574Close [Issue #317](https://github.com/selfrefactor/rambda/issues/317) - add `R.transpose`
19575
19576Close [Issue #325](https://github.com/selfrefactor/rambda/issues/325) - `R.filter` should return equal values for bad inputs `null` and `undefined`
19577
19578Approve suggestion for `R.indexBy` to accept string not only function as first argument.
19579
19580Edit of `R.path` typings
19581
19582- 4.2.0 Approve [PR #314](https://github.com/selfrefactor/rambda/pull/314) - add `R.and`
19583
19584- 4.1.1 Add missing typings for `R.slice`
19585
19586- 4.1.0 Add `R.findLast` and `R.findLastIndex`
19587
19588- 4.0.2 Fix `R.isEmpty` wrong behaviour compared to the Ramda method
19589
19590- 4.0.1 Approve [PR #289](https://github.com/selfrefactor/rambda/pull/289) - remove console.log in `R.values` method
19591
19592- 4.0.0 Multiple breaking changes as Rambda methods are changed in order to increase the similarity between with Ramda
19593
19594Add to `Differences`:
19595
19596```text
19597R.type can return 'NaN'
19598
19599R.compose doesn't pass `this` context
19600
19601R.clone doesn't work with number, booleans and strings as input
19602```
19603
19604All breaking changes:
19605
19606-- R.add works only with numbers
19607
19608-- Fix R.adjust which had wrong order of arguments
19609
19610-- R.adjust works when index is out of bounds
19611
19612-- R.complement support function with multiple arguments
19613
19614-- R.compose/pipe throws when called with no argument
19615
19616-- R.clone works with `Date` value as input
19617
19618-- R.drop/dropLast/take/takeLast always return new copy of the list/string
19619
19620-- R.take/takeLast return original list/string with negative index
19621
19622-- R.equals handles `NaN` and `RegExp` types
19623
19624-- R.type/R.equals supports `new Boolean/new Number/new Date/new String` expressions
19625
19626-- R.has works with non-object
19627
19628-- R.ifElse pass all arguments
19629
19630-- R.length works with bad input
19631
19632-- R.propEq work with bad input for object argument
19633
19634-- R.range work with bad inputs
19635
19636-- R.times work with bad inputs
19637
19638-- R.reverse works with strings
19639
19640-- R.splitEvery throws on non-positive integer index
19641
19642-- R.test throws just like Ramda when first argument is not regex
19643
19644-- R.values works with bad inputs
19645
19646-- R.zipObj ignores extra keys
19647
19648- 3.3.0
19649
19650This is pre `4.0.0` release and it contains all of the above changes
19651
19652Close [issue #287](https://github.com/selfrefactor/rambda/issues/287) - `ts-toolbelt` directory was changed but not reflected in `files` property in `package.json`
19653
19654- 3.2.5
19655
19656Close [issue #273](https://github.com/selfrefactor/rambda/issues/273) - ts-toolbelt needs other type of export when `isolatedModules` TypeScript property
19657
19658Close [issue #245](https://github.com/selfrefactor/rambda/issues/245) - complete typings tests for methods that have more specific Typescript definitions
19659
19660- 3.2.1 Fast fix for [issue #273](https://github.com/selfrefactor/rambda/issues/273) - messed up typings
19661
19662- 3.2.0 There are several changes:
19663
19664Close [issue #263](https://github.com/selfrefactor/rambda/issues/263) - broken curry typing solved by `ts-toolbelt` local dependency.
19665
19666Add `R.partialCurry` typings.
19667
19668Approve [PR #266](https://github.com/selfrefactor/rambda/pull/266) that adds `R.slice` method.
19669
19670- 3.1.0 This might be breaking change for Typescript users, as very different definitions are introduced. With the previous state of the definitions, it was not possible to pass `dtslint` typings tests.
19671
19672- `R.either` and `R.both` supports multiple arguments as they should.
19673
19674- Several methods added by [@squidfunk](https://github.com/squidfunk) - `R.assocPath`, `R.symmetricDifference`, `R.intersperse`, `R.intersection` and `R.difference`
19675
19676- 3.0.1 Close [issue #234](https://github.com/selfrefactor/rambda/issues/234) - wrong curry typing
19677
19678- 3.0.0 Deprecate `R.contains`, while `R.includes` is now following Ramda API(it uses `R.equals` for comparision)
19679
19680- 2.14.5 `R.without` needs currying
19681
19682- 2.14.4 Close [issue #227](https://github.com/selfrefactor/rambda/issues/227) - add index as third argument of `R.reduce` typings
19683
19684- 2.14.2 Use `R.curry` with `R.reduce` as manual curry there didn't work as expected.
19685
19686- 2.14.1 Fix wrong typescript with `R.head` - [PR #228](https://github.com/selfrefactor/rambda/pull/228) pushed by [@tonivj5](https://github.com/tonivj5)
19687
19688- 2.14.0 Add `R.groupWith` by @selfrefactor | Add `R.propOr`, `R.mathMod`, `R.mean`, `R.median`, `R.negate`, `R.product` by [@ku8ar](https://github.com/ku8ar)
19689
19690- 2.13.0 Add `R.identical` - [PR #217](https://github.com/selfrefactor/rambda/pull/217) pushed by [@ku8ar](https://github.com/ku8ar)
19691
19692- 2.12.0 Add `R.propIs` - [PR #213](https://github.com/selfrefactor/rambda/pull/213) and add `R.sum` - [issue #207](https://github.com/selfrefactor/rambda/issues/207)
19693
19694- 2.11.2 Close Rambdax [issue #32](https://github.com/selfrefactor/rambdax/issues/32) - wrong `R.type` when function is input
19695
19696- 2.11.1 Approve [PR #182](https://github.com/selfrefactor/rambda/pull/182) - Changed typings to allow object as input to `R.forEach` and `R.map`
19697
19698- 2.11.0 Approve [PR #179](https://github.com/selfrefactor/rambda/pull/179) - `R.adjust` handles negative index; `R.all` doesn't need `R.filter`
19699
19700- 2.10.2 Close [issue #175](https://github.com/selfrefactor/rambda/issues/175) - missing typescript file
19701
19702- 2.10.0 Approve huge and important [PR #171](https://github.com/selfrefactor/rambda/pull/171) submitted by [@helmuthdu](https://github.com/helmuthdu) - Add comments to each method, improve Typescript support
19703
19704- 2.9.0 `R.toPairs` and `R.fromPairs`
19705
19706- 2.8.0 Approve [PR #165](https://github.com/selfrefactor/rambda/pull/165) `R.clone`
19707
19708- 2.7.1 expose `src` | Discussed at [issue #147](https://github.com/selfrefactor/rambda/issues/147)
19709
19710- 2.7.0 Approve [PR #161](https://github.com/selfrefactor/rambda/pull/161) `R.isEmpty`
19711
19712- 2.6.0 `R.map`, `R.filter` and `R.forEach` pass original object to iterator as third argument | Discussed at [issue #147](https://github.com/selfrefactor/rambda/issues/147)
19713
19714- 2.5.0 Close [issue #149](https://github.com/selfrefactor/rambda/issues/149) Add `R.partial` | `R.type` handles `NaN`
19715
19716- 2.4.0 Major bump of `Rollup`; Stop building for ES5
19717
19718- 2.3.1 Close [issue #90](https://github.com/selfrefactor/rambda/issues/90) | Add string type of path in `R.pathOr`
19719
19720- 2.3.0 Close [issue #89](https://github.com/selfrefactor/rambda/issues/89) | Fix missing `Number` TS definition in `R.type`
19721
19722- 2.2.0 `R.defaultTo` accepts indefinite number of input arguments. So the following is valid expression: `const x = defaultTo('foo',null, null, 'bar')`
19723
19724- 2.1.0 Restore `R.zip` using [WatermelonDB](https://github.com/Nozbe/WatermelonDB/) implementation.
19725
19726- 2.0.0 Major version caused by removing of `R.zip` and `R.addIndex`. [Issue #85](https://github.com/selfrefactor/rambda/issues/85) rightfully finds that the implementation of `R.addIndex` is not correct. This led to removing this method and also of `R.zip` as it had depended on it. The second change is that `R.map`, `R.filter` are passing array index as second argument when looping over arrays. The third change is that `R.includes` will return `false` if input is neigher `string` nor `array`. The previous behaviour was to throw an error. The last change is to increase the number of methods that are passing index as second argument to the predicate function.
19727
19728- 1.2.6 Use `src` folder instead of `modules`
19729- 1.2.5 Fix `omit` typing
19730- 1.2.4 Add missing Typescript definitions - [PR#82](https://github.com/selfrefactor/rambda/pull/82)
19731- 1.2.2 Change curry method used across most of library methods
19732- 1.2.1 Add `R.assoc` | fix passing `undefined` to `R.map` and `R.merge` [issue #77](https://github.com/selfrefactor/rambda/issues/77)
19733- 1.2.0 Add `R.min`, `R.minBy`, `R.max`, `R.maxBy`, `R.nth` and `R.keys`
19734- 1.1.5 Close [issue #74](https://github.com/selfrefactor/rambda/issues/74) `R.zipObj`
19735- 1.1.4 Close [issue #71](https://github.com/selfrefactor/rambda/issues/71) CRA fail to build `rambda`
19736- 1.1.3 Approve [PR #70](https://github.com/selfrefactor/rambda/pull/67) implement `R.groupBy` | Close [issue #69](https://github.com/selfrefactor/rambda/issues/69)
19737- 1.1.2 Approve [PR #67](https://github.com/selfrefactor/rambda/pull/67) use `babel-plugin-annotate-pure-calls`
19738- 1.1.1 Approve [PR #66](https://github.com/selfrefactor/rambda/pull/66) `R.zip`
19739- 1.1.0 `R.compose` accepts more than one input argument [issue #65](https://github.com/selfrefactor/rambda/issues/65)
19740- 1.0.13 Approve [PR #64](https://github.com/selfrefactor/rambda/pull/64) `R.indexOf`
19741- 1.0.12 Close [issue #61](https://github.com/selfrefactor/rambda/issues/61) make all functions modules
19742- 1.0.11 Close [issue #60](https://github.com/selfrefactor/rambda/issues/60) problem with babelrc
19743- 1.0.10 Close [issue #59](https://github.com/selfrefactor/rambda/issues/59) add R.dissoc
19744- 1.0.9 Close [issue #58](https://github.com/selfrefactor/rambda/issues/58) - Incorrect `R.equals`
19745- 1.0.8 `R.map` and `R.filter` pass object properties when mapping over objects
19746- 1.0.7 Add `R.uniqWith`
19747- 1.0.6 Close [issue #52](https://github.com/selfrefactor/rambda/issues/52) - ES5 compatible code
19748- 1.0.5 Close [issue #51](https://github.com/selfrefactor/rambda/issues/51)
19749- 1.0.4 Close [issue #50](https://github.com/selfrefactor/rambda/issues/50) - add `R.pipe` typings
19750- 1.0.3 `R.ifElse` accept also boolean as condition argument
19751- 1.0.2 Remove `typedDefaultTo` and `typedPathOr` | Add `R.pickAll` and `R.none`
19752- 1.0.0 Major change as build is now ES6 not ES5 compatible (Related to [issue #46](https://github.com/selfrefactor/rambda/issues/46))| Making `Rambda` fully tree-shakeable| Edit Typescript definition
19753- 0.9.8 Revert to ES5 compatible build - [issue #46](https://github.com/selfrefactor/rambda/issues/46)
19754- 0.9.7 Refactor for `Rollup` tree-shake | Remove `R.padEnd` and `R.padStart`
19755- 0.9.6 Close [issue #44](https://github.com/selfrefactor/rambda/issues/44) - `R.reverse` mutates the array
19756- 0.9.5 Close [issue #45](https://github.com/selfrefactor/rambda/issues/45) - invalid Typescript typings
19757- 0.9.4 Add `R.reject` and `R.without` ([PR#41](https://github.com/selfrefactor/rambda/pull/41) [PR#42](https://github.com/selfrefactor/rambda/pull/42)) | Remove 'browser' field in `package.json` due to Webpack bug [4674](https://github.com/webpack/webpack/issues/4674)
19758- 0.9.3 Add `R.forEach` and `R.times`
19759- 0.9.2 Add `Typescript` definitions
19760- 0.9.1 Close [issue #36](https://github.com/selfrefactor/rambda/issues/36) - move current behaviour of `defaultTo` to a new method `typedDefaultTo`; make `defaultTo` follow Ramda spec; add `pathOr`; add `typedPathOr`.
19761- 0.9.0 Add `R.pipe` [PR#35](https://github.com/selfrefactor/rambda/pull/35)
19762- 0.8.9 Add `R.isNil`
19763- 0.8.8 Migrate to ES modules [PR33](https://github.com/selfrefactor/rambda/pull/33) | Add R.flip to the API | R.map/filter works with objects
19764- 0.8.7 Change `Webpack` with `Rollup` - [PR29](https://github.com/selfrefactor/rambda/pull/29)
19765- 0.8.6 Add `R.tap` and `R.identity`
19766- 0.8.5 Add `R.all`, `R.allPass`, `R.both`, `R.either` and `R.complement`
19767- 0.8.4 Learning to run `yarn test` before `yarn publish` the hard way
19768- 0.8.3 Add `R.always`, `R.T` and `R.F`
19769- 0.8.2 Add `concat`, `padStart`, `padEnd`, `lastIndexOf`, `toString`, `reverse`, `endsWith` and `startsWith` methods
19770- 0.8.1 Add `R.ifElse`
19771- 0.8.0 Add `R.not`, `R.includes` | Take string as condition for `R.pick` and `R.omit`
19772- 0.7.6 Fix incorrect implementation of `R.values`
19773- 0.7.5 Fix incorrect implementation of `R.omit`
19774- 0.7.4 [issue #13](https://github.com/selfrefactor/rambda/issues/13) - Fix `R.curry`, which used to return incorrectly `function` when called with more arguments
19775- 0.7.3 Close [issue #9](https://github.com/selfrefactor/rambda/issues/9) - Compile to `es2015`; Approve [PR #10](https://github.com/selfrefactor/rambda/pull/10) - add `R.addIndex` to the API
19776- 0.7.2 Add `Promise` support for `R.type`
19777- 0.7.1 Close [issue #7](https://github.com/selfrefactor/rambda/issues/7) - add `R.reduce` to the API
19778- 0.7.0 Close [issue #5](https://github.com/selfrefactor/rambda/issues/5) - change name of `curry` to `partialCurry`; add new method `curry`, which works just like Ramda's `curry`
19779- 0.6.2 Add separate documentation site via `docsify`
19780
19781[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#-changelog)
19782
19783## ❯ Additional info
19784
19785> Most influential contributors
19786
19787- [@farwayer](https://github.com/farwayer) - improving performance in R.find, R.filter; give the idea how to make benchmarks more reliable;
19788
19789- [@thejohnfreeman](https://github.com/thejohnfreeman) - add R.assoc, R.chain;
19790
19791- [@helmuthdu](https://github.com/helmuthdu) - add R.clone; help improve code style;
19792
19793- [@jpgorman](https://github.com/jpgorman) - add R.zip, R.reject, R.without, R.addIndex;
19794
19795- [@ku8ar](https://github.com/ku8ar) - add R.slice, R.propOr, R.identical, R.propIs and several math related methods; introduce the idea to display missing Ramda methods;
19796
19797- [@romgrk](https://github.com/romgrk) - add R.groupBy, R.indexBy, R.findLast, R.findLastIndex;
19798
19799- [@squidfunk](https://github.com/squidfunk) - add R.assocPath, R.symmetricDifference, R.difference, R.intersperse;
19800
19801- [@synthet1c](https://github.com/synthet1c) - add all lenses methods; add R.applySpec, R.converge;
19802
19803- [@vlad-zhukov](https://github.com/vlad-zhukov) - help with configuring Rollup, Babel; change export file to use ES module exports;
19804
19805> Rambda references
19806
19807- [Interview with Dejan Totef at SurviveJS blog](https://survivejs.com/blog/rambda-interview/)
19808
19809- [Awesome functional Javascript programming libraries](https://github.com/stoeffel/awesome-fp-js#libraries)
19810
19811> Links to Rambda
19812
19813- [https://mailchi.mp/webtoolsweekly/web-tools-280](Web Tools Weekly)
19814
19815- [https://github.com/stoeffel/awesome-fp-js](awesome-fp-js)
19816
19817- [https://github.com/docsifyjs/awesome-docsify](awesome-docsify)
19818
19819> Deprecated from `Used by` section
19820
19821- [SAP's Cloud SDK](https://github.com/SAP/cloud-sdk) - This repo doesn't uses `Rambda` since *October/2020* [commit that removes Rambda](https://github.com/SAP/cloud-sdk/commit/b29b4f915c4e4e9c2441e7b6b67cf83dac1fdac3)
19822
19823> Releases
19824
19825[Rambda's releases](https://github.com/selfrefactor/rambda/releases) before **6.4.0** were used mostly for testing purposes.
19826
19827[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#-additional-info)
19828
19829## My other libraries
19830
19831<table>
19832 <tbody>
19833 <tr valign="top">
19834 <td width="20%" align="center">
19835 <h4>Niketa theme</h4>
19836 <a href="https://marketplace.visualstudio.com/items?itemName=selfrefactor.Niketa-theme">Collection of 9 light VSCode themes</a>
19837 </td>
19838 <td width="20%" align="center">
19839 <h4>Niketa dark theme</h4>
19840 <a href="https://marketplace.visualstudio.com/items?itemName=selfrefactor.niketa-dark-theme">Collection of 9 dark VSCode themes</a>
19841 </td>
19842 <td width="20%" align="center">
19843 <h4>String-fn</h4>
19844 <a href="https://github.com/selfrefactor/services/tree/master/packages/string-fn">String utility library</a>
19845 </td>
19846 <td width="20%" align="center">
19847 <h4>Useful Javascript libraries</h4>
19848 <a href="https://github.com/selfrefactor/useful-javascript-libraries">Large collection of JavaScript,Typescript and Angular related repos links</a>
19849 </td>
19850 <td width="20%" align="center">
19851 <h4>Run-fn</h4>
19852 <a href="https://github.com/selfrefactor/services/tree/master/packages/run-fn">CLI commands for lint JS/TS files, commit git changes and upgrade of dependencies</a>
19853 </td>
19854 </tr>
19855 </tbody>
19856</table>
\No newline at end of file