forked from marijnh/Eloquent-JavaScript
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path06_3_sequence_interface.js
More file actions
119 lines (110 loc) · 2.69 KB
/
06_3_sequence_interface.js
File metadata and controls
119 lines (110 loc) · 2.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// I am going to use a system where a sequence object has two methods:
//
// * next(), which returns a boolean indicating whether there are more
// elements in the sequence, and moves it forward to the next
// element when there are.
//
// * current(), which returns the current element, and should only be
// called after next() has returned true at least once.
function logFive(sequence) {
for (var i = 0; i < 5; i++) {
if (!sequence.next())
break;
console.log(sequence.current());
}
}
function ArraySeq(array) {
this.pos = -1;
this.array = array;
}
ArraySeq.prototype.next = function() {
if (this.pos >= this.array.length - 1)
return false;
this.pos++;
return true;
};
ArraySeq.prototype.current = function() {
return this.array[this.pos];
};
function RangeSeq(from, to) {
this.pos = from - 1;
this.to = to;
}
RangeSeq.prototype.next = function() {
if (this.pos >= this.to)
return false;
this.pos++;
return true;
};
RangeSeq.prototype.current = function() {
return this.pos;
};
logFive(new ArraySeq([1, 2]));
// → 1
// → 2
logFive(new RangeSeq(100, 1000));
// → 100
// → 101
// → 102
// → 103
// → 104
// This alternative approach represents the empty sequence as null,
// and gives non-empty sequences two methods:
//
// * head() returns the element at the start of the sequence.
//
// * rest() returns the rest of the sequence, or null if there are no
// elemements left.
//
// Because a JavaScript constructor can not return null, we add a make
// function to constructors of this type of sequence, which constructs
// a sequence, or returns null if the resulting sequence would be
// empty.
function logFive2(sequence) {
for (var i = 0; i < 5 && sequence != null; i++) {
console.log(sequence.head());
sequence = sequence.rest();
}
}
function ArraySeq2(array, offset) {
this.array = array;
this.offset = offset;
}
ArraySeq2.prototype.rest = function() {
return ArraySeq2.make(this.array, this.offset + 1);
};
ArraySeq2.prototype.head = function() {
return this.array[this.offset];
};
ArraySeq2.make = function(array, offset) {
if (offset == null) offset = 0;
if (offset >= array.length)
return null;
else
return new ArraySeq2(array, offset);
};
function RangeSeq2(from, to) {
this.from = from;
this.to = to;
}
RangeSeq2.prototype.rest = function() {
return RangeSeq2.make(this.from + 1, this.to);
};
RangeSeq2.prototype.head = function() {
return this.from;
};
RangeSeq2.make = function(from, to) {
if (from > to)
return null;
else
return new RangeSeq2(from, to);
};
logFive2(ArraySeq2.make([1, 2]));
// → 1
// → 2
logFive2(RangeSeq2.make(100, 1000));
// → 100
// → 101
// → 102
// → 103
// → 104