@effekt-lang/effekt 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/effekt +0 -0
- package/libraries/common/array.effekt +23 -47
- package/libraries/common/bench.effekt +11 -19
- package/libraries/common/buffer.effekt +8 -20
- package/libraries/common/bytes.effekt +5 -15
- package/libraries/common/dequeue.effekt +5 -5
- package/libraries/common/effekt.effekt +21 -23
- package/libraries/common/io/console.effekt +1 -3
- package/libraries/common/io/error.effekt +20 -28
- package/libraries/common/io/filesystem.effekt +11 -23
- package/libraries/common/list.effekt +333 -333
- package/libraries/common/queue.effekt +1 -3
- package/libraries/common/ref.effekt +7 -17
- package/libraries/common/result.effekt +6 -14
- package/libraries/common/seq.effekt +28 -49
- package/libraries/common/string.effekt +7 -15
- package/licenses/eclipse public license, version 2.0 - epl-2.0.html +2 -2
- package/licenses/mit license - mit-license.html +13 -12
- package/licenses/the bsd license - bsd-license.html +12 -13
- package/licenses/the mit license - mit.html +13 -12
- package/package.json +1 -1
|
@@ -4,32 +4,32 @@ import effekt
|
|
|
4
4
|
import option
|
|
5
5
|
import exception
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
/// Immutable linked list for finite sequences of elements.
|
|
8
8
|
type List[A] {
|
|
9
9
|
Nil();
|
|
10
10
|
Cons(head: A, tail: List[A])
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
/// Create an empty list.
|
|
14
|
+
///
|
|
15
|
+
/// O(1)
|
|
16
16
|
def empty[A](): List[A] = Nil()
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
/// Create a list with one element.
|
|
19
|
+
///
|
|
20
|
+
/// O(1)
|
|
21
21
|
def singleton[A](x: A): List[A] = Cons(x, Nil())
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
/// Create a list of length `size` where all elements are `default`.
|
|
24
|
+
///
|
|
25
|
+
/// O(size)
|
|
26
26
|
def fill[A](size: Int, default: A): List[A] = {
|
|
27
27
|
build(size) { i => default }
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
/// Create a list from a function `index` of given `size`.
|
|
31
|
+
///
|
|
32
|
+
/// O(size)
|
|
33
33
|
def build[A](size: Int) { index: Int => A }: List[A] = {
|
|
34
34
|
var result = empty()
|
|
35
35
|
each(0, size) { i =>
|
|
@@ -38,52 +38,52 @@ def build[A](size: Int) { index: Int => A }: List[A] = {
|
|
|
38
38
|
result.reverse
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
/// Check if list is empty.
|
|
42
|
+
///
|
|
43
|
+
/// O(1)
|
|
44
44
|
def isEmpty[A](l: List[A]): Bool = l match {
|
|
45
45
|
case Nil() => true
|
|
46
46
|
case Cons(a, rest) => false
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
/// Check if list is nonempty.
|
|
50
|
+
///
|
|
51
|
+
/// O(1)
|
|
52
52
|
def nonEmpty[A](l: List[A]): Bool = l match {
|
|
53
53
|
case Nil() => false
|
|
54
54
|
case Cons(a, rest) => true
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
/// Return the first element of a given list.
|
|
58
|
+
/// Throws a `MissingValue` exception if it's empty.
|
|
59
|
+
///
|
|
60
|
+
/// O(1)
|
|
61
61
|
def head[A](l: List[A]): A / Exception[MissingValue] = l match {
|
|
62
62
|
case Nil() => do raise(MissingValue(), "Trying to get the head of an empty list")
|
|
63
63
|
case Cons(a, rest) => a
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
/// Return all elements of a given list except the first element.
|
|
67
|
+
/// Throws a `MissingValue` exception if it's empty.
|
|
68
|
+
///
|
|
69
|
+
/// O(1)
|
|
70
70
|
def tail[A](l: List[A]): List[A] / Exception[MissingValue] = l match {
|
|
71
71
|
case Nil() => do raise(MissingValue(), "Trying to get the head of an empty list")
|
|
72
72
|
case Cons(a, rest) => rest
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
/// Return the first element of a given list.
|
|
76
|
+
/// Returns `None()` if it's empty.
|
|
77
|
+
///
|
|
78
|
+
/// O(1)
|
|
79
79
|
def headOption[A](l: List[A]): Option[A] = l match {
|
|
80
80
|
case Nil() => None()
|
|
81
81
|
case Cons(a, rest) => Some(a)
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
/// Returns the last element of a given list.
|
|
85
|
+
///
|
|
86
|
+
/// O(N)
|
|
87
87
|
def last[A](l: List[A]): A / Exception[MissingValue] = {
|
|
88
88
|
def go(list: List[A]): A = {
|
|
89
89
|
list match {
|
|
@@ -96,9 +96,9 @@ def last[A](l: List[A]): A / Exception[MissingValue] = {
|
|
|
96
96
|
go(l)
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
/// Get the value at given index.
|
|
100
|
+
///
|
|
101
|
+
/// O(N)
|
|
102
102
|
def get[A](list: List[A], index: Int): A / Exception[OutOfBounds] = {
|
|
103
103
|
def go(list: List[A], i: Int): A = {
|
|
104
104
|
list match {
|
|
@@ -111,17 +111,17 @@ def get[A](list: List[A], index: Int): A / Exception[OutOfBounds] = {
|
|
|
111
111
|
go(list, index)
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
114
|
+
/// Traverse a list, applying the given action on every element.
|
|
115
|
+
///
|
|
116
|
+
/// O(N)
|
|
117
117
|
def foreach[A](l: List[A]) { f: (A) => Unit } : Unit = l match {
|
|
118
118
|
case Nil() => ()
|
|
119
119
|
case Cons(head, tail) => f(head); tail.foreach {f}
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
122
|
+
/// Traverse a list, applying the given action on every element.
|
|
123
|
+
///
|
|
124
|
+
/// O(N)
|
|
125
125
|
def foreach[A](l: List[A]) { f: (A) {Control} => Unit } : Unit = {
|
|
126
126
|
var remainder = l
|
|
127
127
|
loop { {label} =>
|
|
@@ -134,9 +134,9 @@ def foreach[A](l: List[A]) { f: (A) {Control} => Unit } : Unit = {
|
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
137
|
+
/// Traverse a list, applying the given action on every element and its (zero-based) index.
|
|
138
|
+
///
|
|
139
|
+
/// O(N)
|
|
140
140
|
def foreachIndex[A](list: List[A]){ f: (Int, A) => Unit }: Unit = {
|
|
141
141
|
def loop(index: Int, remainder: List[A]): Unit = remainder match {
|
|
142
142
|
case Nil() => ()
|
|
@@ -147,9 +147,9 @@ def foreachIndex[A](list: List[A]){ f: (Int, A) => Unit }: Unit = {
|
|
|
147
147
|
loop(0, list)
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
150
|
+
/// Traverse a list, applying the given action on every element and its (zero-based) index.
|
|
151
|
+
///
|
|
152
|
+
/// O(N)
|
|
153
153
|
def foreachIndex[A](list: List[A]){ f: (Int, A) {Control} => Unit }: Unit = {
|
|
154
154
|
var remainder = list
|
|
155
155
|
var i = -1
|
|
@@ -164,20 +164,20 @@ def foreachIndex[A](list: List[A]){ f: (Int, A) {Control} => Unit }: Unit = {
|
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
167
|
+
/// Map a function `f` over elements in a given list.
|
|
168
|
+
///
|
|
169
|
+
/// O(N)
|
|
170
170
|
def map[A, B](l: List[A]) { f: A => B } : List[B] = {
|
|
171
171
|
var acc = Nil[B]()
|
|
172
172
|
l.foreach { el => acc = Cons(f(el), acc) }
|
|
173
173
|
acc.reverse
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
176
|
+
/// Map a function `f` over elements in a given list,
|
|
177
|
+
/// keeping only the elements for which the function returned `Some(...)`,
|
|
178
|
+
/// discarding the elements for which the function returned `None()`.
|
|
179
|
+
///
|
|
180
|
+
/// O(N)
|
|
181
181
|
def collect[A, B](l: List[A]) { f : A => Option[B] }: List[B] = {
|
|
182
182
|
var acc = Nil[B]()
|
|
183
183
|
l.foreach { a =>
|
|
@@ -190,9 +190,9 @@ def collect[A, B](l: List[A]) { f : A => Option[B] }: List[B] = {
|
|
|
190
190
|
acc.reverse
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
193
|
+
/// Map a function `f` over elements in a given list and concatenate the results.
|
|
194
|
+
///
|
|
195
|
+
/// O(N)
|
|
196
196
|
def flatMap[A, B](l: List[A]) { f : A => List[B] }: List[B] = {
|
|
197
197
|
var acc = Nil[B]()
|
|
198
198
|
l.foreach { a =>
|
|
@@ -202,9 +202,9 @@ def flatMap[A, B](l: List[A]) { f : A => List[B] }: List[B] = {
|
|
|
202
202
|
acc
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
205
|
+
/// Check if predicate is true for all elements of the given list.
|
|
206
|
+
///
|
|
207
|
+
/// O(N)
|
|
208
208
|
def all[A](list: List[A]) { predicate: A => Bool }: Bool = {
|
|
209
209
|
list match {
|
|
210
210
|
case Cons(x, xs) => predicate(x) && all(xs) { predicate }
|
|
@@ -212,9 +212,9 @@ def all[A](list: List[A]) { predicate: A => Bool }: Bool = {
|
|
|
212
212
|
}
|
|
213
213
|
}
|
|
214
214
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
215
|
+
/// Check if predicate is true for at least one element of the given list.
|
|
216
|
+
///
|
|
217
|
+
/// O(N)
|
|
218
218
|
def any[A](list: List[A]) { predicate: A => Bool }: Bool = {
|
|
219
219
|
list match {
|
|
220
220
|
case Cons(x, xs) => predicate(x) || any(xs) { predicate }
|
|
@@ -222,89 +222,89 @@ def any[A](list: List[A]) { predicate: A => Bool }: Bool = {
|
|
|
222
222
|
}
|
|
223
223
|
}
|
|
224
224
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
225
|
+
/// Fold a list using `f`, starting from the left given a starting value.
|
|
226
|
+
///
|
|
227
|
+
/// O(N)
|
|
228
228
|
def foldLeft[A, B](l: List[A], init: B) { f: (B, A) => B }: B = {
|
|
229
229
|
var acc = init;
|
|
230
230
|
l.foreach { x => acc = f(acc, x) };
|
|
231
231
|
acc
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
234
|
+
/// Fold a list using `f`, starting from the right given a starting value.
|
|
235
|
+
///
|
|
236
|
+
/// O(N)
|
|
237
237
|
def foldRight[A, B](l: List[A], init: B) { f: (A, B) => B }: B = {
|
|
238
238
|
var acc = init;
|
|
239
239
|
l.reverse.foreach { x => acc = f(x, acc) };
|
|
240
240
|
acc
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
243
|
+
/// Sum the elements of the list.
|
|
244
|
+
///
|
|
245
|
+
/// O(N)
|
|
246
246
|
def sum(list: List[Int]): Int = {
|
|
247
247
|
var n = 0;
|
|
248
248
|
list.foreach { x => n = n + x };
|
|
249
249
|
n
|
|
250
250
|
}
|
|
251
251
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
252
|
+
/// Calculate the size of the list.
|
|
253
|
+
///
|
|
254
|
+
/// O(N)
|
|
255
255
|
def size[A](l: List[A]): Int = {
|
|
256
256
|
var n = 0;
|
|
257
257
|
l.foreach { _ => n = n + 1 };
|
|
258
258
|
n
|
|
259
259
|
}
|
|
260
260
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
261
|
+
/// Reverse the list.
|
|
262
|
+
///
|
|
263
|
+
/// O(N)
|
|
264
264
|
def reverse[A](l: List[A]): List[A] = {
|
|
265
265
|
var res = Nil[A]()
|
|
266
266
|
l.foreach { el => res = Cons(el, res) }
|
|
267
267
|
res
|
|
268
268
|
}
|
|
269
269
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
270
|
+
/// Reverse a list `l` and append `other` to it.
|
|
271
|
+
///
|
|
272
|
+
/// Example:
|
|
273
|
+
/// ```
|
|
274
|
+
/// > [1,2,3].reverseOnto([4,5,6])
|
|
275
|
+
/// [3,2,1,4,5,6]
|
|
276
|
+
/// ```
|
|
277
|
+
///
|
|
278
|
+
/// O(|l|)
|
|
279
279
|
def reverseOnto[A](l: List[A], other: List[A]): List[A] = l match {
|
|
280
280
|
case Nil() => other
|
|
281
281
|
case Cons(a, rest) => rest.reverseOnto(Cons(a, other))
|
|
282
282
|
}
|
|
283
283
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
284
|
+
/// Concatenate list `l` with list `other`:
|
|
285
|
+
///
|
|
286
|
+
/// Example:
|
|
287
|
+
/// ```
|
|
288
|
+
/// > [1,2,3].append([4,5,6])
|
|
289
|
+
/// [1,2,3,4,5,6]
|
|
290
|
+
/// ```
|
|
291
|
+
///
|
|
292
|
+
/// O(N)
|
|
293
293
|
def append[A](l: List[A], other: List[A]): List[A] =
|
|
294
294
|
l.reverse.reverseOnto(other)
|
|
295
295
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
296
|
+
/// Flatten a list of lists into a single list.
|
|
297
|
+
///
|
|
298
|
+
/// Examples:
|
|
299
|
+
/// ```
|
|
300
|
+
/// > [[1, 2, 3], [4, 5], [6]].join()
|
|
301
|
+
/// [1, 2, 3, 4, 5, 6]
|
|
302
|
+
///
|
|
303
|
+
/// > [[]].join()
|
|
304
|
+
/// []
|
|
305
|
+
/// ```
|
|
306
|
+
///
|
|
307
|
+
/// O(N)
|
|
308
308
|
def join[A](lists: List[List[A]]): List[A] = {
|
|
309
309
|
var acc: List[A] = Nil()
|
|
310
310
|
lists.foreach { list =>
|
|
@@ -313,19 +313,19 @@ def join[A](lists: List[List[A]]): List[A] = {
|
|
|
313
313
|
acc
|
|
314
314
|
}
|
|
315
315
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
316
|
+
/// Flatten a list of lists into a single list,
|
|
317
|
+
/// putting the `between` list in between each list in the input.
|
|
318
|
+
///
|
|
319
|
+
/// Examples:
|
|
320
|
+
/// ```
|
|
321
|
+
/// > [[100], [200, 300], [400]].join([1, 2, 3])
|
|
322
|
+
/// [100, 1, 2, 3, 200, 300, 1, 2, 3, 400]
|
|
323
|
+
///
|
|
324
|
+
/// > [[]].join([1, 2, 3])
|
|
325
|
+
/// []
|
|
326
|
+
/// ```
|
|
327
|
+
///
|
|
328
|
+
/// O(N)
|
|
329
329
|
def join[A](lists: List[List[A]], between: List[A]): List[A] = {
|
|
330
330
|
lists match {
|
|
331
331
|
case Nil() => Nil()
|
|
@@ -336,27 +336,27 @@ def join[A](lists: List[List[A]], between: List[A]): List[A] = {
|
|
|
336
336
|
}
|
|
337
337
|
}
|
|
338
338
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
339
|
+
/// Take the first `n` elements of a given list.
|
|
340
|
+
///
|
|
341
|
+
/// Examples:
|
|
342
|
+
/// ```
|
|
343
|
+
/// > [1, 2, 3].take(2)
|
|
344
|
+
/// [1, 2]
|
|
345
|
+
///
|
|
346
|
+
/// > [1, 2, 3].take(0)
|
|
347
|
+
/// []
|
|
348
|
+
///
|
|
349
|
+
/// > [1, 2, 3].take(3)
|
|
350
|
+
/// [1, 2, 3]
|
|
351
|
+
///
|
|
352
|
+
/// > [1, 2, 3].take(5)
|
|
353
|
+
/// [1, 2, 3]
|
|
354
|
+
///
|
|
355
|
+
/// > [1, 2, 3].take(-1)
|
|
356
|
+
/// []
|
|
357
|
+
/// ```
|
|
358
|
+
///
|
|
359
|
+
/// O(n)
|
|
360
360
|
def take[A](l: List[A], n: Int): List[A] =
|
|
361
361
|
if (n <= 0) {
|
|
362
362
|
Nil()
|
|
@@ -365,27 +365,27 @@ def take[A](l: List[A], n: Int): List[A] =
|
|
|
365
365
|
case Cons(a, rest) => Cons(a, rest.take(n - 1))
|
|
366
366
|
}
|
|
367
367
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
368
|
+
/// Drop the first `n` elements of a given list.
|
|
369
|
+
///
|
|
370
|
+
/// Examples:
|
|
371
|
+
/// ```
|
|
372
|
+
/// > [1, 2, 3].drop(2)
|
|
373
|
+
/// [3]
|
|
374
|
+
///
|
|
375
|
+
/// > [1, 2, 3].drop(0)
|
|
376
|
+
/// [1, 2, 3]
|
|
377
|
+
///
|
|
378
|
+
/// > [1, 2, 3].drop(3)
|
|
379
|
+
/// []
|
|
380
|
+
///
|
|
381
|
+
/// > [1, 2, 3].drop(5)
|
|
382
|
+
/// []
|
|
383
|
+
///
|
|
384
|
+
/// > [1, 2, 3].drop(-1)
|
|
385
|
+
/// [1, 2, 3]
|
|
386
|
+
/// ```
|
|
387
|
+
///
|
|
388
|
+
/// O(n)
|
|
389
389
|
def drop[A](l: List[A], n: Int): List[A] =
|
|
390
390
|
if (n <= 0) {
|
|
391
391
|
l
|
|
@@ -394,57 +394,57 @@ def drop[A](l: List[A], n: Int): List[A] =
|
|
|
394
394
|
case Cons(a, rest) => rest.drop(n - 1)
|
|
395
395
|
}
|
|
396
396
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
397
|
+
/// Return a slice of a given list from the starting index (inclusive)
|
|
398
|
+
/// to the given end index (exclusive).
|
|
399
|
+
///
|
|
400
|
+
/// Examples:
|
|
401
|
+
/// ```
|
|
402
|
+
/// > [1, 2, 3, 4, 5, 6].slice(1, 4)
|
|
403
|
+
/// [2, 3, 4]
|
|
404
|
+
///
|
|
405
|
+
/// > [1, 2, 3, 4, 5, 6].slice(1, 2)
|
|
406
|
+
/// [2]
|
|
407
|
+
///
|
|
408
|
+
/// > [1, 2, 3, 4, 5, 6].slice(1, 1)
|
|
409
|
+
/// []
|
|
410
|
+
///
|
|
411
|
+
/// > [1, 2, 3, 4, 5, 6].slice(4, 1)
|
|
412
|
+
/// []
|
|
413
|
+
///
|
|
414
|
+
/// > [1, 2, 3, 4, 5, 6].slice(-100, 100)
|
|
415
|
+
/// [1, 2, 3, 4, 5, 6]
|
|
416
|
+
/// ```
|
|
417
|
+
///
|
|
418
|
+
/// O(N)
|
|
419
419
|
def slice[A](list: List[A], start: Int, stopExclusive: Int): List[A] = {
|
|
420
420
|
val prefix = list.drop(start)
|
|
421
421
|
val length = stopExclusive - start
|
|
422
422
|
prefix.take(length)
|
|
423
423
|
}
|
|
424
424
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
425
|
+
/// Split the list at given index.
|
|
426
|
+
///
|
|
427
|
+
/// Law: `val (l, r) = list.splitAt(i); l.append(r) === list`
|
|
428
|
+
///
|
|
429
|
+
/// O(N)
|
|
430
430
|
def splitAt[A](list: List[A], index: Int): (List[A], List[A]) = {
|
|
431
431
|
(list.take(index), list.drop(index))
|
|
432
432
|
}
|
|
433
433
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
434
|
+
/// Update the element at given index in the list using the `update` function.
|
|
435
|
+
/// Returns the original list if the index is out of bounds.
|
|
436
|
+
///
|
|
437
|
+
/// See: `modifyAt`
|
|
438
|
+
/// Examples:
|
|
439
|
+
/// ```
|
|
440
|
+
/// > [1, 2, 3].updateAt(1) { n => n + 100 }
|
|
441
|
+
/// [1, 102, 3]
|
|
442
|
+
///
|
|
443
|
+
/// > [1, 2, 3].updateAt(10) { n => n + 100 }
|
|
444
|
+
/// [1, 2, 3]
|
|
445
|
+
/// ```
|
|
446
|
+
///
|
|
447
|
+
/// O(N)
|
|
448
448
|
def updateAt[A](list: List[A], index: Int) { update: A => A }: List[A] = {
|
|
449
449
|
list.splitAt(index) match {
|
|
450
450
|
case (left, Cons(x, right)) =>
|
|
@@ -453,20 +453,20 @@ def updateAt[A](list: List[A], index: Int) { update: A => A }: List[A] = {
|
|
|
453
453
|
}
|
|
454
454
|
}
|
|
455
455
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
456
|
+
/// Modify the element at given index in the list using the `update` function.
|
|
457
|
+
/// Throws `OutOfBounds` if the index is out of bounds.
|
|
458
|
+
///
|
|
459
|
+
/// See: `updateAt`
|
|
460
|
+
/// Examples:
|
|
461
|
+
/// ```
|
|
462
|
+
/// > [1, 2, 3].modifyAt(1) { n => n + 100 }
|
|
463
|
+
/// Some([1, 102, 3])
|
|
464
|
+
///
|
|
465
|
+
/// > [1, 2, 3].modifyAt(10) { n => n + 100 }
|
|
466
|
+
/// None()
|
|
467
|
+
/// ```
|
|
468
|
+
///
|
|
469
|
+
/// O(N)
|
|
470
470
|
def modifyAt[A](list: List[A], index: Int) { update: A => A }: List[A] / Exception[OutOfBounds] = {
|
|
471
471
|
list.splitAt(index) match {
|
|
472
472
|
case (left, Cons(x, right)) =>
|
|
@@ -475,69 +475,69 @@ def modifyAt[A](list: List[A], index: Int) { update: A => A }: List[A] / Excepti
|
|
|
475
475
|
}
|
|
476
476
|
}
|
|
477
477
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
478
|
+
/// Delete the element at given index in the list.
|
|
479
|
+
///
|
|
480
|
+
/// Example:
|
|
481
|
+
/// ```
|
|
482
|
+
/// > [1, 2, 3, 4].deleteAt(1)
|
|
483
|
+
/// [1, 3, 4]
|
|
484
|
+
///
|
|
485
|
+
/// > [1, 2, 3, 4].deleteAt(-1)
|
|
486
|
+
/// [1, 2, 3, 4]
|
|
487
|
+
///
|
|
488
|
+
/// > [1, 2, 3, 4].deleteAt(10)
|
|
489
|
+
/// [1, 2, 3, 4]
|
|
490
|
+
/// ```
|
|
491
|
+
///
|
|
492
|
+
/// O(N)
|
|
493
493
|
def deleteAt[A](list: List[A], index: Int): List[A] = {
|
|
494
494
|
val left = list.slice(0, index)
|
|
495
495
|
val right = list.slice(index + 1, list.size())
|
|
496
496
|
left.append(right)
|
|
497
497
|
}
|
|
498
498
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
499
|
+
/// Add an element at given index in the list.
|
|
500
|
+
///
|
|
501
|
+
/// Examples:
|
|
502
|
+
/// ```
|
|
503
|
+
/// > [1, 2, 3].insert(-1, 0)
|
|
504
|
+
/// [0, 1, 2, 3]
|
|
505
|
+
///
|
|
506
|
+
/// > [1, 2, 3].insert(0, 0)
|
|
507
|
+
/// [0, 1, 2, 3]
|
|
508
|
+
///
|
|
509
|
+
/// > [1, 2, 3].insert(1, 0)
|
|
510
|
+
/// [1, 0, 2, 3]
|
|
511
|
+
///
|
|
512
|
+
/// > [1, 2, 3].insert(3, 0)
|
|
513
|
+
/// [1, 2, 3, 0]
|
|
514
|
+
///
|
|
515
|
+
/// > [1, 2, 3].insert(10, 0)
|
|
516
|
+
/// [1, 2, 3, 0]
|
|
517
|
+
/// ```
|
|
518
|
+
///
|
|
519
|
+
/// O(N)
|
|
520
520
|
def insert[A](list: List[A], index: Int, x: A): List[A] = {
|
|
521
521
|
val (left, right) = list.splitAt(index)
|
|
522
522
|
left.append(Cons(x, right))
|
|
523
523
|
}
|
|
524
524
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
525
|
+
/// Replace an element at given index in the list.
|
|
526
|
+
/// Returns the original list when the index is out of bounds.
|
|
527
|
+
///
|
|
528
|
+
/// Examples:
|
|
529
|
+
/// ```
|
|
530
|
+
/// > [1, 2, 3].replace(0, 42)
|
|
531
|
+
/// [42, 2, 3]
|
|
532
|
+
///
|
|
533
|
+
/// > [1, 2, 3].replace(-1, 42)
|
|
534
|
+
/// [1, 2, 3]
|
|
535
|
+
///
|
|
536
|
+
/// > [1, 2, 3].replace(10, 42)
|
|
537
|
+
/// [1, 2, 3]
|
|
538
|
+
/// ```
|
|
539
|
+
///
|
|
540
|
+
/// O(N)
|
|
541
541
|
def replace[A](list: List[A], index: Int, x: A): List[A] = {
|
|
542
542
|
if (index < 0 || index >= list.size()) {
|
|
543
543
|
list
|
|
@@ -548,25 +548,25 @@ def replace[A](list: List[A], index: Int, x: A): List[A] = {
|
|
|
548
548
|
}
|
|
549
549
|
}
|
|
550
550
|
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
551
|
+
/// Produce a list of pairs from a pair of lists.
|
|
552
|
+
/// The length of the result is the minimum of lengths of the two lists.
|
|
553
|
+
///
|
|
554
|
+
/// Examples:
|
|
555
|
+
/// ```
|
|
556
|
+
/// > zip([1, 2, 3], [100, 200, 300])
|
|
557
|
+
/// [(1, 100), (2, 200), (3, 300)]
|
|
558
|
+
///
|
|
559
|
+
/// > zip([1, 2, 3], Nil[Int]())
|
|
560
|
+
/// []
|
|
561
|
+
///
|
|
562
|
+
/// > zip(Nil[Int](), [1, 2, 3])
|
|
563
|
+
/// []
|
|
564
|
+
///
|
|
565
|
+
/// > zip([1, 2, 3], [42])
|
|
566
|
+
/// [(1, 42)]
|
|
567
|
+
/// ```
|
|
568
|
+
///
|
|
569
|
+
/// O(N)
|
|
570
570
|
def zip[A, B](left: List[A], right: List[B]): List[(A, B)] = {
|
|
571
571
|
def go(acc: List[(A, B)], left: List[A], right: List[B]): List[(A, B)] = {
|
|
572
572
|
(left, right) match {
|
|
@@ -580,25 +580,25 @@ def zip[A, B](left: List[A], right: List[B]): List[(A, B)] = {
|
|
|
580
580
|
go(Nil(), left, right)
|
|
581
581
|
}
|
|
582
582
|
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
583
|
+
/// Combine two lists with the given function.
|
|
584
|
+
/// The length of the result is the minimum of lengths of the two lists.
|
|
585
|
+
///
|
|
586
|
+
/// Examples:
|
|
587
|
+
/// ```
|
|
588
|
+
/// > zipWith([1, 2, 3], [100, 200, 300]) { (a, b) => a + b }
|
|
589
|
+
/// [101, 202, 303]
|
|
590
|
+
///
|
|
591
|
+
/// > zipWith([1, 2, 3], Nil[Int]()) { (a, b) => a + b }
|
|
592
|
+
/// []
|
|
593
|
+
///
|
|
594
|
+
/// > zipWith(Nil[Int](), [1, 2, 3]) { (a, b) => a + b }
|
|
595
|
+
/// []
|
|
596
|
+
///
|
|
597
|
+
/// > zipWith([1, 2, 3], [42]) { (a, b) => a + b }
|
|
598
|
+
/// [43]
|
|
599
|
+
/// ```
|
|
600
|
+
///
|
|
601
|
+
/// O(N)
|
|
602
602
|
def zipWith[A, B, C](left: List[A], right: List[B]) { combine : (A, B) => C }: List[C] = {
|
|
603
603
|
def go(acc: List[C], left: List[A], right: List[B]): List[C] = {
|
|
604
604
|
(left, right) match {
|
|
@@ -612,15 +612,15 @@ def zipWith[A, B, C](left: List[A], right: List[B]) { combine : (A, B) => C }: L
|
|
|
612
612
|
go(Nil(), left, right)
|
|
613
613
|
}
|
|
614
614
|
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
615
|
+
/// Produce a pair of lists from a list of pairs.
|
|
616
|
+
///
|
|
617
|
+
/// Examples:
|
|
618
|
+
/// ```
|
|
619
|
+
/// > [(1, 100), (2, 200), (3, 300)].unzip()
|
|
620
|
+
/// ([1, 2, 3], [100, 200, 300])
|
|
621
|
+
/// ```
|
|
622
|
+
///
|
|
623
|
+
/// O(N)
|
|
624
624
|
def unzip[A, B](pairs: List[(A, B)]): (List[A], List[B]) = {
|
|
625
625
|
pairs match {
|
|
626
626
|
case Nil() => (Nil(), Nil())
|
|
@@ -630,11 +630,11 @@ def unzip[A, B](pairs: List[(A, B)]): (List[A], List[B]) = {
|
|
|
630
630
|
}
|
|
631
631
|
}
|
|
632
632
|
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
633
|
+
/// Partition a given list into two lists.
|
|
634
|
+
/// The left list contains the elements that satsify the predicate,
|
|
635
|
+
/// the right list contains the elements that do not.
|
|
636
|
+
///
|
|
637
|
+
/// O(N)
|
|
638
638
|
def partition[A](l: List[A]) { pred: A => Bool }: (List[A], List[A]) = {
|
|
639
639
|
var lefts: List[A] = Nil()
|
|
640
640
|
var rights: List[A] = Nil()
|
|
@@ -649,11 +649,11 @@ def partition[A](l: List[A]) { pred: A => Bool }: (List[A], List[A]) = {
|
|
|
649
649
|
(lefts.reverse, rights.reverse)
|
|
650
650
|
}
|
|
651
651
|
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
652
|
+
/// Sort a list using a given comparison function.
|
|
653
|
+
///
|
|
654
|
+
/// Note: this implementation is not stacksafe!
|
|
655
|
+
///
|
|
656
|
+
/// O(N log N)
|
|
657
657
|
def sortBy[A](l: List[A]) { compare: (A, A) => Bool }: List[A] =
|
|
658
658
|
l match {
|
|
659
659
|
case Nil() => Nil()
|
|
@@ -667,9 +667,9 @@ def sortBy[A](l: List[A]) { compare: (A, A) => Bool }: List[A] =
|
|
|
667
667
|
def sort(l: List[Int]): List[Int] = l.sortBy { (a, b) => a < b }
|
|
668
668
|
def sort(l: List[Double]): List[Double] = l.sortBy { (a, b) => a < b }
|
|
669
669
|
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
670
|
+
/// Check if a list is sorted according to the given comparison function.
|
|
671
|
+
///
|
|
672
|
+
/// O(N)
|
|
673
673
|
def isSortedBy[A](list: List[A]) { compare: (A, A) => Bool }: Bool = {
|
|
674
674
|
def go(list: List[A]): Bool = {
|
|
675
675
|
list match {
|