Skip to content

Commit cc70bcb

Browse files
committed
Define skip and take in terms of slice
instead of doing the vice-versa. slice is a more generalized concept and centralizing this behavior makes it easier to override for custom collections and sequences.
1 parent 1c6b72d commit cc70bcb

File tree

6 files changed

+154
-281
lines changed

6 files changed

+154
-281
lines changed

dist/immutable.js

+50-111
Original file line numberDiff line numberDiff line change
@@ -446,16 +446,7 @@ var $Iterable = Iterable;
446446
return reify(this, reverseFactory(this, true));
447447
},
448448
slice: function(begin, end) {
449-
if (wholeSlice(begin, end, this.size)) {
450-
return this;
451-
}
452-
var resolvedBegin = resolveBegin(begin, this.size);
453-
var resolvedEnd = resolveEnd(end, this.size);
454-
if (resolvedBegin !== resolvedBegin || resolvedEnd !== resolvedEnd) {
455-
return this.toSeq().cacheResult().slice(begin, end);
456-
}
457-
var skipped = resolvedBegin === 0 ? this : this.skip(resolvedBegin);
458-
return reify(this, resolvedEnd === undefined || resolvedEnd === this.size ? skipped : skipped.take(resolvedEnd - resolvedBegin));
449+
return reify(this, sliceFactory(this, begin, end, true));
459450
},
460451
some: function(predicate, context) {
461452
return !this.every(not(predicate), context);
@@ -570,7 +561,7 @@ var $Iterable = Iterable;
570561
return this.slice(1);
571562
},
572563
skip: function(amount) {
573-
return reify(this, skipFactory(this, amount, true));
564+
return this.slice(Math.max(0, amount));
574565
},
575566
skipLast: function(amount) {
576567
return reify(this, this.toSeq().reverse().skip(amount).reverse());
@@ -585,7 +576,7 @@ var $Iterable = Iterable;
585576
return reify(this, sortFactory(this, comparator, mapper));
586577
},
587578
take: function(amount) {
588-
return reify(this, takeFactory(this, amount));
579+
return this.slice(0, Math.max(0, amount));
589580
},
590581
takeLast: function(amount) {
591582
return reify(this, this.toSeq().reverse().take(amount).reverse());
@@ -709,6 +700,9 @@ var IndexedIterable = function IndexedIterable(value) {
709700
reverse: function() {
710701
return reify(this, reverseFactory(this, false));
711702
},
703+
slice: function(begin, end) {
704+
return reify(this, sliceFactory(this, begin, end, false));
705+
},
712706
splice: function(index, removeNum) {
713707
var numArgs = arguments.length;
714708
removeNum = Math.max(removeNum | 0, 0);
@@ -745,30 +739,8 @@ var IndexedIterable = function IndexedIterable(value) {
745739
last: function() {
746740
return this.get(-1);
747741
},
748-
skip: function(amount) {
749-
var iter = this;
750-
var skipSeq = skipFactory(iter, amount, false);
751-
if (isSeq(iter) && skipSeq !== iter) {
752-
skipSeq.get = function(index, notSetValue) {
753-
index = wrapIndex(this, index);
754-
return index >= 0 ? iter.get(index + amount, notSetValue) : notSetValue;
755-
};
756-
}
757-
return reify(this, skipSeq);
758-
},
759742
skipWhile: function(predicate, context) {
760743
return reify(this, skipWhileFactory(this, predicate, context, false));
761-
},
762-
take: function(amount) {
763-
var iter = this;
764-
var takeSeq = takeFactory(iter, amount);
765-
if (isSeq(iter) && takeSeq !== iter) {
766-
takeSeq.get = function(index, notSetValue) {
767-
index = wrapIndex(this, index);
768-
return index >= 0 && index < amount ? iter.get(index, notSetValue) : notSetValue;
769-
};
770-
}
771-
return reify(this, takeSeq);
772744
}
773745
}, {}, Iterable);
774746
IndexedIterable.prototype[IS_INDEXED_SENTINEL] = true;
@@ -2247,43 +2219,72 @@ function groupByFactory(iterable, grouper, context) {
22472219
return reify(iterable, coerce(arr));
22482220
}));
22492221
}
2250-
function takeFactory(iterable, amount) {
2251-
if (amount > iterable.size) {
2222+
function sliceFactory(iterable, begin, end, useKeys) {
2223+
var originalSize = iterable.size;
2224+
if (wholeSlice(begin, end, originalSize)) {
22522225
return iterable;
22532226
}
2254-
if (amount < 0) {
2255-
amount = 0;
2227+
var resolvedBegin = resolveBegin(begin, originalSize);
2228+
var resolvedEnd = resolveEnd(end, originalSize);
2229+
if (resolvedBegin !== resolvedBegin || resolvedEnd !== resolvedEnd) {
2230+
return sliceFactory(iterable.toSeq().cacheResult(), begin, end, useKeys);
2231+
}
2232+
var sliceSize = resolvedEnd - resolvedBegin;
2233+
if (sliceSize < 0) {
2234+
sliceSize = 0;
2235+
}
2236+
var sliceSeq = makeSequence(iterable);
2237+
sliceSeq.size = sliceSize === 0 ? sliceSize : iterable.size && sliceSize || undefined;
2238+
if (!useKeys && isSeq(iterable) && sliceSize >= 0) {
2239+
sliceSeq.get = function(index, notSetValue) {
2240+
index = wrapIndex(this, index);
2241+
return index >= 0 && index < sliceSize ? iterable.get(index + resolvedBegin, notSetValue) : notSetValue;
2242+
};
22562243
}
2257-
var takeSequence = makeSequence(iterable);
2258-
takeSequence.size = iterable.size && Math.min(iterable.size, amount);
2259-
takeSequence.__iterateUncached = function(fn, reverse) {
2244+
sliceSeq.__iterateUncached = function(fn, reverse) {
22602245
var $__0 = this;
2261-
if (amount === 0) {
2246+
if (sliceSize === 0) {
22622247
return 0;
22632248
}
22642249
if (reverse) {
22652250
return this.cacheResult().__iterate(fn, reverse);
22662251
}
2252+
var skipped = 0;
2253+
var isSkipping = true;
22672254
var iterations = 0;
22682255
iterable.__iterate((function(v, k) {
2269-
return ++iterations && fn(v, k, $__0) !== false && iterations < amount;
2256+
if (!(isSkipping && (isSkipping = skipped++ < resolvedBegin))) {
2257+
iterations++;
2258+
return fn(v, useKeys ? k : iterations - 1, $__0) !== false && iterations !== sliceSize;
2259+
}
22702260
}));
22712261
return iterations;
22722262
};
2273-
takeSequence.__iteratorUncached = function(type, reverse) {
2274-
if (reverse) {
2263+
sliceSeq.__iteratorUncached = function(type, reverse) {
2264+
if (sliceSize && reverse) {
22752265
return this.cacheResult().__iterator(type, reverse);
22762266
}
2277-
var iterator = amount && iterable.__iterator(type, reverse);
2267+
var iterator = sliceSize && iterable.__iterator(type, reverse);
2268+
var skipped = 0;
22782269
var iterations = 0;
22792270
return new Iterator((function() {
2280-
if (iterations++ > amount) {
2271+
while (skipped++ !== resolvedBegin) {
2272+
iterator.next();
2273+
}
2274+
if (++iterations > sliceSize) {
22812275
return iteratorDone();
22822276
}
2283-
return iterator.next();
2277+
var step = iterator.next();
2278+
if (useKeys || type === ITERATE_VALUES) {
2279+
return step;
2280+
} else if (type === ITERATE_KEYS) {
2281+
return iteratorValue(type, iterations - 1, undefined, step);
2282+
} else {
2283+
return iteratorValue(type, iterations - 1, step.value[1], step);
2284+
}
22842285
}));
22852286
};
2286-
return takeSequence;
2287+
return sliceSeq;
22872288
}
22882289
function takeWhileFactory(iterable, predicate, context) {
22892290
var takeSequence = makeSequence(iterable);
@@ -2325,52 +2326,6 @@ function takeWhileFactory(iterable, predicate, context) {
23252326
};
23262327
return takeSequence;
23272328
}
2328-
function skipFactory(iterable, amount, useKeys) {
2329-
if (amount <= 0) {
2330-
return iterable;
2331-
}
2332-
var skipSequence = makeSequence(iterable);
2333-
skipSequence.size = iterable.size && Math.max(0, iterable.size - amount);
2334-
skipSequence.__iterateUncached = function(fn, reverse) {
2335-
var $__0 = this;
2336-
if (reverse) {
2337-
return this.cacheResult().__iterate(fn, reverse);
2338-
}
2339-
var skipped = 0;
2340-
var isSkipping = true;
2341-
var iterations = 0;
2342-
iterable.__iterate((function(v, k) {
2343-
if (!(isSkipping && (isSkipping = skipped++ < amount))) {
2344-
iterations++;
2345-
return fn(v, useKeys ? k : iterations - 1, $__0);
2346-
}
2347-
}));
2348-
return iterations;
2349-
};
2350-
skipSequence.__iteratorUncached = function(type, reverse) {
2351-
if (reverse) {
2352-
return this.cacheResult().__iterator(type, reverse);
2353-
}
2354-
var iterator = amount && iterable.__iterator(type, reverse);
2355-
var skipped = 0;
2356-
var iterations = 0;
2357-
return new Iterator((function() {
2358-
while (skipped < amount) {
2359-
skipped++;
2360-
iterator.next();
2361-
}
2362-
var step = iterator.next();
2363-
if (useKeys || type === ITERATE_VALUES) {
2364-
return step;
2365-
} else if (type === ITERATE_KEYS) {
2366-
return iteratorValue(type, iterations++, undefined, step);
2367-
} else {
2368-
return iteratorValue(type, iterations++, step.value[1], step);
2369-
}
2370-
}));
2371-
};
2372-
return skipSequence;
2373-
}
23742329
function skipWhileFactory(iterable, predicate, context, useKeys) {
23752330
var skipSequence = makeSequence(iterable);
23762331
skipSequence.__iterateUncached = function(fn, reverse) {
@@ -3791,12 +3746,6 @@ var $Range = Range;
37913746
lastIndexOf: function(searchValue) {
37923747
return this.indexOf(searchValue);
37933748
},
3794-
take: function(amount) {
3795-
return this.slice(0, Math.max(0, amount));
3796-
},
3797-
skip: function(amount) {
3798-
return this.slice(Math.max(0, amount));
3799-
},
38003749
__iterate: function(fn, reverse) {
38013750
var maxIndex = this.size - 1;
38023751
var step = this._step;
@@ -3824,10 +3773,6 @@ var $Range = Range;
38243773
return other instanceof $Range ? this._start === other._start && this._end === other._end && this._step === other._step : deepEqual(this, other);
38253774
}
38263775
}, {}, IndexedSeq);
3827-
var RangePrototype = Range.prototype;
3828-
RangePrototype.__toJS = RangePrototype.toArray;
3829-
RangePrototype.first = ListPrototype.first;
3830-
RangePrototype.last = ListPrototype.last;
38313776
var __EMPTY_RANGE = Range(0, 0);
38323777
var Repeat = function Repeat(value, times) {
38333778
if (times <= 0 && EMPTY_REPEAT) {
@@ -3894,12 +3839,6 @@ var $Repeat = Repeat;
38943839
return other instanceof $Repeat ? is(this._value, other._value) : deepEqual(other);
38953840
}
38963841
}, {}, IndexedSeq);
3897-
var RepeatPrototype = Repeat.prototype;
3898-
RepeatPrototype.last = RepeatPrototype.first;
3899-
RepeatPrototype.has = RangePrototype.has;
3900-
RepeatPrototype.take = RangePrototype.take;
3901-
RepeatPrototype.skip = RangePrototype.skip;
3902-
RepeatPrototype.__toJS = RangePrototype.__toJS;
39033842
var EMPTY_REPEAT;
39043843
var Immutable = {
39053844
Iterable: Iterable,

0 commit comments

Comments
 (0)