Skip to content

Commit 1f6f28c

Browse files
selfrefactorDeyan Totev
andauthored
11.1.0 (#98)
* release * chore@small --------- Co-authored-by: Deyan Totev <[email protected]>
1 parent 2fe94a5 commit 1f6f28c

File tree

13 files changed

+826
-1014
lines changed

13 files changed

+826
-1014
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
11.1.0
2+
3+
- Improve `R.mapToObject` types - [Issue #96](https://github.com/selfrefactor/rambdax/issues/96)
4+
5+
- Sync with `Rambda` version `9.2.0`
6+
17
11.0.0
28

39
- Sync with `Rambda` version `9.1.0`

README.md

Lines changed: 47 additions & 221 deletions
Original file line numberDiff line numberDiff line change
@@ -4103,6 +4103,8 @@ function parseRegex(maybeRegex){
41034103
export function equals(a, b){
41044104
if (arguments.length === 1) return _b => equals(a, _b)
41054105

4106+
if (Object.is(a, b)) return true
4107+
41064108
const aType = type(a)
41074109

41084110
if (aType !== type(b)) return false
@@ -4507,7 +4509,7 @@ describe('brute force', () => {
45074509
{
45084510
"ERRORS_MESSAGE_MISMATCH": 0,
45094511
"ERRORS_TYPE_MISMATCH": 0,
4510-
"RESULTS_MISMATCH": 8,
4512+
"RESULTS_MISMATCH": 0,
45114513
"SHOULD_NOT_THROW": 0,
45124514
"SHOULD_THROW": 0,
45134515
"TOTAL_TESTS": 289,
@@ -7025,6 +7027,12 @@ export function isEmpty(input){
70257027
return false
70267028
if (!input) return true
70277029

7030+
if (type(input.isEmpty) === 'Function') {
7031+
return input.isEmpty();
7032+
} else if (input.isEmpty) {
7033+
return !!input.isEmpty;
7034+
}
7035+
70287036
if (inputType === 'Object'){
70297037
return Object.keys(input).length === 0
70307038
}
@@ -7059,6 +7067,10 @@ test('happy', () => {
70597067
expect(isEmpty(0)).toBeFalse()
70607068
expect(isEmpty(NaN)).toBeFalse()
70617069
expect(isEmpty([ '' ])).toBeFalse()
7070+
expect(isEmpty({ isEmpty: false})).toBeFalse()
7071+
expect(isEmpty({ isEmpty: () => false})).toBeFalse()
7072+
expect(isEmpty({ isEmpty: true})).toBeTrue()
7073+
expect(isEmpty({ isEmpty: () => true})).toBeTrue()
70627074
})
70637075
```
70647076

@@ -9831,7 +9843,7 @@ test('fallback to R.mapFastAsync', async () => {
98319843

98329844
```typescript
98339845

9834-
mapToObject<T, U>(fn: (input: T) => object|false, list: T[]): U
9846+
mapToObject<T, U extends object>(fn: (input: T) => U|false, list: readonly T[]): U
98359847
```
98369848

98379849
This method allows to generate an object from a list using input function `fn`.
@@ -9952,7 +9964,7 @@ test('bad path', () => {
99529964

99539965
```typescript
99549966

9955-
mapToObjectAsync<T, U>(fn: (input: T) => Promise<object|false>, list: T[]): Promise<U>
9967+
mapToObjectAsync<T, U extends object>(fn: (input: T) => Promise<U|false>, list: readonly T[]): Promise<U>
99569968
```
99579969

99589970
Asynchronous version of `R.mapToObject`
@@ -10371,222 +10383,10 @@ test('with empty array', () => {
1037110383

1037210384
### memoize
1037310385

10374-
```typescript
10375-
10376-
memoize<T, K extends any[]>(fn: (...inputs: K) => T): (...inputs: K) => T
10377-
```
10378-
1037910386
When `fn` is called for a second time with the same input, then the cache result is returned instead of calling again `fn`.
1038010387

10381-
```javascript
10382-
let result = 0
10383-
const fn = (a,b) =>{
10384-
result++
10385-
10386-
return a + b
10387-
}
10388-
const memoized = R.memoize(fn)
10389-
memoized(1, 2)
10390-
memoized(1, 2)
10391-
10392-
// => `result` is equal to `1`
10393-
```
10394-
1039510388
<a title="redirect to Rambda Repl site" href="https://rambda.now.sh?let%20result%20%3D%200%0Aconst%20fn%20%3D%20(a%2Cb)%20%3D%3E%7B%0A%20%20result%2B%2B%0A%0A%20%20return%20a%20%2B%20b%0A%7D%0Aconst%20memoized%20%3D%20R.memoize(fn)%0Amemoized(1%2C%202)%0Amemoized(1%2C%202)%0Aconst%20result%20%3D%20%0A%2F%2F%20%3D%3E%20%60result%60%20is%20equal%20to%20%601%60">Try this <strong>R.memoize</strong> example in Rambda REPL</a>
1039610389

10397-
<details>
10398-
10399-
<summary><strong>R.memoize</strong> source</summary>
10400-
10401-
```javascript
10402-
import { compose } from './compose.js'
10403-
import { map } from './map.js'
10404-
import { replace } from './replace.js'
10405-
import { sort } from './sort.js'
10406-
import { take } from './take.js'
10407-
import { type } from './type.js'
10408-
10409-
const cache = {}
10410-
10411-
const normalizeObject = obj => {
10412-
const sortFn = (a, b) => a > b ? 1 : -1
10413-
const willReturn = {}
10414-
compose(map(prop => willReturn[ prop ] = obj[ prop ]),
10415-
sort(sortFn))(Object.keys(obj))
10416-
10417-
return willReturn
10418-
}
10419-
10420-
const stringify = a => {
10421-
const aType = type(a)
10422-
if (aType === 'String'){
10423-
return a
10424-
} else if ([ 'Function', 'Promise' ].includes(aType)){
10425-
const compacted = replace(
10426-
/\s{1,}/g, ' ', a.toString()
10427-
)
10428-
10429-
return replace(
10430-
/\s/g, '_', take(15, compacted)
10431-
)
10432-
} else if (aType === 'Object'){
10433-
return JSON.stringify(normalizeObject(a))
10434-
}
10435-
10436-
return JSON.stringify(a)
10437-
}
10438-
10439-
const generateProp = (fn, ...inputArguments) => {
10440-
let propString = ''
10441-
inputArguments.forEach(inputArgument => {
10442-
propString += `${ stringify(inputArgument) }_`
10443-
})
10444-
10445-
return `${ propString }${ stringify(fn) }`
10446-
}
10447-
// with weakmaps
10448-
export function memoize(fn, ...inputArguments){
10449-
if (arguments.length === 1){
10450-
return (...inputArgumentsHolder) => memoize(fn, ...inputArgumentsHolder)
10451-
}
10452-
10453-
const prop = generateProp(fn, ...inputArguments)
10454-
if (prop in cache) return cache[ prop ]
10455-
10456-
if (type(fn) === 'Async'){
10457-
return new Promise(resolve => {
10458-
fn(...inputArguments).then(result => {
10459-
cache[ prop ] = result
10460-
resolve(result)
10461-
})
10462-
})
10463-
}
10464-
10465-
const result = fn(...inputArguments)
10466-
cache[ prop ] = result
10467-
10468-
return result
10469-
}
10470-
```
10471-
10472-
</details>
10473-
10474-
<details>
10475-
10476-
<summary><strong>Tests</strong></summary>
10477-
10478-
```javascript
10479-
import { memoize } from './memoize.js'
10480-
10481-
test('memoize function without input arguments', () => {
10482-
const fn = () => 4
10483-
const memoized = memoize(fn)
10484-
expect(typeof memoized()).toBe('function')
10485-
})
10486-
10487-
test('happy', () => {
10488-
let counter = 0
10489-
10490-
const fn = ({ a, b, c }) => {
10491-
counter++
10492-
10493-
return a + b - c
10494-
}
10495-
const memoized = memoize(fn)
10496-
expect(memoized({
10497-
a : 1,
10498-
c : 3,
10499-
b : 2,
10500-
})).toBe(0)
10501-
expect(counter).toBe(1)
10502-
expect(memoized({
10503-
c : 3,
10504-
a : 1,
10505-
b : 2,
10506-
})).toBe(0)
10507-
expect(counter).toBe(1)
10508-
})
10509-
10510-
test('normal function', () => {
10511-
let counter = 0
10512-
const fn = (a, b) => {
10513-
counter++
10514-
10515-
return a + b
10516-
}
10517-
const memoized = memoize(fn)
10518-
expect(memoized(1, 2)).toBe(3)
10519-
expect(memoized(1, 2)).toBe(3)
10520-
expect(memoized(1, 2)).toBe(3)
10521-
expect(counter).toBe(1)
10522-
expect(memoized(2, 2)).toBe(4)
10523-
expect(counter).toBe(2)
10524-
expect(memoized(1, 2)).toBe(3)
10525-
expect(counter).toBe(2)
10526-
})
10527-
10528-
test('async function', async () => {
10529-
let counter = 0
10530-
const delay = ms =>
10531-
new Promise(resolve => {
10532-
setTimeout(resolve, ms)
10533-
})
10534-
const fn = async (
10535-
ms, a, b
10536-
) => {
10537-
await delay(ms)
10538-
counter++
10539-
10540-
return a + b
10541-
}
10542-
10543-
const memoized = memoize(fn)
10544-
await expect(memoized(
10545-
100, 1, 2
10546-
)).resolves.toBe(3)
10547-
await expect(memoized(
10548-
100, 1, 2
10549-
)).resolves.toBe(3)
10550-
await expect(memoized(
10551-
100, 1, 2
10552-
)).resolves.toBe(3)
10553-
expect(counter).toBe(1)
10554-
await expect(memoized(
10555-
100, 2, 2
10556-
)).resolves.toBe(4)
10557-
expect(counter).toBe(2)
10558-
await expect(memoized(
10559-
100, 1, 2
10560-
)).resolves.toBe(3)
10561-
expect(counter).toBe(2)
10562-
})
10563-
10564-
test('string as argument', () => {
10565-
let count = 0
10566-
const foo = 'foo'
10567-
const tester = memoize(n => {
10568-
count++
10569-
10570-
return `${ n }bar`
10571-
})
10572-
tester(foo)
10573-
tester(foo)
10574-
tester(foo)
10575-
10576-
expect(tester(foo)).toBe('foobar')
10577-
10578-
expect(count).toBe(1)
10579-
10580-
tester('baz')
10581-
10582-
expect(tester('baz')).toBe('bazbar')
10583-
10584-
expect(count).toBe(2)
10585-
})
10586-
```
10587-
10588-
</details>
10589-
1059010390
[![---------------](https://raw.githubusercontent.com/selfrefactor/rambda/master/files/separator.png)](#memoize)
1059110391

1059210392
### memoizeWith
@@ -11919,7 +11719,7 @@ This method is also known as P combinator.
1191911719

1192011720
```typescript
1192111721

11922-
once<T extends AnyFunction>(func: T): T
11722+
once<T extends AnyFunction, C = unknown>(fn: T, context?: C): T
1192311723
```
1192411724

1192511725
It returns a function, which invokes only once `fn` function.
@@ -11999,6 +11799,17 @@ test('happy path', () => {
1199911799
)).toBe(60)
1200011800
expect(addOneOnce(40)).toBe(60)
1200111801
})
11802+
11803+
test('with context', () => {
11804+
const context = { name: 'fris' }
11805+
const getNameOnce = once(function (){
11806+
return this.name
11807+
}, context)
11808+
11809+
expect(getNameOnce()).toBe('fris')
11810+
expect(getNameOnce()).toBe('fris')
11811+
expect(getNameOnce()).toBe('fris')
11812+
})
1200211813
```
1200311814

1200411815
</details>
@@ -18138,13 +17949,17 @@ const result = [
1813817949
<summary><strong>R.unless</strong> source</summary>
1813917950

1814017951
```javascript
18141-
export function unless(predicate, whenFalse){
18142-
if (arguments.length === 1){
18143-
return _whenFalse => unless(predicate, _whenFalse)
18144-
}
17952+
import { curry } from './curry.js'
1814517953

18146-
return input => predicate(input) ? input : whenFalse(input)
17954+
function unlessFn(
17955+
predicate, whenFalseFn, input
17956+
){
17957+
if (predicate(input)) return input
17958+
17959+
return whenFalseFn(input)
1814717960
}
17961+
17962+
export const unless = curry(unlessFn)
1814817963
```
1814917964

1815017965
</details>
@@ -18168,6 +17983,11 @@ test('curried', () => {
1816817983
const safeIncCurried = unless(isNil)(inc)
1816917984
expect(safeIncCurried(null)).toBeNull()
1817017985
})
17986+
17987+
test('with 3 inputs', () => {
17988+
let result = unless(x => x.startsWith('/'), x=> x.concat('/'), '/api')
17989+
expect(result).toBe('/api')
17990+
})
1817117991
```
1817217992

1817317993
</details>
@@ -19554,6 +19374,12 @@ test('when second list is longer', () => {
1955419374

1955519375
## ❯ CHANGELOG
1955619376

19377+
11.1.0
19378+
19379+
- Improve `R.mapToObject` types - [Issue #96](https://github.com/selfrefactor/rambdax/issues/96)
19380+
19381+
- Sync with `Rambda` version `9.2.0`
19382+
1955719383
11.0.0
1955819384

1955919385
- Sync with `Rambda` version `9.1.0`

0 commit comments

Comments
 (0)