diff --git a/__tests__/Times.ts b/__tests__/Times.ts
new file mode 100644
index 000000000..9c503abff
--- /dev/null
+++ b/__tests__/Times.ts
@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+///
+
+import { Times } from '../';
+
+describe('Times', () => {
+ it('fixed times', () => {
+ const v = Times(5, n => n + 1);
+ expect(v.size).toBe(5);
+ expect(v.first()).toBe(2);
+ expect(v.rest().toArray()).toEqual([3, 4, 5, 6]);
+ expect(v.last()).toBe(6);
+ expect(v.butLast().toArray()).toEqual([2, 3, 4, 5]);
+ expect(v.toArray()).toEqual([2, 3, 4, 5, 6]);
+ });
+
+ it('defined seed', () => {
+ const v = Times(5, n => n + 1, 2);
+ expect(v.size).toBe(5);
+ expect(v.first()).toBe(3);
+ expect(v.rest().toArray()).toEqual([4, 5, 6, 7]);
+ expect(v.last()).toBe(7);
+ expect(v.butLast().toArray()).toEqual([3, 4, 5, 6]);
+ expect(v.toArray()).toEqual([3, 4, 5, 6, 7]);
+ });
+});
diff --git a/src/Immutable.js b/src/Immutable.js
index de672c8a7..d26da1c59 100644
--- a/src/Immutable.js
+++ b/src/Immutable.js
@@ -15,6 +15,7 @@ import { Set } from './Set';
import { Record } from './Record';
import { Range } from './Range';
import { Repeat } from './Repeat';
+import { Times } from './Times';
import { is } from './is';
import { fromJS } from './fromJS';
@@ -71,6 +72,7 @@ export default {
Record: Record,
Range: Range,
Repeat: Repeat,
+ Times: Times,
is: is,
fromJS: fromJS,
@@ -125,6 +127,7 @@ export {
Record,
Range,
Repeat,
+ Times,
is,
fromJS,
hash,
diff --git a/src/Times.js b/src/Times.js
new file mode 100644
index 000000000..07204450b
--- /dev/null
+++ b/src/Times.js
@@ -0,0 +1,55 @@
+/**
+ * Copyright (c) 2014-present, Facebook, Inc.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+import { ArraySeq } from './Seq';
+
+import deepEqual from './utils/deepEqual';
+
+/**
+ * Calls func with seed as the argument and returns an Seq.Indexed of the results,
+ * times and func are required and seed defaults to 1
+ */
+export class Times extends ArraySeq {
+ constructor(times, func, seed) {
+ if (!(this instanceof Times)) {
+ return new Times(times, func, seed);
+ }
+ const source = [];
+ seed = seed || 1;
+ times = Math.max(0, times);
+ this._times = times;
+ this._seed = seed;
+ this._func = func;
+ while (times > 0) {
+ seed = func(seed);
+ source.push(seed);
+ times--;
+ }
+ super(source);
+ if (this.size === 0) {
+ if (EMPTY_TIMES) {
+ return EMPTY_TIMES;
+ }
+ EMPTY_TIMES = this;
+ }
+ }
+ toString() {
+ if (this.size === 0) {
+ return 'Times []';
+ }
+ return this.toArray().toString();
+ }
+ equals(other) {
+ return other instanceof Times
+ ? this._times === other._times &&
+ this._seed === other._seed &&
+ this._func === other._func
+ : deepEqual(this, other);
+ }
+}
+
+let EMPTY_TIMES;
diff --git a/type-definitions/immutable.js.flow b/type-definitions/immutable.js.flow
index 2b37f4143..e4719a5a2 100644
--- a/type-definitions/immutable.js.flow
+++ b/type-definitions/immutable.js.flow
@@ -1380,6 +1380,7 @@ declare class Stack<+T> extends IndexedCollection {
declare function Range(start?: number, end?: number, step?: number): IndexedSeq;
declare function Repeat(value: T, times?: number): IndexedSeq;
+declare function Times(times: number, callback: (value: any) => any, seed?: any): IndexedSeq;
// The type of a Record factory function.
type RecordFactory = Class>;
@@ -1581,6 +1582,7 @@ export {
OrderedSet,
Range,
Repeat,
+ Times,
Record,
Set,
Stack,
@@ -1624,6 +1626,7 @@ export default {
OrderedSet,
Range,
Repeat,
+ Times,
Record,
Set,
Stack,
diff --git a/type-definitions/tests/immutable-flow.js b/type-definitions/tests/immutable-flow.js
index 0bc7289b0..2b9e2bbba 100644
--- a/type-definitions/tests/immutable-flow.js
+++ b/type-definitions/tests/immutable-flow.js
@@ -18,6 +18,7 @@ import Immutable, {
Seq,
Range,
Repeat,
+ Times,
Record,
OrderedMap,
OrderedSet,
@@ -64,6 +65,7 @@ const ImmutableSet = Immutable.Set
const ImmutableKeyedCollection: KeyedCollection<*, *> = Immutable.Collection.Keyed()
const ImmutableRange = Immutable.Range
const ImmutableRepeat = Immutable.Repeat
+const ImmutableTimes = Immutable.Times
const ImmutableIndexedSeq: IndexedSeq<*> = Immutable.Seq.Indexed()
const Immutable2List = Immutable2.List
@@ -73,6 +75,7 @@ const Immutable2Set = Immutable2.Set
const Immutable2KeyedCollection: Immutable2.KeyedCollection<*, *> = Immutable2.Collection.Keyed()
const Immutable2Range = Immutable2.Range
const Immutable2Repeat = Immutable2.Repeat
+const Immutable2Times = Immutable2.Times
const Immutable2IndexedSeq: Immutable2.IndexedSeq<*> = Immutable2.Seq.Indexed()
var defaultExport: List<*> = Immutable.List();
@@ -884,18 +887,20 @@ numberStack = Stack([1]).flatMap((value, index, iter) => ['a'])
numberStack = Stack([1]).flatten()
numberStack = Stack(['a']).flatten()
-/* Range & Repeat */
+/* Range & Repeat & Times */
// `{}` provide namespaces
{ const numberSequence: IndexedSeq = Range(0, 0, 0) }
{ const numberSequence: IndexedSeq = Repeat(1, 5) }
+{ const numberSequence: IndexedSeq = Times(5, n => n + 1) }
{ const stringSequence: IndexedSeq = Repeat('a', 5) }
// $ExpectError
{ const stringSequence: IndexedSeq = Repeat(0, 1) }
// $ExpectError
{ const stringSequence: IndexedSeq = Range(0, 0, 0) }
-
+// $ExpectError
+{ const stringSequence: IndexedSeq = Times('a', n => n + 1) }
/* Seq */
let numberSeq = Seq([ 1, 2, 3 ])