@effekt-lang/effekt 0.3.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/README.md +6 -18
- package/bin/effekt +0 -0
- package/libraries/common/args.effekt +0 -27
- package/libraries/common/array.effekt +34 -63
- package/libraries/common/bench.effekt +40 -22
- 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 +51 -92
- package/libraries/common/exception.effekt +0 -1
- package/libraries/common/io/console.effekt +30 -36
- package/libraries/common/io/error.effekt +131 -30
- package/libraries/common/io/filesystem.effekt +262 -0
- package/libraries/common/io/network.effekt +30 -54
- package/libraries/common/io/time.effekt +9 -12
- package/libraries/common/io.effekt +54 -124
- package/libraries/common/list.effekt +345 -327
- package/libraries/common/process.effekt +0 -1
- package/libraries/common/queue.effekt +1 -3
- package/libraries/common/ref.effekt +11 -24
- package/libraries/common/result.effekt +6 -14
- package/libraries/common/seq.effekt +28 -49
- package/libraries/common/string/tty.effekt +66 -0
- package/libraries/common/string.effekt +7 -49
- package/libraries/common/test.effekt +96 -34
- package/libraries/js/unsafe/cont.effekt +1 -1
- package/libraries/llvm/io.c +258 -378
- package/libraries/llvm/main.c +3 -0
- package/libraries/llvm/rts.ll +57 -38
- package/libraries/llvm/types.c +10 -1
- package/licenses/eclipse public license, version 2.0 - epl-2.0.html +4 -4
- package/licenses/mit license - mit-license.html +21 -20
- package/licenses/the bsd license - bsd-license.html +20 -21
- package/licenses/the mit license - mit.html +22 -21
- package/package.json +1 -1
- package/libraries/chez/lift/effekt.ss +0 -118
- package/libraries/common/io/files.effekt +0 -282
- package/libraries/js/io.js +0 -143
- package/libraries/llvm/io.ll +0 -19
- package/libraries/ml/effekt.sml +0 -65
- package/libraries/ml/internal/mllist.effekt +0 -9
- package/libraries/ml/internal/mloption.effekt +0 -18
- package/libraries/ml/random.effekt +0 -85
- package/libraries/ml/text/regex.effekt +0 -102
|
@@ -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,71 +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
|
+
def foldLeft[A, B](l: List[A], init: B) { f: (B, A) => B }: B = {
|
|
229
|
+
var acc = init;
|
|
230
|
+
l.foreach { x => acc = f(acc, x) };
|
|
231
|
+
acc
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/// Fold a list using `f`, starting from the right given a starting value.
|
|
235
|
+
///
|
|
236
|
+
/// O(N)
|
|
237
|
+
def foldRight[A, B](l: List[A], init: B) { f: (A, B) => B }: B = {
|
|
238
|
+
var acc = init;
|
|
239
|
+
l.reverse.foreach { x => acc = f(x, acc) };
|
|
240
|
+
acc
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/// Sum the elements of the list.
|
|
244
|
+
///
|
|
245
|
+
/// O(N)
|
|
228
246
|
def sum(list: List[Int]): Int = {
|
|
229
247
|
var n = 0;
|
|
230
248
|
list.foreach { x => n = n + x };
|
|
231
249
|
n
|
|
232
250
|
}
|
|
233
251
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
252
|
+
/// Calculate the size of the list.
|
|
253
|
+
///
|
|
254
|
+
/// O(N)
|
|
237
255
|
def size[A](l: List[A]): Int = {
|
|
238
256
|
var n = 0;
|
|
239
257
|
l.foreach { _ => n = n + 1 };
|
|
240
258
|
n
|
|
241
259
|
}
|
|
242
260
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
261
|
+
/// Reverse the list.
|
|
262
|
+
///
|
|
263
|
+
/// O(N)
|
|
246
264
|
def reverse[A](l: List[A]): List[A] = {
|
|
247
265
|
var res = Nil[A]()
|
|
248
266
|
l.foreach { el => res = Cons(el, res) }
|
|
249
267
|
res
|
|
250
268
|
}
|
|
251
269
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
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|)
|
|
261
279
|
def reverseOnto[A](l: List[A], other: List[A]): List[A] = l match {
|
|
262
280
|
case Nil() => other
|
|
263
281
|
case Cons(a, rest) => rest.reverseOnto(Cons(a, other))
|
|
264
282
|
}
|
|
265
283
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
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)
|
|
275
293
|
def append[A](l: List[A], other: List[A]): List[A] =
|
|
276
294
|
l.reverse.reverseOnto(other)
|
|
277
295
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
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)
|
|
290
308
|
def join[A](lists: List[List[A]]): List[A] = {
|
|
291
309
|
var acc: List[A] = Nil()
|
|
292
310
|
lists.foreach { list =>
|
|
@@ -295,19 +313,19 @@ def join[A](lists: List[List[A]]): List[A] = {
|
|
|
295
313
|
acc
|
|
296
314
|
}
|
|
297
315
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
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)
|
|
311
329
|
def join[A](lists: List[List[A]], between: List[A]): List[A] = {
|
|
312
330
|
lists match {
|
|
313
331
|
case Nil() => Nil()
|
|
@@ -318,27 +336,27 @@ def join[A](lists: List[List[A]], between: List[A]): List[A] = {
|
|
|
318
336
|
}
|
|
319
337
|
}
|
|
320
338
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
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)
|
|
342
360
|
def take[A](l: List[A], n: Int): List[A] =
|
|
343
361
|
if (n <= 0) {
|
|
344
362
|
Nil()
|
|
@@ -347,27 +365,27 @@ def take[A](l: List[A], n: Int): List[A] =
|
|
|
347
365
|
case Cons(a, rest) => Cons(a, rest.take(n - 1))
|
|
348
366
|
}
|
|
349
367
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
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)
|
|
371
389
|
def drop[A](l: List[A], n: Int): List[A] =
|
|
372
390
|
if (n <= 0) {
|
|
373
391
|
l
|
|
@@ -376,57 +394,57 @@ def drop[A](l: List[A], n: Int): List[A] =
|
|
|
376
394
|
case Cons(a, rest) => rest.drop(n - 1)
|
|
377
395
|
}
|
|
378
396
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
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)
|
|
401
419
|
def slice[A](list: List[A], start: Int, stopExclusive: Int): List[A] = {
|
|
402
420
|
val prefix = list.drop(start)
|
|
403
421
|
val length = stopExclusive - start
|
|
404
422
|
prefix.take(length)
|
|
405
423
|
}
|
|
406
424
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
425
|
+
/// Split the list at given index.
|
|
426
|
+
///
|
|
427
|
+
/// Law: `val (l, r) = list.splitAt(i); l.append(r) === list`
|
|
428
|
+
///
|
|
429
|
+
/// O(N)
|
|
412
430
|
def splitAt[A](list: List[A], index: Int): (List[A], List[A]) = {
|
|
413
431
|
(list.take(index), list.drop(index))
|
|
414
432
|
}
|
|
415
433
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
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)
|
|
430
448
|
def updateAt[A](list: List[A], index: Int) { update: A => A }: List[A] = {
|
|
431
449
|
list.splitAt(index) match {
|
|
432
450
|
case (left, Cons(x, right)) =>
|
|
@@ -435,20 +453,20 @@ def updateAt[A](list: List[A], index: Int) { update: A => A }: List[A] = {
|
|
|
435
453
|
}
|
|
436
454
|
}
|
|
437
455
|
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
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)
|
|
452
470
|
def modifyAt[A](list: List[A], index: Int) { update: A => A }: List[A] / Exception[OutOfBounds] = {
|
|
453
471
|
list.splitAt(index) match {
|
|
454
472
|
case (left, Cons(x, right)) =>
|
|
@@ -457,69 +475,69 @@ def modifyAt[A](list: List[A], index: Int) { update: A => A }: List[A] / Excepti
|
|
|
457
475
|
}
|
|
458
476
|
}
|
|
459
477
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
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)
|
|
475
493
|
def deleteAt[A](list: List[A], index: Int): List[A] = {
|
|
476
494
|
val left = list.slice(0, index)
|
|
477
495
|
val right = list.slice(index + 1, list.size())
|
|
478
496
|
left.append(right)
|
|
479
497
|
}
|
|
480
498
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
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)
|
|
502
520
|
def insert[A](list: List[A], index: Int, x: A): List[A] = {
|
|
503
521
|
val (left, right) = list.splitAt(index)
|
|
504
522
|
left.append(Cons(x, right))
|
|
505
523
|
}
|
|
506
524
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
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)
|
|
523
541
|
def replace[A](list: List[A], index: Int, x: A): List[A] = {
|
|
524
542
|
if (index < 0 || index >= list.size()) {
|
|
525
543
|
list
|
|
@@ -530,25 +548,25 @@ def replace[A](list: List[A], index: Int, x: A): List[A] = {
|
|
|
530
548
|
}
|
|
531
549
|
}
|
|
532
550
|
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
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)
|
|
552
570
|
def zip[A, B](left: List[A], right: List[B]): List[(A, B)] = {
|
|
553
571
|
def go(acc: List[(A, B)], left: List[A], right: List[B]): List[(A, B)] = {
|
|
554
572
|
(left, right) match {
|
|
@@ -562,25 +580,25 @@ def zip[A, B](left: List[A], right: List[B]): List[(A, B)] = {
|
|
|
562
580
|
go(Nil(), left, right)
|
|
563
581
|
}
|
|
564
582
|
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
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)
|
|
584
602
|
def zipWith[A, B, C](left: List[A], right: List[B]) { combine : (A, B) => C }: List[C] = {
|
|
585
603
|
def go(acc: List[C], left: List[A], right: List[B]): List[C] = {
|
|
586
604
|
(left, right) match {
|
|
@@ -594,15 +612,15 @@ def zipWith[A, B, C](left: List[A], right: List[B]) { combine : (A, B) => C }: L
|
|
|
594
612
|
go(Nil(), left, right)
|
|
595
613
|
}
|
|
596
614
|
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
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)
|
|
606
624
|
def unzip[A, B](pairs: List[(A, B)]): (List[A], List[B]) = {
|
|
607
625
|
pairs match {
|
|
608
626
|
case Nil() => (Nil(), Nil())
|
|
@@ -612,11 +630,11 @@ def unzip[A, B](pairs: List[(A, B)]): (List[A], List[B]) = {
|
|
|
612
630
|
}
|
|
613
631
|
}
|
|
614
632
|
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
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)
|
|
620
638
|
def partition[A](l: List[A]) { pred: A => Bool }: (List[A], List[A]) = {
|
|
621
639
|
var lefts: List[A] = Nil()
|
|
622
640
|
var rights: List[A] = Nil()
|
|
@@ -631,11 +649,11 @@ def partition[A](l: List[A]) { pred: A => Bool }: (List[A], List[A]) = {
|
|
|
631
649
|
(lefts.reverse, rights.reverse)
|
|
632
650
|
}
|
|
633
651
|
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
652
|
+
/// Sort a list using a given comparison function.
|
|
653
|
+
///
|
|
654
|
+
/// Note: this implementation is not stacksafe!
|
|
655
|
+
///
|
|
656
|
+
/// O(N log N)
|
|
639
657
|
def sortBy[A](l: List[A]) { compare: (A, A) => Bool }: List[A] =
|
|
640
658
|
l match {
|
|
641
659
|
case Nil() => Nil()
|
|
@@ -649,9 +667,9 @@ def sortBy[A](l: List[A]) { compare: (A, A) => Bool }: List[A] =
|
|
|
649
667
|
def sort(l: List[Int]): List[Int] = l.sortBy { (a, b) => a < b }
|
|
650
668
|
def sort(l: List[Double]): List[Double] = l.sortBy { (a, b) => a < b }
|
|
651
669
|
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
670
|
+
/// Check if a list is sorted according to the given comparison function.
|
|
671
|
+
///
|
|
672
|
+
/// O(N)
|
|
655
673
|
def isSortedBy[A](list: List[A]) { compare: (A, A) => Bool }: Bool = {
|
|
656
674
|
def go(list: List[A]): Bool = {
|
|
657
675
|
list match {
|