Skip to content

Commit

Permalink
List.merge* support
Browse files Browse the repository at this point in the history
  • Loading branch information
davecoates committed Sep 11, 2016
1 parent 0e3278d commit 6f2765d
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 0 deletions.
62 changes: 62 additions & 0 deletions src/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,35 @@ const change = (list, f) => {
}
}

const maxSizeFromIterables = (iterables) => {
let maxSize = 0;
for (let i = 0; i < iterables.length; i++) {
const iter = Indexed(iterables[i]);
if (iter.size > maxSize) {
maxSize = iter.size;
}
}
return maxSize;
}

const convertValuesToType = (type, values) => {
const items = []
const iter = Indexed(values);
let index = 0
while (index < iter.size) {
const value = iter.get(index)
const result = type[$read](value)

if (result instanceof TypeError) {
throw TypeError(`Invalid value: ${result.message}`)
}

items.push(result)
index = index + 1
}
return items;
}

const clear = target => target.clear()
const pop = target => target.pop()
const shift = target => target.shift()
Expand Down Expand Up @@ -236,6 +265,39 @@ class TypeInferedList extends BaseImmutableList {
return this[$store].wasAltered()
}

merge(...iterables) {
const maxSize = maxSizeFromIterables(iterables);
const typedIterables = iterables.map(convertValuesToType.bind(null, this[$type]));
if (maxSize > this.size) {
return change(this, store => store.setSize(maxSize)).merge(...typedIterables);
}
return change(this, store => store.merge(...typedIterables));
}

mergeWith(merger, ...iterables) {
const maxSize = maxSizeFromIterables(iterables);
if (maxSize > this.size) {
return change(this, store => store.setSize(maxSize).mergeWith(merger, ...iterables));
}
return change(this, store => store.mergeWith(merger, ...iterables));
}

mergeDeep(...iterables) {
const maxSize = maxSizeFromIterables(iterables);
if (maxSize > this.size) {
return change(this, store => store.setSize(maxSize).mergeDeep(...iterables));
}
return change(this, store => store.mergeDeep(...iterables));
}

mergeDeepWith(merger, ...iterables) {
const maxSize = maxSizeFromIterables(iterables);
if (maxSize > this.size) {
return change(this, store => store.setSize(maxSize).mergeDeepWith(merger, ...iterables));
}
return change(this, store => store.mergeDeepWith(merger, ...iterables));
}

__ensureOwner(ownerID) {
const result = this.__ownerID === ownerID ? this :
!ownerID ? this :
Expand Down
38 changes: 38 additions & 0 deletions src/test/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {List} from "../list"
import {Typed, Union, Maybe} from "../typed"

const NumberList = List(Number)
const NumberListOfNumbers = List(NumberList)
const StringList = List(String)
const Point = Record({x: Number(0),
y: Number(0)},
Expand Down Expand Up @@ -1015,3 +1016,40 @@ test('flatMap', assert => {

})

test('merge', assert => {
const numbers = NumberList.of(1, 2, 3)
assert.deepEqual(numbers.merge(NumberList.of(4, 5, 6, 7)).toArray(), [4, 5, 6, 7])
assert.deepEqual(numbers.merge(NumberList.of(4)).toArray(), [4, 2, 3])
assert.throws(() => numbers.merge([1,2], [4, 5, 6, '7']), /is not a number/)
})

test('mergeWith', assert => {
const numbers = NumberList.of(1, 2, 3)
const useExisting = (prev, next) => prev != null ? prev : next;
assert.deepEqual(numbers.mergeWith(useExisting, NumberList.of(4, 5, 6, 7)).toArray(), [1, 2, 3, 7])
assert.deepEqual(numbers.mergeWith(useExisting, NumberList.of(4)).toArray(), [1, 2, 3])
assert.throws(() => numbers.merge(useExisting, [4, 5, 6, '7']), /is not a number/)
})

test('mergeDeep', assert => {
var numbers = NumberListOfNumbers.of([1, 2, 3], [4, 5, 6])
assert.deepEqual(
numbers.mergeDeep([[10], [20, 21], [30]]).toJS(),
[[10, 2, 3], [20, 21, 6], [30]])
assert.deepEqual(
numbers.mergeDeep([[10, 11, 12, 13], [20, 21]]).toJS(),
[[10, 11, 12, 13], [20, 21, 6]])
assert.throws(() => numbers.mergeDeep([[10], ['11']], /is not a number/)
})

test('mergeDeepWith', assert => {
var numbers = NumberListOfNumbers.of([1, 2, 3], [4, 5, 6])
const add = (prev, next) => (prev || 0) + next;
assert.deepEqual(
numbers.mergeDeepWith(add, [[10], [20, 21]]).toJS(),
[[11, 2, 3], [24, 26, 6]])
assert.deepEqual(
numbers.mergeDeepWith(add, [[10, 11, 12, 13], [20, 21]]).toJS(),
[[11, 13, 15, 13], [24, 26, 6]])
assert.throws(() => numbers.mergeDeep(add, [[10], ['11']], /is not a number/)
})

0 comments on commit 6f2765d

Please sign in to comment.