create-mendix-widget-gleam 2.0.14 → 2.0.15
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 +1 -1
- package/package.json +5 -1
- package/src/index.mjs +22 -7
- package/template/gleam.toml +1 -1
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@command.cache +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@command.cache_inline +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@command.cache_meta +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@cursor.cache +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@cursor.cache_inline +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@cursor.cache_meta +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@event.cache +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@event.cache_inline +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@event.cache_meta +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@internal@consts.cache +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@internal@consts.cache_inline +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@internal@consts.cache_meta +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@stdout.cache +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@stdout.cache_inline +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@stdout.cache_meta +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@style.cache +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@style.cache_inline +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@style.cache_meta +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@terminal.cache +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@terminal.cache_inline +0 -0
- package/tui/build/dev/javascript/etch/_gleam_artefacts/etch@terminal.cache_meta +0 -0
- package/tui/build/dev/javascript/etch/etch/command.mjs +479 -0
- package/tui/build/dev/javascript/etch/etch/cursor.mjs +164 -0
- package/tui/build/dev/javascript/etch/etch/event.mjs +2399 -0
- package/tui/build/dev/javascript/etch/etch/internal/consts.mjs +3 -0
- package/tui/build/dev/javascript/etch/etch/stdout.mjs +375 -0
- package/tui/build/dev/javascript/etch/etch/style.mjs +741 -0
- package/tui/build/dev/javascript/etch/etch/terminal.mjs +137 -0
- package/tui/build/dev/javascript/etch/gleam.mjs +1 -0
- package/tui/build/dev/javascript/etch/input/event_ffi.erl +73 -0
- package/tui/build/dev/javascript/etch/input/input_ffi.mjs +192 -0
- package/tui/build/dev/javascript/etch/input/signal_handler.erl +33 -0
- package/tui/build/dev/javascript/etch/terminal/terminal_ffi.erl +22 -0
- package/tui/build/dev/javascript/etch/terminal/terminal_ffi.mjs +37 -0
- package/tui/build/dev/javascript/etch/terminal/tty_state.erl +29 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@application.cache +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@application.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@application.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@atom.cache +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@atom.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@atom.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@charlist.cache +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@charlist.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@charlist.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@node.cache +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@node.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@node.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@port.cache +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@port.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@port.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@process.cache +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@process.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@process.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@reference.cache +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@reference.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_erlang/_gleam_artefacts/gleam@erlang@reference.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam/erlang/application.mjs +38 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam/erlang/atom.mjs +2 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam/erlang/charlist.mjs +1 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam/erlang/node.mjs +12 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam/erlang/port.mjs +1 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam/erlang/process.mjs +161 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam/erlang/reference.mjs +1 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam.mjs +1 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam@erlang@application.erl +43 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam@erlang@atom.erl +94 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam@erlang@charlist.erl +42 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam@erlang@node.erl +80 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam@erlang@port.erl +8 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam@erlang@process.erl +868 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam@erlang@reference.erl +21 -0
- package/tui/build/dev/javascript/gleam_erlang/gleam_erlang_ffi.erl +164 -0
- package/tui/build/dev/javascript/gleam_javascript/_gleam_artefacts/gleam@javascript@array.cache +0 -0
- package/tui/build/dev/javascript/gleam_javascript/_gleam_artefacts/gleam@javascript@array.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_javascript/_gleam_artefacts/gleam@javascript@array.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_javascript/_gleam_artefacts/gleam@javascript@promise.cache +0 -0
- package/tui/build/dev/javascript/gleam_javascript/_gleam_artefacts/gleam@javascript@promise.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_javascript/_gleam_artefacts/gleam@javascript@promise.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_javascript/_gleam_artefacts/gleam@javascript@symbol.cache +0 -0
- package/tui/build/dev/javascript/gleam_javascript/_gleam_artefacts/gleam@javascript@symbol.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_javascript/_gleam_artefacts/gleam@javascript@symbol.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_javascript/gleam/javascript/array.mjs +24 -0
- package/tui/build/dev/javascript/gleam_javascript/gleam/javascript/promise.mjs +105 -0
- package/tui/build/dev/javascript/gleam_javascript/gleam/javascript/symbol.mjs +7 -0
- package/tui/build/dev/javascript/gleam_javascript/gleam.mjs +1 -0
- package/tui/build/dev/javascript/gleam_javascript/gleam_javascript_ffi.mjs +133 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bit_array.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bool.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bool.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@bytes_tree.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dict.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dict.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic@decode.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic@decode.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@dynamic@decode.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@float.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@float.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@float.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@function.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@function.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@function.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@int.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@int.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@int.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@io.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@io.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@io.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@list.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@list.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@list.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@option.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@option.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@option.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@order.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@order.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@order.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@pair.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@pair.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@result.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@result.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@result.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@set.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@set.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@set.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@string_tree.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@uri.cache +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_inline +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/_gleam_artefacts/gleam@uri.cache_meta +0 -0
- package/tui/build/dev/javascript/gleam_stdlib/dict.mjs +710 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/bit_array.mjs +286 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/bool.mjs +295 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/bytes_tree.mjs +225 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/dict.mjs +455 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/dynamic/decode.mjs +993 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/dynamic.mjs +35 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/float.mjs +528 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/function.mjs +6 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/int.mjs +764 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/io.mjs +8 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/list.mjs +3063 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/option.mjs +386 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/order.mjs +166 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/pair.mjs +96 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/result.mjs +448 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/set.mjs +413 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/string.mjs +695 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/string_tree.mjs +128 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam/uri.mjs +1151 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam.mjs +1 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@bit_array.erl +347 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@bool.erl +334 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@bytes_tree.erl +211 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@dict.erl +513 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@dynamic.erl +105 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@dynamic@decode.erl +1114 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@float.erl +711 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@function.erl +18 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@int.erl +972 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@io.erl +76 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@list.erl +2735 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@option.erl +381 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@order.erl +188 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@pair.erl +104 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@result.erl +500 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@set.erl +430 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@string.erl +964 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@string_tree.erl +202 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam@uri.erl +1042 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam_stdlib.erl +534 -0
- package/tui/build/dev/javascript/gleam_stdlib/gleam_stdlib.mjs +1133 -0
- package/tui/build/dev/javascript/gleam_version +1 -0
- package/tui/build/dev/javascript/prelude.mjs +1575 -0
- package/tui/build/dev/javascript/tui/_gleam_artefacts/tui.cache +0 -0
- package/tui/build/dev/javascript/tui/_gleam_artefacts/tui.cache_inline +0 -0
- package/tui/build/dev/javascript/tui/_gleam_artefacts/tui.cache_meta +0 -0
- package/tui/build/dev/javascript/tui/_gleam_artefacts/tui.cache_warnings +0 -0
- package/tui/build/dev/javascript/tui/_gleam_artefacts/tui@prompt.cache +0 -0
- package/tui/build/dev/javascript/tui/_gleam_artefacts/tui@prompt.cache_inline +0 -0
- package/tui/build/dev/javascript/tui/_gleam_artefacts/tui@prompt.cache_meta +0 -0
- package/tui/build/dev/javascript/tui/_gleam_artefacts/tui@prompt.cache_warnings +0 -0
- package/tui/build/dev/javascript/tui/gleam.mjs +1 -0
- package/tui/build/dev/javascript/tui/tui/prompt.mjs +521 -0
- package/tui/build/dev/javascript/tui/tui.mjs +334 -0
- package/tui/build/dev/javascript/tui/tui_ffi.mjs +32 -0
|
@@ -0,0 +1,3063 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Ok,
|
|
3
|
+
Error,
|
|
4
|
+
toList,
|
|
5
|
+
Empty as $Empty,
|
|
6
|
+
prepend as listPrepend,
|
|
7
|
+
CustomType as $CustomType,
|
|
8
|
+
makeError,
|
|
9
|
+
divideFloat,
|
|
10
|
+
isEqual,
|
|
11
|
+
} from "../gleam.mjs";
|
|
12
|
+
import * as $dict from "../gleam/dict.mjs";
|
|
13
|
+
import * as $float from "../gleam/float.mjs";
|
|
14
|
+
import * as $int from "../gleam/int.mjs";
|
|
15
|
+
import * as $order from "../gleam/order.mjs";
|
|
16
|
+
|
|
17
|
+
const FILEPATH = "src\\gleam\\list.gleam";
|
|
18
|
+
|
|
19
|
+
export class Continue extends $CustomType {
|
|
20
|
+
constructor($0) {
|
|
21
|
+
super();
|
|
22
|
+
this[0] = $0;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export const ContinueOrStop$Continue = ($0) => new Continue($0);
|
|
26
|
+
export const ContinueOrStop$isContinue = (value) => value instanceof Continue;
|
|
27
|
+
export const ContinueOrStop$Continue$0 = (value) => value[0];
|
|
28
|
+
|
|
29
|
+
export class Stop extends $CustomType {
|
|
30
|
+
constructor($0) {
|
|
31
|
+
super();
|
|
32
|
+
this[0] = $0;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export const ContinueOrStop$Stop = ($0) => new Stop($0);
|
|
36
|
+
export const ContinueOrStop$isStop = (value) => value instanceof Stop;
|
|
37
|
+
export const ContinueOrStop$Stop$0 = (value) => value[0];
|
|
38
|
+
|
|
39
|
+
class Ascending extends $CustomType {}
|
|
40
|
+
|
|
41
|
+
class Descending extends $CustomType {}
|
|
42
|
+
|
|
43
|
+
const min_positive = 2.2250738585072014e-308;
|
|
44
|
+
|
|
45
|
+
function length_loop(loop$list, loop$count) {
|
|
46
|
+
while (true) {
|
|
47
|
+
let list = loop$list;
|
|
48
|
+
let count = loop$count;
|
|
49
|
+
if (list instanceof $Empty) {
|
|
50
|
+
return count;
|
|
51
|
+
} else {
|
|
52
|
+
let list$1 = list.tail;
|
|
53
|
+
loop$list = list$1;
|
|
54
|
+
loop$count = count + 1;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Counts the number of elements in a given list.
|
|
61
|
+
*
|
|
62
|
+
* This function has to traverse the list to determine the number of elements,
|
|
63
|
+
* so it runs in linear time.
|
|
64
|
+
*
|
|
65
|
+
* This function is natively implemented by the virtual machine and is highly
|
|
66
|
+
* optimised.
|
|
67
|
+
*
|
|
68
|
+
* ## Examples
|
|
69
|
+
*
|
|
70
|
+
* ```gleam
|
|
71
|
+
* assert length([]) == 0
|
|
72
|
+
* ```
|
|
73
|
+
*
|
|
74
|
+
* ```gleam
|
|
75
|
+
* assert length([1]) == 1
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
* ```gleam
|
|
79
|
+
* assert length([1, 2]) == 2
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
export function length(list) {
|
|
83
|
+
return length_loop(list, 0);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function count_loop(loop$list, loop$predicate, loop$acc) {
|
|
87
|
+
while (true) {
|
|
88
|
+
let list = loop$list;
|
|
89
|
+
let predicate = loop$predicate;
|
|
90
|
+
let acc = loop$acc;
|
|
91
|
+
if (list instanceof $Empty) {
|
|
92
|
+
return acc;
|
|
93
|
+
} else {
|
|
94
|
+
let first$1 = list.head;
|
|
95
|
+
let rest$1 = list.tail;
|
|
96
|
+
let $ = predicate(first$1);
|
|
97
|
+
if ($) {
|
|
98
|
+
loop$list = rest$1;
|
|
99
|
+
loop$predicate = predicate;
|
|
100
|
+
loop$acc = acc + 1;
|
|
101
|
+
} else {
|
|
102
|
+
loop$list = rest$1;
|
|
103
|
+
loop$predicate = predicate;
|
|
104
|
+
loop$acc = acc;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Counts the number of elements in a given list satisfying a given predicate.
|
|
112
|
+
*
|
|
113
|
+
* This function has to traverse the list to determine the number of elements,
|
|
114
|
+
* so it runs in linear time.
|
|
115
|
+
*
|
|
116
|
+
* ## Examples
|
|
117
|
+
*
|
|
118
|
+
* ```gleam
|
|
119
|
+
* assert count([], fn(a) { a > 0 }) == 0
|
|
120
|
+
* ```
|
|
121
|
+
*
|
|
122
|
+
* ```gleam
|
|
123
|
+
* assert count([1], fn(a) { a > 0 }) == 1
|
|
124
|
+
* ```
|
|
125
|
+
*
|
|
126
|
+
* ```gleam
|
|
127
|
+
* assert count([1, 2, 3], int.is_odd) == 2
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
export function count(list, predicate) {
|
|
131
|
+
return count_loop(list, predicate, 0);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Reverses a list and prepends it to another list.
|
|
136
|
+
* This function runs in linear time, proportional to the length of the list
|
|
137
|
+
* to prepend.
|
|
138
|
+
*
|
|
139
|
+
* @ignore
|
|
140
|
+
*/
|
|
141
|
+
function reverse_and_prepend(loop$prefix, loop$suffix) {
|
|
142
|
+
while (true) {
|
|
143
|
+
let prefix = loop$prefix;
|
|
144
|
+
let suffix = loop$suffix;
|
|
145
|
+
if (prefix instanceof $Empty) {
|
|
146
|
+
return suffix;
|
|
147
|
+
} else {
|
|
148
|
+
let first$1 = prefix.head;
|
|
149
|
+
let rest$1 = prefix.tail;
|
|
150
|
+
loop$prefix = rest$1;
|
|
151
|
+
loop$suffix = listPrepend(first$1, suffix);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Creates a new list from a given list containing the same elements but in the
|
|
158
|
+
* opposite order.
|
|
159
|
+
*
|
|
160
|
+
* This function has to traverse the list to create the new reversed list, so
|
|
161
|
+
* it runs in linear time.
|
|
162
|
+
*
|
|
163
|
+
* This function is natively implemented by the virtual machine and is highly
|
|
164
|
+
* optimised.
|
|
165
|
+
*
|
|
166
|
+
* ## Examples
|
|
167
|
+
*
|
|
168
|
+
* ```gleam
|
|
169
|
+
* assert reverse([]) == []
|
|
170
|
+
* ```
|
|
171
|
+
*
|
|
172
|
+
* ```gleam
|
|
173
|
+
* assert reverse([1]) == [1]
|
|
174
|
+
* ```
|
|
175
|
+
*
|
|
176
|
+
* ```gleam
|
|
177
|
+
* assert reverse([1, 2]) == [2, 1]
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
export function reverse(list) {
|
|
181
|
+
return reverse_and_prepend(list, toList([]));
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Determines whether or not the list is empty.
|
|
186
|
+
*
|
|
187
|
+
* This function runs in constant time.
|
|
188
|
+
*
|
|
189
|
+
* ## Examples
|
|
190
|
+
*
|
|
191
|
+
* ```gleam
|
|
192
|
+
* assert is_empty([])
|
|
193
|
+
* ```
|
|
194
|
+
*
|
|
195
|
+
* ```gleam
|
|
196
|
+
* assert !is_empty([1])
|
|
197
|
+
* ```
|
|
198
|
+
*
|
|
199
|
+
* ```gleam
|
|
200
|
+
* assert !is_empty([1, 1])
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
203
|
+
export function is_empty(list) {
|
|
204
|
+
return isEqual(list, toList([]));
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Determines whether or not a given element exists within a given list.
|
|
209
|
+
*
|
|
210
|
+
* This function traverses the list to find the element, so it runs in linear
|
|
211
|
+
* time.
|
|
212
|
+
*
|
|
213
|
+
* ## Examples
|
|
214
|
+
*
|
|
215
|
+
* ```gleam
|
|
216
|
+
* assert !contains([], any: 0)
|
|
217
|
+
* ```
|
|
218
|
+
*
|
|
219
|
+
* ```gleam
|
|
220
|
+
* assert [0] |> contains(any: 0)
|
|
221
|
+
* ```
|
|
222
|
+
*
|
|
223
|
+
* ```gleam
|
|
224
|
+
* assert !contains([1], any: 0)
|
|
225
|
+
* ```
|
|
226
|
+
*
|
|
227
|
+
* ```gleam
|
|
228
|
+
* assert !contains([1, 1], any: 0)
|
|
229
|
+
* ```
|
|
230
|
+
*
|
|
231
|
+
* ```gleam
|
|
232
|
+
* assert [1, 0] |> contains(any: 0)
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
export function contains(loop$list, loop$elem) {
|
|
236
|
+
while (true) {
|
|
237
|
+
let list = loop$list;
|
|
238
|
+
let elem = loop$elem;
|
|
239
|
+
if (list instanceof $Empty) {
|
|
240
|
+
return false;
|
|
241
|
+
} else {
|
|
242
|
+
let first$1 = list.head;
|
|
243
|
+
if (isEqual(first$1, elem)) {
|
|
244
|
+
return true;
|
|
245
|
+
} else {
|
|
246
|
+
let rest$1 = list.tail;
|
|
247
|
+
loop$list = rest$1;
|
|
248
|
+
loop$elem = elem;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Gets the first element from the start of the list, if there is one.
|
|
256
|
+
*
|
|
257
|
+
* ## Examples
|
|
258
|
+
*
|
|
259
|
+
* ```gleam
|
|
260
|
+
* assert first([]) == Error(Nil)
|
|
261
|
+
* ```
|
|
262
|
+
*
|
|
263
|
+
* ```gleam
|
|
264
|
+
* assert first([0]) == Ok(0)
|
|
265
|
+
* ```
|
|
266
|
+
*
|
|
267
|
+
* ```gleam
|
|
268
|
+
* assert first([1, 2]) == Ok(1)
|
|
269
|
+
* ```
|
|
270
|
+
*/
|
|
271
|
+
export function first(list) {
|
|
272
|
+
if (list instanceof $Empty) {
|
|
273
|
+
return new Error(undefined);
|
|
274
|
+
} else {
|
|
275
|
+
let first$1 = list.head;
|
|
276
|
+
return new Ok(first$1);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Returns the list minus the first element. If the list is empty, `Error(Nil)` is
|
|
282
|
+
* returned.
|
|
283
|
+
*
|
|
284
|
+
* This function runs in constant time and does not make a copy of the list.
|
|
285
|
+
*
|
|
286
|
+
* ## Examples
|
|
287
|
+
*
|
|
288
|
+
* ```gleam
|
|
289
|
+
* assert rest([]) == Error(Nil)
|
|
290
|
+
* ```
|
|
291
|
+
*
|
|
292
|
+
* ```gleam
|
|
293
|
+
* assert rest([0]) == Ok([])
|
|
294
|
+
* ```
|
|
295
|
+
*
|
|
296
|
+
* ```gleam
|
|
297
|
+
* assert rest([1, 2]) == Ok([2])
|
|
298
|
+
* ```
|
|
299
|
+
*/
|
|
300
|
+
export function rest(list) {
|
|
301
|
+
if (list instanceof $Empty) {
|
|
302
|
+
return new Error(undefined);
|
|
303
|
+
} else {
|
|
304
|
+
let rest$1 = list.tail;
|
|
305
|
+
return new Ok(rest$1);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Groups the elements from the given list by the given key function.
|
|
311
|
+
*
|
|
312
|
+
* Does not preserve the initial value order.
|
|
313
|
+
*
|
|
314
|
+
* ## Examples
|
|
315
|
+
*
|
|
316
|
+
* ```gleam
|
|
317
|
+
* import gleam/dict
|
|
318
|
+
*
|
|
319
|
+
* assert
|
|
320
|
+
* [Ok(3), Error("Wrong"), Ok(200), Ok(73)]
|
|
321
|
+
* |> group(by: fn(i) {
|
|
322
|
+
* case i {
|
|
323
|
+
* Ok(_) -> "Successful"
|
|
324
|
+
* Error(_) -> "Failed"
|
|
325
|
+
* }
|
|
326
|
+
* })
|
|
327
|
+
* |> dict.to_list
|
|
328
|
+
* == [
|
|
329
|
+
* #("Failed", [Error("Wrong")]),
|
|
330
|
+
* #("Successful", [Ok(73), Ok(200), Ok(3)])
|
|
331
|
+
* ]
|
|
332
|
+
* ```
|
|
333
|
+
*
|
|
334
|
+
* ```gleam
|
|
335
|
+
* import gleam/dict
|
|
336
|
+
*
|
|
337
|
+
* assert group([1,2,3,4,5], by: fn(i) { i - i / 3 * 3 })
|
|
338
|
+
* |> dict.to_list
|
|
339
|
+
* == [#(0, [3]), #(1, [4, 1]), #(2, [5, 2])]
|
|
340
|
+
* ```
|
|
341
|
+
*/
|
|
342
|
+
export function group(list, key) {
|
|
343
|
+
return $dict.group(key, list);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function filter_loop(loop$list, loop$fun, loop$acc) {
|
|
347
|
+
while (true) {
|
|
348
|
+
let list = loop$list;
|
|
349
|
+
let fun = loop$fun;
|
|
350
|
+
let acc = loop$acc;
|
|
351
|
+
if (list instanceof $Empty) {
|
|
352
|
+
return reverse(acc);
|
|
353
|
+
} else {
|
|
354
|
+
let first$1 = list.head;
|
|
355
|
+
let rest$1 = list.tail;
|
|
356
|
+
let _block;
|
|
357
|
+
let $ = fun(first$1);
|
|
358
|
+
if ($) {
|
|
359
|
+
_block = listPrepend(first$1, acc);
|
|
360
|
+
} else {
|
|
361
|
+
_block = acc;
|
|
362
|
+
}
|
|
363
|
+
let new_acc = _block;
|
|
364
|
+
loop$list = rest$1;
|
|
365
|
+
loop$fun = fun;
|
|
366
|
+
loop$acc = new_acc;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Returns a new list containing only the elements from the first list for
|
|
373
|
+
* which the given functions returns `True`.
|
|
374
|
+
*
|
|
375
|
+
* ## Examples
|
|
376
|
+
*
|
|
377
|
+
* ```gleam
|
|
378
|
+
* assert filter([2, 4, 6, 1], fn(x) { x > 2 }) == [4, 6]
|
|
379
|
+
* ```
|
|
380
|
+
*
|
|
381
|
+
* ```gleam
|
|
382
|
+
* assert filter([2, 4, 6, 1], fn(x) { x > 6 }) == []
|
|
383
|
+
* ```
|
|
384
|
+
*/
|
|
385
|
+
export function filter(list, predicate) {
|
|
386
|
+
return filter_loop(list, predicate, toList([]));
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
function filter_map_loop(loop$list, loop$fun, loop$acc) {
|
|
390
|
+
while (true) {
|
|
391
|
+
let list = loop$list;
|
|
392
|
+
let fun = loop$fun;
|
|
393
|
+
let acc = loop$acc;
|
|
394
|
+
if (list instanceof $Empty) {
|
|
395
|
+
return reverse(acc);
|
|
396
|
+
} else {
|
|
397
|
+
let first$1 = list.head;
|
|
398
|
+
let rest$1 = list.tail;
|
|
399
|
+
let _block;
|
|
400
|
+
let $ = fun(first$1);
|
|
401
|
+
if ($ instanceof Ok) {
|
|
402
|
+
let first$2 = $[0];
|
|
403
|
+
_block = listPrepend(first$2, acc);
|
|
404
|
+
} else {
|
|
405
|
+
_block = acc;
|
|
406
|
+
}
|
|
407
|
+
let new_acc = _block;
|
|
408
|
+
loop$list = rest$1;
|
|
409
|
+
loop$fun = fun;
|
|
410
|
+
loop$acc = new_acc;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Returns a new list containing only the elements from the first list for
|
|
417
|
+
* which the given functions returns `Ok(_)`.
|
|
418
|
+
*
|
|
419
|
+
* ## Examples
|
|
420
|
+
*
|
|
421
|
+
* ```gleam
|
|
422
|
+
* assert filter_map([2, 4, 6, 1], Error) == []
|
|
423
|
+
* ```
|
|
424
|
+
*
|
|
425
|
+
* ```gleam
|
|
426
|
+
* assert filter_map([2, 4, 6, 1], fn(x) { Ok(x + 1) }) == [3, 5, 7, 2]
|
|
427
|
+
* ```
|
|
428
|
+
*/
|
|
429
|
+
export function filter_map(list, fun) {
|
|
430
|
+
return filter_map_loop(list, fun, toList([]));
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
function map_loop(loop$list, loop$fun, loop$acc) {
|
|
434
|
+
while (true) {
|
|
435
|
+
let list = loop$list;
|
|
436
|
+
let fun = loop$fun;
|
|
437
|
+
let acc = loop$acc;
|
|
438
|
+
if (list instanceof $Empty) {
|
|
439
|
+
return reverse(acc);
|
|
440
|
+
} else {
|
|
441
|
+
let first$1 = list.head;
|
|
442
|
+
let rest$1 = list.tail;
|
|
443
|
+
loop$list = rest$1;
|
|
444
|
+
loop$fun = fun;
|
|
445
|
+
loop$acc = listPrepend(fun(first$1), acc);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Returns a new list containing the results of applying the supplied function to each element.
|
|
452
|
+
*
|
|
453
|
+
* ## Examples
|
|
454
|
+
*
|
|
455
|
+
* ```gleam
|
|
456
|
+
* assert map([2, 4, 6], fn(x) { x * 2 }) == [4, 8, 12]
|
|
457
|
+
* ```
|
|
458
|
+
*/
|
|
459
|
+
export function map(list, fun) {
|
|
460
|
+
return map_loop(list, fun, toList([]));
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
function map2_loop(loop$list1, loop$list2, loop$fun, loop$acc) {
|
|
464
|
+
while (true) {
|
|
465
|
+
let list1 = loop$list1;
|
|
466
|
+
let list2 = loop$list2;
|
|
467
|
+
let fun = loop$fun;
|
|
468
|
+
let acc = loop$acc;
|
|
469
|
+
if (list1 instanceof $Empty) {
|
|
470
|
+
return reverse(acc);
|
|
471
|
+
} else if (list2 instanceof $Empty) {
|
|
472
|
+
return reverse(acc);
|
|
473
|
+
} else {
|
|
474
|
+
let a = list1.head;
|
|
475
|
+
let as_ = list1.tail;
|
|
476
|
+
let b = list2.head;
|
|
477
|
+
let bs = list2.tail;
|
|
478
|
+
loop$list1 = as_;
|
|
479
|
+
loop$list2 = bs;
|
|
480
|
+
loop$fun = fun;
|
|
481
|
+
loop$acc = listPrepend(fun(a, b), acc);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Combines two lists into a single list using the given function.
|
|
488
|
+
*
|
|
489
|
+
* If a list is longer than the other, the extra elements are dropped.
|
|
490
|
+
*
|
|
491
|
+
* ## Examples
|
|
492
|
+
*
|
|
493
|
+
* ```gleam
|
|
494
|
+
* assert map2([1, 2, 3], [4, 5, 6], fn(x, y) { x + y }) == [5, 7, 9]
|
|
495
|
+
* ```
|
|
496
|
+
*
|
|
497
|
+
* ```gleam
|
|
498
|
+
* assert map2([1, 2], ["a", "b", "c"], fn(i, x) { #(i, x) })
|
|
499
|
+
* == [#(1, "a"), #(2, "b")]
|
|
500
|
+
* ```
|
|
501
|
+
*/
|
|
502
|
+
export function map2(list1, list2, fun) {
|
|
503
|
+
return map2_loop(list1, list2, fun, toList([]));
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
function map_fold_loop(loop$list, loop$fun, loop$acc, loop$list_acc) {
|
|
507
|
+
while (true) {
|
|
508
|
+
let list = loop$list;
|
|
509
|
+
let fun = loop$fun;
|
|
510
|
+
let acc = loop$acc;
|
|
511
|
+
let list_acc = loop$list_acc;
|
|
512
|
+
if (list instanceof $Empty) {
|
|
513
|
+
return [acc, reverse(list_acc)];
|
|
514
|
+
} else {
|
|
515
|
+
let first$1 = list.head;
|
|
516
|
+
let rest$1 = list.tail;
|
|
517
|
+
let $ = fun(acc, first$1);
|
|
518
|
+
let acc$1;
|
|
519
|
+
let first$2;
|
|
520
|
+
acc$1 = $[0];
|
|
521
|
+
first$2 = $[1];
|
|
522
|
+
loop$list = rest$1;
|
|
523
|
+
loop$fun = fun;
|
|
524
|
+
loop$acc = acc$1;
|
|
525
|
+
loop$list_acc = listPrepend(first$2, list_acc);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* Similar to `map` but also lets you pass around an accumulated value.
|
|
532
|
+
*
|
|
533
|
+
* ## Examples
|
|
534
|
+
*
|
|
535
|
+
* ```gleam
|
|
536
|
+
* assert
|
|
537
|
+
* map_fold(
|
|
538
|
+
* over: [1, 2, 3],
|
|
539
|
+
* from: 100,
|
|
540
|
+
* with: fn(memo, i) { #(memo + i, i * 2) }
|
|
541
|
+
* )
|
|
542
|
+
* == #(106, [2, 4, 6])
|
|
543
|
+
* ```
|
|
544
|
+
*/
|
|
545
|
+
export function map_fold(list, initial, fun) {
|
|
546
|
+
return map_fold_loop(list, fun, initial, toList([]));
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
function index_map_loop(loop$list, loop$fun, loop$index, loop$acc) {
|
|
550
|
+
while (true) {
|
|
551
|
+
let list = loop$list;
|
|
552
|
+
let fun = loop$fun;
|
|
553
|
+
let index = loop$index;
|
|
554
|
+
let acc = loop$acc;
|
|
555
|
+
if (list instanceof $Empty) {
|
|
556
|
+
return reverse(acc);
|
|
557
|
+
} else {
|
|
558
|
+
let first$1 = list.head;
|
|
559
|
+
let rest$1 = list.tail;
|
|
560
|
+
let acc$1 = listPrepend(fun(first$1, index), acc);
|
|
561
|
+
loop$list = rest$1;
|
|
562
|
+
loop$fun = fun;
|
|
563
|
+
loop$index = index + 1;
|
|
564
|
+
loop$acc = acc$1;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* Similar to `map`, but the supplied function will also be passed the index
|
|
571
|
+
* of the element being mapped as an additional argument.
|
|
572
|
+
*
|
|
573
|
+
* The index starts at 0, so the first element is 0, the second is 1, and so
|
|
574
|
+
* on.
|
|
575
|
+
*
|
|
576
|
+
* ## Examples
|
|
577
|
+
*
|
|
578
|
+
* ```gleam
|
|
579
|
+
* assert index_map(["a", "b"], fn(x, i) { #(i, x) }) == [#(0, "a"), #(1, "b")]
|
|
580
|
+
* ```
|
|
581
|
+
*/
|
|
582
|
+
export function index_map(list, fun) {
|
|
583
|
+
return index_map_loop(list, fun, 0, toList([]));
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
function try_map_loop(loop$list, loop$fun, loop$acc) {
|
|
587
|
+
while (true) {
|
|
588
|
+
let list = loop$list;
|
|
589
|
+
let fun = loop$fun;
|
|
590
|
+
let acc = loop$acc;
|
|
591
|
+
if (list instanceof $Empty) {
|
|
592
|
+
return new Ok(reverse(acc));
|
|
593
|
+
} else {
|
|
594
|
+
let first$1 = list.head;
|
|
595
|
+
let rest$1 = list.tail;
|
|
596
|
+
let $ = fun(first$1);
|
|
597
|
+
if ($ instanceof Ok) {
|
|
598
|
+
let first$2 = $[0];
|
|
599
|
+
loop$list = rest$1;
|
|
600
|
+
loop$fun = fun;
|
|
601
|
+
loop$acc = listPrepend(first$2, acc);
|
|
602
|
+
} else {
|
|
603
|
+
return $;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* Takes a function that returns a `Result` and applies it to each element in a
|
|
611
|
+
* given list in turn.
|
|
612
|
+
*
|
|
613
|
+
* If the function returns `Ok(new_value)` for all elements in the list then a
|
|
614
|
+
* list of the new values is returned.
|
|
615
|
+
*
|
|
616
|
+
* If the function returns `Error(reason)` for any of the elements then it is
|
|
617
|
+
* returned immediately. None of the elements in the list are processed after
|
|
618
|
+
* one returns an `Error`.
|
|
619
|
+
*
|
|
620
|
+
* ## Examples
|
|
621
|
+
*
|
|
622
|
+
* ```gleam
|
|
623
|
+
* assert try_map([1, 2, 3], fn(x) { Ok(x + 2) }) == Ok([3, 4, 5])
|
|
624
|
+
* ```
|
|
625
|
+
*
|
|
626
|
+
* ```gleam
|
|
627
|
+
* assert try_map([1, 2, 3], fn(_) { Error(0) }) == Error(0)
|
|
628
|
+
* ```
|
|
629
|
+
*
|
|
630
|
+
* ```gleam
|
|
631
|
+
* assert try_map([[1], [2, 3]], first) == Ok([1, 2])
|
|
632
|
+
* ```
|
|
633
|
+
*
|
|
634
|
+
* ```gleam
|
|
635
|
+
* assert try_map([[1], [], [2]], first) == Error(Nil)
|
|
636
|
+
* ```
|
|
637
|
+
*/
|
|
638
|
+
export function try_map(list, fun) {
|
|
639
|
+
return try_map_loop(list, fun, toList([]));
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* Returns a list that is the given list with up to the given number of
|
|
644
|
+
* elements removed from the front of the list.
|
|
645
|
+
*
|
|
646
|
+
* If the list has less than the number of elements an empty list is
|
|
647
|
+
* returned.
|
|
648
|
+
*
|
|
649
|
+
* This function runs in linear time but does not copy the list.
|
|
650
|
+
*
|
|
651
|
+
* ## Examples
|
|
652
|
+
*
|
|
653
|
+
* ```gleam
|
|
654
|
+
* assert drop([1, 2, 3, 4], 2) == [3, 4]
|
|
655
|
+
* ```
|
|
656
|
+
*
|
|
657
|
+
* ```gleam
|
|
658
|
+
* assert drop([1, 2, 3, 4], 9) == []
|
|
659
|
+
* ```
|
|
660
|
+
*/
|
|
661
|
+
export function drop(loop$list, loop$n) {
|
|
662
|
+
while (true) {
|
|
663
|
+
let list = loop$list;
|
|
664
|
+
let n = loop$n;
|
|
665
|
+
let $ = n <= 0;
|
|
666
|
+
if ($) {
|
|
667
|
+
return list;
|
|
668
|
+
} else {
|
|
669
|
+
if (list instanceof $Empty) {
|
|
670
|
+
return list;
|
|
671
|
+
} else {
|
|
672
|
+
let rest$1 = list.tail;
|
|
673
|
+
loop$list = rest$1;
|
|
674
|
+
loop$n = n - 1;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
function take_loop(loop$list, loop$n, loop$acc) {
|
|
681
|
+
while (true) {
|
|
682
|
+
let list = loop$list;
|
|
683
|
+
let n = loop$n;
|
|
684
|
+
let acc = loop$acc;
|
|
685
|
+
let $ = n <= 0;
|
|
686
|
+
if ($) {
|
|
687
|
+
return reverse(acc);
|
|
688
|
+
} else {
|
|
689
|
+
if (list instanceof $Empty) {
|
|
690
|
+
return reverse(acc);
|
|
691
|
+
} else {
|
|
692
|
+
let first$1 = list.head;
|
|
693
|
+
let rest$1 = list.tail;
|
|
694
|
+
loop$list = rest$1;
|
|
695
|
+
loop$n = n - 1;
|
|
696
|
+
loop$acc = listPrepend(first$1, acc);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
/**
|
|
703
|
+
* Returns a list containing the first given number of elements from the given
|
|
704
|
+
* list.
|
|
705
|
+
*
|
|
706
|
+
* If the list has less than the number of elements then the full list is
|
|
707
|
+
* returned.
|
|
708
|
+
*
|
|
709
|
+
* This function runs in linear time.
|
|
710
|
+
*
|
|
711
|
+
* ## Examples
|
|
712
|
+
*
|
|
713
|
+
* ```gleam
|
|
714
|
+
* assert take([1, 2, 3, 4], 2) == [1, 2]
|
|
715
|
+
* ```
|
|
716
|
+
*
|
|
717
|
+
* ```gleam
|
|
718
|
+
* assert take([1, 2, 3, 4], 9) == [1, 2, 3, 4]
|
|
719
|
+
* ```
|
|
720
|
+
*/
|
|
721
|
+
export function take(list, n) {
|
|
722
|
+
return take_loop(list, n, toList([]));
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
/**
|
|
726
|
+
* Returns a new empty list.
|
|
727
|
+
*
|
|
728
|
+
* ## Examples
|
|
729
|
+
*
|
|
730
|
+
* ```gleam
|
|
731
|
+
* assert new() == []
|
|
732
|
+
* ```
|
|
733
|
+
*/
|
|
734
|
+
export function new$() {
|
|
735
|
+
return toList([]);
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
/**
|
|
739
|
+
* Returns the given item wrapped in a list.
|
|
740
|
+
*
|
|
741
|
+
* ## Examples
|
|
742
|
+
*
|
|
743
|
+
* ```gleam
|
|
744
|
+
* assert wrap(1) == [1]
|
|
745
|
+
* ```
|
|
746
|
+
*
|
|
747
|
+
* ```gleam
|
|
748
|
+
* assert wrap(["a", "b", "c"]) == [["a", "b", "c"]]
|
|
749
|
+
* ```
|
|
750
|
+
*
|
|
751
|
+
* ```gleam
|
|
752
|
+
* assert wrap([[]]) == [[[]]]
|
|
753
|
+
* ```
|
|
754
|
+
*/
|
|
755
|
+
export function wrap(item) {
|
|
756
|
+
return toList([item]);
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
function append_loop(loop$first, loop$second) {
|
|
760
|
+
while (true) {
|
|
761
|
+
let first = loop$first;
|
|
762
|
+
let second = loop$second;
|
|
763
|
+
if (first instanceof $Empty) {
|
|
764
|
+
return second;
|
|
765
|
+
} else {
|
|
766
|
+
let first$1 = first.head;
|
|
767
|
+
let rest$1 = first.tail;
|
|
768
|
+
loop$first = rest$1;
|
|
769
|
+
loop$second = listPrepend(first$1, second);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
/**
|
|
775
|
+
* Joins one list onto the end of another.
|
|
776
|
+
*
|
|
777
|
+
* This function runs in linear time, and it traverses and copies the first
|
|
778
|
+
* list.
|
|
779
|
+
*
|
|
780
|
+
* ## Examples
|
|
781
|
+
*
|
|
782
|
+
* ```gleam
|
|
783
|
+
* assert append([1, 2], [3]) == [1, 2, 3]
|
|
784
|
+
* ```
|
|
785
|
+
*/
|
|
786
|
+
export function append(first, second) {
|
|
787
|
+
return append_loop(reverse(first), second);
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
/**
|
|
791
|
+
* Prefixes an item to a list. This can also be done using the dedicated
|
|
792
|
+
* syntax instead.
|
|
793
|
+
*
|
|
794
|
+
* ```gleam
|
|
795
|
+
* let existing_list = [2, 3, 4]
|
|
796
|
+
* assert [1, ..existing_list] == [1, 2, 3, 4]
|
|
797
|
+
* ```
|
|
798
|
+
*
|
|
799
|
+
* ```gleam
|
|
800
|
+
* let existing_list = [2, 3, 4]
|
|
801
|
+
* assert prepend(to: existing_list, this: 1) == [1, 2, 3, 4]
|
|
802
|
+
* ```
|
|
803
|
+
*/
|
|
804
|
+
export function prepend(list, item) {
|
|
805
|
+
return listPrepend(item, list);
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
function flatten_loop(loop$lists, loop$acc) {
|
|
809
|
+
while (true) {
|
|
810
|
+
let lists = loop$lists;
|
|
811
|
+
let acc = loop$acc;
|
|
812
|
+
if (lists instanceof $Empty) {
|
|
813
|
+
return reverse(acc);
|
|
814
|
+
} else {
|
|
815
|
+
let list = lists.head;
|
|
816
|
+
let further_lists = lists.tail;
|
|
817
|
+
loop$lists = further_lists;
|
|
818
|
+
loop$acc = reverse_and_prepend(list, acc);
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
/**
|
|
824
|
+
* Joins a list of lists into a single list.
|
|
825
|
+
*
|
|
826
|
+
* This function traverses all elements twice on the JavaScript target.
|
|
827
|
+
* This function traverses all elements once on the Erlang target.
|
|
828
|
+
*
|
|
829
|
+
* ## Examples
|
|
830
|
+
*
|
|
831
|
+
* ```gleam
|
|
832
|
+
* assert flatten([[1], [2, 3], []]) == [1, 2, 3]
|
|
833
|
+
* ```
|
|
834
|
+
*/
|
|
835
|
+
export function flatten(lists) {
|
|
836
|
+
return flatten_loop(lists, toList([]));
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
/**
|
|
840
|
+
* Maps the list with the given function into a list of lists, and then flattens it.
|
|
841
|
+
*
|
|
842
|
+
* ## Examples
|
|
843
|
+
*
|
|
844
|
+
* ```gleam
|
|
845
|
+
* assert flat_map([2, 4, 6], fn(x) { [x, x + 1] }) == [2, 3, 4, 5, 6, 7]
|
|
846
|
+
* ```
|
|
847
|
+
*/
|
|
848
|
+
export function flat_map(list, fun) {
|
|
849
|
+
return flatten(map(list, fun));
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
/**
|
|
853
|
+
* Reduces a list of elements into a single value by calling a given function
|
|
854
|
+
* on each element, going from left to right.
|
|
855
|
+
*
|
|
856
|
+
* `fold([1, 2, 3], 0, add)` is the equivalent of
|
|
857
|
+
* `add(add(add(0, 1), 2), 3)`.
|
|
858
|
+
*
|
|
859
|
+
* This function runs in linear time.
|
|
860
|
+
*/
|
|
861
|
+
export function fold(loop$list, loop$initial, loop$fun) {
|
|
862
|
+
while (true) {
|
|
863
|
+
let list = loop$list;
|
|
864
|
+
let initial = loop$initial;
|
|
865
|
+
let fun = loop$fun;
|
|
866
|
+
if (list instanceof $Empty) {
|
|
867
|
+
return initial;
|
|
868
|
+
} else {
|
|
869
|
+
let first$1 = list.head;
|
|
870
|
+
let rest$1 = list.tail;
|
|
871
|
+
loop$list = rest$1;
|
|
872
|
+
loop$initial = fun(initial, first$1);
|
|
873
|
+
loop$fun = fun;
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
/**
|
|
879
|
+
* Reduces a list of elements into a single value by calling a given function
|
|
880
|
+
* on each element, going from right to left.
|
|
881
|
+
*
|
|
882
|
+
* `fold_right([1, 2, 3], 0, add)` is the equivalent of
|
|
883
|
+
* `add(add(add(0, 3), 2), 1)`.
|
|
884
|
+
*
|
|
885
|
+
* This function runs in linear time.
|
|
886
|
+
*
|
|
887
|
+
* Unlike `fold` this function is not tail recursive. Where possible use
|
|
888
|
+
* `fold` instead as it will use less memory.
|
|
889
|
+
*/
|
|
890
|
+
export function fold_right(list, initial, fun) {
|
|
891
|
+
if (list instanceof $Empty) {
|
|
892
|
+
return initial;
|
|
893
|
+
} else {
|
|
894
|
+
let first$1 = list.head;
|
|
895
|
+
let rest$1 = list.tail;
|
|
896
|
+
return fun(fold_right(rest$1, initial, fun), first$1);
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
function index_fold_loop(loop$over, loop$acc, loop$with, loop$index) {
|
|
901
|
+
while (true) {
|
|
902
|
+
let over = loop$over;
|
|
903
|
+
let acc = loop$acc;
|
|
904
|
+
let with$ = loop$with;
|
|
905
|
+
let index = loop$index;
|
|
906
|
+
if (over instanceof $Empty) {
|
|
907
|
+
return acc;
|
|
908
|
+
} else {
|
|
909
|
+
let first$1 = over.head;
|
|
910
|
+
let rest$1 = over.tail;
|
|
911
|
+
loop$over = rest$1;
|
|
912
|
+
loop$acc = with$(acc, first$1, index);
|
|
913
|
+
loop$with = with$;
|
|
914
|
+
loop$index = index + 1;
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
/**
|
|
920
|
+
* Like `fold` but the folding function also receives the index of the current element.
|
|
921
|
+
*
|
|
922
|
+
* ## Examples
|
|
923
|
+
*
|
|
924
|
+
* ```gleam
|
|
925
|
+
* assert ["a", "b", "c"]
|
|
926
|
+
* |> index_fold("", fn(acc, item, index) {
|
|
927
|
+
* acc <> int.to_string(index) <> ":" <> item <> " "
|
|
928
|
+
* })
|
|
929
|
+
* == "0:a 1:b 2:c"
|
|
930
|
+
* ```
|
|
931
|
+
*
|
|
932
|
+
* ```gleam
|
|
933
|
+
* assert [10, 20, 30]
|
|
934
|
+
* |> index_fold(0, fn(acc, item, index) { acc + item * index })
|
|
935
|
+
* == 80
|
|
936
|
+
* ```
|
|
937
|
+
*/
|
|
938
|
+
export function index_fold(list, initial, fun) {
|
|
939
|
+
return index_fold_loop(list, initial, fun, 0);
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
/**
|
|
943
|
+
* A variant of fold that might fail.
|
|
944
|
+
*
|
|
945
|
+
* The folding function should return `Result(accumulator, error)`.
|
|
946
|
+
* If the returned value is `Ok(accumulator)` try_fold will try the next value in the list.
|
|
947
|
+
* If the returned value is `Error(error)` try_fold will stop and return that error.
|
|
948
|
+
*
|
|
949
|
+
* ## Examples
|
|
950
|
+
*
|
|
951
|
+
* ```gleam
|
|
952
|
+
* assert [1, 2, 3, 4]
|
|
953
|
+
* |> try_fold(0, fn(acc, i) {
|
|
954
|
+
* case i < 3 {
|
|
955
|
+
* True -> Ok(acc + i)
|
|
956
|
+
* False -> Error(Nil)
|
|
957
|
+
* }
|
|
958
|
+
* })
|
|
959
|
+
* == Error(Nil)
|
|
960
|
+
* ```
|
|
961
|
+
*/
|
|
962
|
+
export function try_fold(loop$list, loop$initial, loop$fun) {
|
|
963
|
+
while (true) {
|
|
964
|
+
let list = loop$list;
|
|
965
|
+
let initial = loop$initial;
|
|
966
|
+
let fun = loop$fun;
|
|
967
|
+
if (list instanceof $Empty) {
|
|
968
|
+
return new Ok(initial);
|
|
969
|
+
} else {
|
|
970
|
+
let first$1 = list.head;
|
|
971
|
+
let rest$1 = list.tail;
|
|
972
|
+
let $ = fun(initial, first$1);
|
|
973
|
+
if ($ instanceof Ok) {
|
|
974
|
+
let result = $[0];
|
|
975
|
+
loop$list = rest$1;
|
|
976
|
+
loop$initial = result;
|
|
977
|
+
loop$fun = fun;
|
|
978
|
+
} else {
|
|
979
|
+
return $;
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
/**
|
|
986
|
+
* A variant of fold that allows to stop folding earlier.
|
|
987
|
+
*
|
|
988
|
+
* The folding function should return `ContinueOrStop(accumulator)`.
|
|
989
|
+
* If the returned value is `Continue(accumulator)` fold_until will try the next value in the list.
|
|
990
|
+
* If the returned value is `Stop(accumulator)` fold_until will stop and return that accumulator.
|
|
991
|
+
*
|
|
992
|
+
* ## Examples
|
|
993
|
+
*
|
|
994
|
+
* ```gleam
|
|
995
|
+
* assert [1, 2, 3, 4]
|
|
996
|
+
* |> fold_until(0, fn(acc, i) {
|
|
997
|
+
* case i < 3 {
|
|
998
|
+
* True -> Continue(acc + i)
|
|
999
|
+
* False -> Stop(acc)
|
|
1000
|
+
* }
|
|
1001
|
+
* })
|
|
1002
|
+
* == 3
|
|
1003
|
+
* ```
|
|
1004
|
+
*/
|
|
1005
|
+
export function fold_until(loop$list, loop$initial, loop$fun) {
|
|
1006
|
+
while (true) {
|
|
1007
|
+
let list = loop$list;
|
|
1008
|
+
let initial = loop$initial;
|
|
1009
|
+
let fun = loop$fun;
|
|
1010
|
+
if (list instanceof $Empty) {
|
|
1011
|
+
return initial;
|
|
1012
|
+
} else {
|
|
1013
|
+
let first$1 = list.head;
|
|
1014
|
+
let rest$1 = list.tail;
|
|
1015
|
+
let $ = fun(initial, first$1);
|
|
1016
|
+
if ($ instanceof Continue) {
|
|
1017
|
+
let next_accumulator = $[0];
|
|
1018
|
+
loop$list = rest$1;
|
|
1019
|
+
loop$initial = next_accumulator;
|
|
1020
|
+
loop$fun = fun;
|
|
1021
|
+
} else {
|
|
1022
|
+
let b = $[0];
|
|
1023
|
+
return b;
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
/**
|
|
1030
|
+
* Finds the first element in a given list for which the given function returns
|
|
1031
|
+
* `True`.
|
|
1032
|
+
*
|
|
1033
|
+
* Returns `Error(Nil)` if no such element is found.
|
|
1034
|
+
*
|
|
1035
|
+
* ## Examples
|
|
1036
|
+
*
|
|
1037
|
+
* ```gleam
|
|
1038
|
+
* assert find([1, 2, 3], fn(x) { x > 2 }) == Ok(3)
|
|
1039
|
+
* ```
|
|
1040
|
+
*
|
|
1041
|
+
* ```gleam
|
|
1042
|
+
* assert find([1, 2, 3], fn(x) { x > 4 }) == Error(Nil)
|
|
1043
|
+
* ```
|
|
1044
|
+
*
|
|
1045
|
+
* ```gleam
|
|
1046
|
+
* assert find([], fn(_) { True }) == Error(Nil)
|
|
1047
|
+
* ```
|
|
1048
|
+
*/
|
|
1049
|
+
export function find(loop$list, loop$is_desired) {
|
|
1050
|
+
while (true) {
|
|
1051
|
+
let list = loop$list;
|
|
1052
|
+
let is_desired = loop$is_desired;
|
|
1053
|
+
if (list instanceof $Empty) {
|
|
1054
|
+
return new Error(undefined);
|
|
1055
|
+
} else {
|
|
1056
|
+
let first$1 = list.head;
|
|
1057
|
+
let rest$1 = list.tail;
|
|
1058
|
+
let $ = is_desired(first$1);
|
|
1059
|
+
if ($) {
|
|
1060
|
+
return new Ok(first$1);
|
|
1061
|
+
} else {
|
|
1062
|
+
loop$list = rest$1;
|
|
1063
|
+
loop$is_desired = is_desired;
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
/**
|
|
1070
|
+
* Finds the first element in a given list for which the given function returns
|
|
1071
|
+
* `Ok(new_value)`, then returns the wrapped `new_value`.
|
|
1072
|
+
*
|
|
1073
|
+
* Returns `Error(Nil)` if no such element is found.
|
|
1074
|
+
*
|
|
1075
|
+
* ## Examples
|
|
1076
|
+
*
|
|
1077
|
+
* ```gleam
|
|
1078
|
+
* assert find_map([[], [2], [3]], first) == Ok(2)
|
|
1079
|
+
* ```
|
|
1080
|
+
*
|
|
1081
|
+
* ```gleam
|
|
1082
|
+
* assert find_map([[], []], first) == Error(Nil)
|
|
1083
|
+
* ```
|
|
1084
|
+
*
|
|
1085
|
+
* ```gleam
|
|
1086
|
+
* assert find_map([], first) == Error(Nil)
|
|
1087
|
+
* ```
|
|
1088
|
+
*/
|
|
1089
|
+
export function find_map(loop$list, loop$fun) {
|
|
1090
|
+
while (true) {
|
|
1091
|
+
let list = loop$list;
|
|
1092
|
+
let fun = loop$fun;
|
|
1093
|
+
if (list instanceof $Empty) {
|
|
1094
|
+
return new Error(undefined);
|
|
1095
|
+
} else {
|
|
1096
|
+
let first$1 = list.head;
|
|
1097
|
+
let rest$1 = list.tail;
|
|
1098
|
+
let $ = fun(first$1);
|
|
1099
|
+
if ($ instanceof Ok) {
|
|
1100
|
+
return $;
|
|
1101
|
+
} else {
|
|
1102
|
+
loop$list = rest$1;
|
|
1103
|
+
loop$fun = fun;
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
/**
|
|
1110
|
+
* Returns `True` if the given function returns `True` for all the elements in
|
|
1111
|
+
* the given list. If the function returns `False` for any of the elements it
|
|
1112
|
+
* immediately returns `False` without checking the rest of the list.
|
|
1113
|
+
*
|
|
1114
|
+
* ## Examples
|
|
1115
|
+
*
|
|
1116
|
+
* ```gleam
|
|
1117
|
+
* assert all([], fn(x) { x > 3 })
|
|
1118
|
+
* ```
|
|
1119
|
+
*
|
|
1120
|
+
* ```gleam
|
|
1121
|
+
* assert all([4, 5], fn(x) { x > 3 })
|
|
1122
|
+
* ```
|
|
1123
|
+
*
|
|
1124
|
+
* ```gleam
|
|
1125
|
+
* assert !all([4, 3], fn(x) { x > 3 })
|
|
1126
|
+
* ```
|
|
1127
|
+
*/
|
|
1128
|
+
export function all(loop$list, loop$predicate) {
|
|
1129
|
+
while (true) {
|
|
1130
|
+
let list = loop$list;
|
|
1131
|
+
let predicate = loop$predicate;
|
|
1132
|
+
if (list instanceof $Empty) {
|
|
1133
|
+
return true;
|
|
1134
|
+
} else {
|
|
1135
|
+
let first$1 = list.head;
|
|
1136
|
+
let rest$1 = list.tail;
|
|
1137
|
+
let $ = predicate(first$1);
|
|
1138
|
+
if ($) {
|
|
1139
|
+
loop$list = rest$1;
|
|
1140
|
+
loop$predicate = predicate;
|
|
1141
|
+
} else {
|
|
1142
|
+
return $;
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
/**
|
|
1149
|
+
* Returns `True` if the given function returns `True` for any the elements in
|
|
1150
|
+
* the given list. If the function returns `True` for any of the elements it
|
|
1151
|
+
* immediately returns `True` without checking the rest of the list.
|
|
1152
|
+
*
|
|
1153
|
+
* ## Examples
|
|
1154
|
+
*
|
|
1155
|
+
* ```gleam
|
|
1156
|
+
* assert !any([], fn(x) { x > 3 })
|
|
1157
|
+
* ```
|
|
1158
|
+
*
|
|
1159
|
+
* ```gleam
|
|
1160
|
+
* assert any([4, 5], fn(x) { x > 3 })
|
|
1161
|
+
* ```
|
|
1162
|
+
*
|
|
1163
|
+
* ```gleam
|
|
1164
|
+
* assert any([4, 3], fn(x) { x > 4 })
|
|
1165
|
+
* ```
|
|
1166
|
+
*
|
|
1167
|
+
* ```gleam
|
|
1168
|
+
* assert any([3, 4], fn(x) { x > 3 })
|
|
1169
|
+
* ```
|
|
1170
|
+
*/
|
|
1171
|
+
export function any(loop$list, loop$predicate) {
|
|
1172
|
+
while (true) {
|
|
1173
|
+
let list = loop$list;
|
|
1174
|
+
let predicate = loop$predicate;
|
|
1175
|
+
if (list instanceof $Empty) {
|
|
1176
|
+
return false;
|
|
1177
|
+
} else {
|
|
1178
|
+
let first$1 = list.head;
|
|
1179
|
+
let rest$1 = list.tail;
|
|
1180
|
+
let $ = predicate(first$1);
|
|
1181
|
+
if ($) {
|
|
1182
|
+
return $;
|
|
1183
|
+
} else {
|
|
1184
|
+
loop$list = rest$1;
|
|
1185
|
+
loop$predicate = predicate;
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
function zip_loop(loop$one, loop$other, loop$acc) {
|
|
1192
|
+
while (true) {
|
|
1193
|
+
let one = loop$one;
|
|
1194
|
+
let other = loop$other;
|
|
1195
|
+
let acc = loop$acc;
|
|
1196
|
+
if (one instanceof $Empty) {
|
|
1197
|
+
return reverse(acc);
|
|
1198
|
+
} else if (other instanceof $Empty) {
|
|
1199
|
+
return reverse(acc);
|
|
1200
|
+
} else {
|
|
1201
|
+
let first_one = one.head;
|
|
1202
|
+
let rest_one = one.tail;
|
|
1203
|
+
let first_other = other.head;
|
|
1204
|
+
let rest_other = other.tail;
|
|
1205
|
+
loop$one = rest_one;
|
|
1206
|
+
loop$other = rest_other;
|
|
1207
|
+
loop$acc = listPrepend([first_one, first_other], acc);
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
/**
|
|
1213
|
+
* Takes two lists and returns a single list of 2-element tuples.
|
|
1214
|
+
*
|
|
1215
|
+
* If one of the lists is longer than the other, the remaining elements from
|
|
1216
|
+
* the longer list are not used.
|
|
1217
|
+
*
|
|
1218
|
+
* ## Examples
|
|
1219
|
+
*
|
|
1220
|
+
* ```gleam
|
|
1221
|
+
* assert zip([], []) == []
|
|
1222
|
+
* ```
|
|
1223
|
+
*
|
|
1224
|
+
* ```gleam
|
|
1225
|
+
* assert zip([1, 2], [3]) == [#(1, 3)]
|
|
1226
|
+
* ```
|
|
1227
|
+
*
|
|
1228
|
+
* ```gleam
|
|
1229
|
+
* assert zip([1], [3, 4]) == [#(1, 3)]
|
|
1230
|
+
* ```
|
|
1231
|
+
*
|
|
1232
|
+
* ```gleam
|
|
1233
|
+
* assert zip([1, 2], [3, 4]) == [#(1, 3), #(2, 4)]
|
|
1234
|
+
* ```
|
|
1235
|
+
*/
|
|
1236
|
+
export function zip(list, other) {
|
|
1237
|
+
return zip_loop(list, other, toList([]));
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
function strict_zip_loop(loop$one, loop$other, loop$acc) {
|
|
1241
|
+
while (true) {
|
|
1242
|
+
let one = loop$one;
|
|
1243
|
+
let other = loop$other;
|
|
1244
|
+
let acc = loop$acc;
|
|
1245
|
+
if (one instanceof $Empty) {
|
|
1246
|
+
if (other instanceof $Empty) {
|
|
1247
|
+
return new Ok(reverse(acc));
|
|
1248
|
+
} else {
|
|
1249
|
+
return new Error(undefined);
|
|
1250
|
+
}
|
|
1251
|
+
} else if (other instanceof $Empty) {
|
|
1252
|
+
return new Error(undefined);
|
|
1253
|
+
} else {
|
|
1254
|
+
let first_one = one.head;
|
|
1255
|
+
let rest_one = one.tail;
|
|
1256
|
+
let first_other = other.head;
|
|
1257
|
+
let rest_other = other.tail;
|
|
1258
|
+
loop$one = rest_one;
|
|
1259
|
+
loop$other = rest_other;
|
|
1260
|
+
loop$acc = listPrepend([first_one, first_other], acc);
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
/**
|
|
1266
|
+
* Takes two lists and returns a single list of 2-element tuples.
|
|
1267
|
+
*
|
|
1268
|
+
* If one of the lists is longer than the other, an `Error` is returned.
|
|
1269
|
+
*
|
|
1270
|
+
* ## Examples
|
|
1271
|
+
*
|
|
1272
|
+
* ```gleam
|
|
1273
|
+
* assert strict_zip([], []) == Ok([])
|
|
1274
|
+
* ```
|
|
1275
|
+
*
|
|
1276
|
+
* ```gleam
|
|
1277
|
+
* assert strict_zip([1, 2], [3]) == Error(Nil)
|
|
1278
|
+
* ```
|
|
1279
|
+
*
|
|
1280
|
+
* ```gleam
|
|
1281
|
+
* assert strict_zip([1], [3, 4]) == Error(Nil)
|
|
1282
|
+
* ```
|
|
1283
|
+
*
|
|
1284
|
+
* ```gleam
|
|
1285
|
+
* assert strict_zip([1, 2], [3, 4]) == Ok([#(1, 3), #(2, 4)])
|
|
1286
|
+
* ```
|
|
1287
|
+
*/
|
|
1288
|
+
export function strict_zip(list, other) {
|
|
1289
|
+
return strict_zip_loop(list, other, toList([]));
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
function unzip_loop(loop$input, loop$one, loop$other) {
|
|
1293
|
+
while (true) {
|
|
1294
|
+
let input = loop$input;
|
|
1295
|
+
let one = loop$one;
|
|
1296
|
+
let other = loop$other;
|
|
1297
|
+
if (input instanceof $Empty) {
|
|
1298
|
+
return [reverse(one), reverse(other)];
|
|
1299
|
+
} else {
|
|
1300
|
+
let rest$1 = input.tail;
|
|
1301
|
+
let first_one = input.head[0];
|
|
1302
|
+
let first_other = input.head[1];
|
|
1303
|
+
loop$input = rest$1;
|
|
1304
|
+
loop$one = listPrepend(first_one, one);
|
|
1305
|
+
loop$other = listPrepend(first_other, other);
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
/**
|
|
1311
|
+
* Takes a single list of 2-element tuples and returns two lists.
|
|
1312
|
+
*
|
|
1313
|
+
* ## Examples
|
|
1314
|
+
*
|
|
1315
|
+
* ```gleam
|
|
1316
|
+
* assert unzip([#(1, 2), #(3, 4)]) == #([1, 3], [2, 4])
|
|
1317
|
+
* ```
|
|
1318
|
+
*
|
|
1319
|
+
* ```gleam
|
|
1320
|
+
* assert unzip([]) == #([], [])
|
|
1321
|
+
* ```
|
|
1322
|
+
*/
|
|
1323
|
+
export function unzip(input) {
|
|
1324
|
+
return unzip_loop(input, toList([]), toList([]));
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
function intersperse_loop(loop$list, loop$separator, loop$acc) {
|
|
1328
|
+
while (true) {
|
|
1329
|
+
let list = loop$list;
|
|
1330
|
+
let separator = loop$separator;
|
|
1331
|
+
let acc = loop$acc;
|
|
1332
|
+
if (list instanceof $Empty) {
|
|
1333
|
+
return reverse(acc);
|
|
1334
|
+
} else {
|
|
1335
|
+
let first$1 = list.head;
|
|
1336
|
+
let rest$1 = list.tail;
|
|
1337
|
+
loop$list = rest$1;
|
|
1338
|
+
loop$separator = separator;
|
|
1339
|
+
loop$acc = listPrepend(first$1, listPrepend(separator, acc));
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
/**
|
|
1345
|
+
* Inserts a given value between each existing element in a given list.
|
|
1346
|
+
*
|
|
1347
|
+
* This function runs in linear time and copies the list.
|
|
1348
|
+
*
|
|
1349
|
+
* ## Examples
|
|
1350
|
+
*
|
|
1351
|
+
* ```gleam
|
|
1352
|
+
* assert intersperse([1, 1, 1], 2) == [1, 2, 1, 2, 1]
|
|
1353
|
+
* ```
|
|
1354
|
+
*
|
|
1355
|
+
* ```gleam
|
|
1356
|
+
* assert intersperse([], 2) == []
|
|
1357
|
+
* ```
|
|
1358
|
+
*/
|
|
1359
|
+
export function intersperse(list, elem) {
|
|
1360
|
+
if (list instanceof $Empty) {
|
|
1361
|
+
return list;
|
|
1362
|
+
} else {
|
|
1363
|
+
let $ = list.tail;
|
|
1364
|
+
if ($ instanceof $Empty) {
|
|
1365
|
+
return list;
|
|
1366
|
+
} else {
|
|
1367
|
+
let first$1 = list.head;
|
|
1368
|
+
let rest$1 = $;
|
|
1369
|
+
return intersperse_loop(rest$1, elem, toList([first$1]));
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
function unique_loop(loop$list, loop$seen, loop$acc) {
|
|
1375
|
+
while (true) {
|
|
1376
|
+
let list = loop$list;
|
|
1377
|
+
let seen = loop$seen;
|
|
1378
|
+
let acc = loop$acc;
|
|
1379
|
+
if (list instanceof $Empty) {
|
|
1380
|
+
return reverse(acc);
|
|
1381
|
+
} else {
|
|
1382
|
+
let first$1 = list.head;
|
|
1383
|
+
let rest$1 = list.tail;
|
|
1384
|
+
let $ = $dict.has_key(seen, first$1);
|
|
1385
|
+
if ($) {
|
|
1386
|
+
loop$list = rest$1;
|
|
1387
|
+
loop$seen = seen;
|
|
1388
|
+
loop$acc = acc;
|
|
1389
|
+
} else {
|
|
1390
|
+
loop$list = rest$1;
|
|
1391
|
+
loop$seen = $dict.insert(seen, first$1, undefined);
|
|
1392
|
+
loop$acc = listPrepend(first$1, acc);
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
/**
|
|
1399
|
+
* Removes any duplicate elements from a given list.
|
|
1400
|
+
*
|
|
1401
|
+
* This function returns in loglinear time.
|
|
1402
|
+
*
|
|
1403
|
+
* ## Examples
|
|
1404
|
+
*
|
|
1405
|
+
* ```gleam
|
|
1406
|
+
* assert unique([1, 1, 1, 4, 7, 3, 3, 4]) == [1, 4, 7, 3]
|
|
1407
|
+
* ```
|
|
1408
|
+
*/
|
|
1409
|
+
export function unique(list) {
|
|
1410
|
+
return unique_loop(list, $dict.new$(), toList([]));
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
/**
|
|
1414
|
+
* Given a list it returns slices of it that are locally sorted in ascending
|
|
1415
|
+
* order.
|
|
1416
|
+
*
|
|
1417
|
+
* Imagine you have this list:
|
|
1418
|
+
*
|
|
1419
|
+
* ```
|
|
1420
|
+
* [1, 2, 3, 2, 1, 0]
|
|
1421
|
+
* ^^^^^^^ ^^^^^^^ This is a slice in descending order
|
|
1422
|
+
* |
|
|
1423
|
+
* | This is a slice that is sorted in ascending order
|
|
1424
|
+
* ```
|
|
1425
|
+
*
|
|
1426
|
+
* So the produced result will contain these two slices, each one sorted in
|
|
1427
|
+
* ascending order: `[[1, 2, 3], [0, 1, 2]]`.
|
|
1428
|
+
*
|
|
1429
|
+
* - `growing` is an accumulator with the current slice being grown
|
|
1430
|
+
* - `direction` is the growing direction of the slice being grown, it could
|
|
1431
|
+
* either be ascending or strictly descending
|
|
1432
|
+
* - `prev` is the previous element that needs to be added to the growing slice
|
|
1433
|
+
* it is carried around to check whether we have to keep growing the current
|
|
1434
|
+
* slice or not
|
|
1435
|
+
* - `acc` is the accumulator containing the slices sorted in ascending order
|
|
1436
|
+
*
|
|
1437
|
+
* @ignore
|
|
1438
|
+
*/
|
|
1439
|
+
function sequences(
|
|
1440
|
+
loop$list,
|
|
1441
|
+
loop$compare,
|
|
1442
|
+
loop$growing,
|
|
1443
|
+
loop$direction,
|
|
1444
|
+
loop$prev,
|
|
1445
|
+
loop$acc
|
|
1446
|
+
) {
|
|
1447
|
+
while (true) {
|
|
1448
|
+
let list = loop$list;
|
|
1449
|
+
let compare = loop$compare;
|
|
1450
|
+
let growing = loop$growing;
|
|
1451
|
+
let direction = loop$direction;
|
|
1452
|
+
let prev = loop$prev;
|
|
1453
|
+
let acc = loop$acc;
|
|
1454
|
+
let growing$1 = listPrepend(prev, growing);
|
|
1455
|
+
if (list instanceof $Empty) {
|
|
1456
|
+
if (direction instanceof Ascending) {
|
|
1457
|
+
return listPrepend(reverse(growing$1), acc);
|
|
1458
|
+
} else {
|
|
1459
|
+
return listPrepend(growing$1, acc);
|
|
1460
|
+
}
|
|
1461
|
+
} else {
|
|
1462
|
+
let new$1 = list.head;
|
|
1463
|
+
let rest$1 = list.tail;
|
|
1464
|
+
let $ = compare(prev, new$1);
|
|
1465
|
+
if (direction instanceof Ascending) {
|
|
1466
|
+
if ($ instanceof $order.Lt) {
|
|
1467
|
+
loop$list = rest$1;
|
|
1468
|
+
loop$compare = compare;
|
|
1469
|
+
loop$growing = growing$1;
|
|
1470
|
+
loop$direction = direction;
|
|
1471
|
+
loop$prev = new$1;
|
|
1472
|
+
loop$acc = acc;
|
|
1473
|
+
} else if ($ instanceof $order.Eq) {
|
|
1474
|
+
loop$list = rest$1;
|
|
1475
|
+
loop$compare = compare;
|
|
1476
|
+
loop$growing = growing$1;
|
|
1477
|
+
loop$direction = direction;
|
|
1478
|
+
loop$prev = new$1;
|
|
1479
|
+
loop$acc = acc;
|
|
1480
|
+
} else {
|
|
1481
|
+
let _block;
|
|
1482
|
+
if (direction instanceof Ascending) {
|
|
1483
|
+
_block = listPrepend(reverse(growing$1), acc);
|
|
1484
|
+
} else {
|
|
1485
|
+
_block = listPrepend(growing$1, acc);
|
|
1486
|
+
}
|
|
1487
|
+
let acc$1 = _block;
|
|
1488
|
+
if (rest$1 instanceof $Empty) {
|
|
1489
|
+
return listPrepend(toList([new$1]), acc$1);
|
|
1490
|
+
} else {
|
|
1491
|
+
let next = rest$1.head;
|
|
1492
|
+
let rest$2 = rest$1.tail;
|
|
1493
|
+
let _block$1;
|
|
1494
|
+
let $1 = compare(new$1, next);
|
|
1495
|
+
if ($1 instanceof $order.Lt) {
|
|
1496
|
+
_block$1 = new Ascending();
|
|
1497
|
+
} else if ($1 instanceof $order.Eq) {
|
|
1498
|
+
_block$1 = new Ascending();
|
|
1499
|
+
} else {
|
|
1500
|
+
_block$1 = new Descending();
|
|
1501
|
+
}
|
|
1502
|
+
let direction$1 = _block$1;
|
|
1503
|
+
loop$list = rest$2;
|
|
1504
|
+
loop$compare = compare;
|
|
1505
|
+
loop$growing = toList([new$1]);
|
|
1506
|
+
loop$direction = direction$1;
|
|
1507
|
+
loop$prev = next;
|
|
1508
|
+
loop$acc = acc$1;
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
} else if ($ instanceof $order.Lt) {
|
|
1512
|
+
let _block;
|
|
1513
|
+
if (direction instanceof Ascending) {
|
|
1514
|
+
_block = listPrepend(reverse(growing$1), acc);
|
|
1515
|
+
} else {
|
|
1516
|
+
_block = listPrepend(growing$1, acc);
|
|
1517
|
+
}
|
|
1518
|
+
let acc$1 = _block;
|
|
1519
|
+
if (rest$1 instanceof $Empty) {
|
|
1520
|
+
return listPrepend(toList([new$1]), acc$1);
|
|
1521
|
+
} else {
|
|
1522
|
+
let next = rest$1.head;
|
|
1523
|
+
let rest$2 = rest$1.tail;
|
|
1524
|
+
let _block$1;
|
|
1525
|
+
let $1 = compare(new$1, next);
|
|
1526
|
+
if ($1 instanceof $order.Lt) {
|
|
1527
|
+
_block$1 = new Ascending();
|
|
1528
|
+
} else if ($1 instanceof $order.Eq) {
|
|
1529
|
+
_block$1 = new Ascending();
|
|
1530
|
+
} else {
|
|
1531
|
+
_block$1 = new Descending();
|
|
1532
|
+
}
|
|
1533
|
+
let direction$1 = _block$1;
|
|
1534
|
+
loop$list = rest$2;
|
|
1535
|
+
loop$compare = compare;
|
|
1536
|
+
loop$growing = toList([new$1]);
|
|
1537
|
+
loop$direction = direction$1;
|
|
1538
|
+
loop$prev = next;
|
|
1539
|
+
loop$acc = acc$1;
|
|
1540
|
+
}
|
|
1541
|
+
} else if ($ instanceof $order.Eq) {
|
|
1542
|
+
let _block;
|
|
1543
|
+
if (direction instanceof Ascending) {
|
|
1544
|
+
_block = listPrepend(reverse(growing$1), acc);
|
|
1545
|
+
} else {
|
|
1546
|
+
_block = listPrepend(growing$1, acc);
|
|
1547
|
+
}
|
|
1548
|
+
let acc$1 = _block;
|
|
1549
|
+
if (rest$1 instanceof $Empty) {
|
|
1550
|
+
return listPrepend(toList([new$1]), acc$1);
|
|
1551
|
+
} else {
|
|
1552
|
+
let next = rest$1.head;
|
|
1553
|
+
let rest$2 = rest$1.tail;
|
|
1554
|
+
let _block$1;
|
|
1555
|
+
let $1 = compare(new$1, next);
|
|
1556
|
+
if ($1 instanceof $order.Lt) {
|
|
1557
|
+
_block$1 = new Ascending();
|
|
1558
|
+
} else if ($1 instanceof $order.Eq) {
|
|
1559
|
+
_block$1 = new Ascending();
|
|
1560
|
+
} else {
|
|
1561
|
+
_block$1 = new Descending();
|
|
1562
|
+
}
|
|
1563
|
+
let direction$1 = _block$1;
|
|
1564
|
+
loop$list = rest$2;
|
|
1565
|
+
loop$compare = compare;
|
|
1566
|
+
loop$growing = toList([new$1]);
|
|
1567
|
+
loop$direction = direction$1;
|
|
1568
|
+
loop$prev = next;
|
|
1569
|
+
loop$acc = acc$1;
|
|
1570
|
+
}
|
|
1571
|
+
} else {
|
|
1572
|
+
loop$list = rest$1;
|
|
1573
|
+
loop$compare = compare;
|
|
1574
|
+
loop$growing = growing$1;
|
|
1575
|
+
loop$direction = direction;
|
|
1576
|
+
loop$prev = new$1;
|
|
1577
|
+
loop$acc = acc;
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
/**
|
|
1584
|
+
* Merges two lists sorted in ascending order into a single list sorted in
|
|
1585
|
+
* descending order according to the given comparator function.
|
|
1586
|
+
*
|
|
1587
|
+
* This reversing of the sort order is not avoidable if we want to implement
|
|
1588
|
+
* merge as a tail recursive function. We could reverse the accumulator before
|
|
1589
|
+
* returning it but that would end up being less efficient; so the merging
|
|
1590
|
+
* algorithm has to play around this.
|
|
1591
|
+
*
|
|
1592
|
+
* @ignore
|
|
1593
|
+
*/
|
|
1594
|
+
function merge_ascendings(loop$list1, loop$list2, loop$compare, loop$acc) {
|
|
1595
|
+
while (true) {
|
|
1596
|
+
let list1 = loop$list1;
|
|
1597
|
+
let list2 = loop$list2;
|
|
1598
|
+
let compare = loop$compare;
|
|
1599
|
+
let acc = loop$acc;
|
|
1600
|
+
if (list1 instanceof $Empty) {
|
|
1601
|
+
let list = list2;
|
|
1602
|
+
return reverse_and_prepend(list, acc);
|
|
1603
|
+
} else if (list2 instanceof $Empty) {
|
|
1604
|
+
let list = list1;
|
|
1605
|
+
return reverse_and_prepend(list, acc);
|
|
1606
|
+
} else {
|
|
1607
|
+
let first1 = list1.head;
|
|
1608
|
+
let rest1 = list1.tail;
|
|
1609
|
+
let first2 = list2.head;
|
|
1610
|
+
let rest2 = list2.tail;
|
|
1611
|
+
let $ = compare(first1, first2);
|
|
1612
|
+
if ($ instanceof $order.Lt) {
|
|
1613
|
+
loop$list1 = rest1;
|
|
1614
|
+
loop$list2 = list2;
|
|
1615
|
+
loop$compare = compare;
|
|
1616
|
+
loop$acc = listPrepend(first1, acc);
|
|
1617
|
+
} else if ($ instanceof $order.Eq) {
|
|
1618
|
+
loop$list1 = list1;
|
|
1619
|
+
loop$list2 = rest2;
|
|
1620
|
+
loop$compare = compare;
|
|
1621
|
+
loop$acc = listPrepend(first2, acc);
|
|
1622
|
+
} else {
|
|
1623
|
+
loop$list1 = list1;
|
|
1624
|
+
loop$list2 = rest2;
|
|
1625
|
+
loop$compare = compare;
|
|
1626
|
+
loop$acc = listPrepend(first2, acc);
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
/**
|
|
1633
|
+
* Given a list of ascending lists, it merges adjacent pairs into a single
|
|
1634
|
+
* descending list, halving their number.
|
|
1635
|
+
* It returns a list of the remaining descending lists.
|
|
1636
|
+
*
|
|
1637
|
+
* @ignore
|
|
1638
|
+
*/
|
|
1639
|
+
function merge_ascending_pairs(loop$sequences, loop$compare, loop$acc) {
|
|
1640
|
+
while (true) {
|
|
1641
|
+
let sequences = loop$sequences;
|
|
1642
|
+
let compare = loop$compare;
|
|
1643
|
+
let acc = loop$acc;
|
|
1644
|
+
if (sequences instanceof $Empty) {
|
|
1645
|
+
return reverse(acc);
|
|
1646
|
+
} else {
|
|
1647
|
+
let $ = sequences.tail;
|
|
1648
|
+
if ($ instanceof $Empty) {
|
|
1649
|
+
let sequence = sequences.head;
|
|
1650
|
+
return reverse(listPrepend(reverse(sequence), acc));
|
|
1651
|
+
} else {
|
|
1652
|
+
let ascending1 = sequences.head;
|
|
1653
|
+
let ascending2 = $.head;
|
|
1654
|
+
let rest$1 = $.tail;
|
|
1655
|
+
let descending = merge_ascendings(
|
|
1656
|
+
ascending1,
|
|
1657
|
+
ascending2,
|
|
1658
|
+
compare,
|
|
1659
|
+
toList([]),
|
|
1660
|
+
);
|
|
1661
|
+
loop$sequences = rest$1;
|
|
1662
|
+
loop$compare = compare;
|
|
1663
|
+
loop$acc = listPrepend(descending, acc);
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1669
|
+
/**
|
|
1670
|
+
* This is exactly the same as merge_ascendings but mirrored: it merges two
|
|
1671
|
+
* lists sorted in descending order into a single list sorted in ascending
|
|
1672
|
+
* order according to the given comparator function.
|
|
1673
|
+
*
|
|
1674
|
+
* This reversing of the sort order is not avoidable if we want to implement
|
|
1675
|
+
* merge as a tail recursive function. We could reverse the accumulator before
|
|
1676
|
+
* returning it but that would end up being less efficient; so the merging
|
|
1677
|
+
* algorithm has to play around this.
|
|
1678
|
+
*
|
|
1679
|
+
* @ignore
|
|
1680
|
+
*/
|
|
1681
|
+
function merge_descendings(loop$list1, loop$list2, loop$compare, loop$acc) {
|
|
1682
|
+
while (true) {
|
|
1683
|
+
let list1 = loop$list1;
|
|
1684
|
+
let list2 = loop$list2;
|
|
1685
|
+
let compare = loop$compare;
|
|
1686
|
+
let acc = loop$acc;
|
|
1687
|
+
if (list1 instanceof $Empty) {
|
|
1688
|
+
let list = list2;
|
|
1689
|
+
return reverse_and_prepend(list, acc);
|
|
1690
|
+
} else if (list2 instanceof $Empty) {
|
|
1691
|
+
let list = list1;
|
|
1692
|
+
return reverse_and_prepend(list, acc);
|
|
1693
|
+
} else {
|
|
1694
|
+
let first1 = list1.head;
|
|
1695
|
+
let rest1 = list1.tail;
|
|
1696
|
+
let first2 = list2.head;
|
|
1697
|
+
let rest2 = list2.tail;
|
|
1698
|
+
let $ = compare(first1, first2);
|
|
1699
|
+
if ($ instanceof $order.Lt) {
|
|
1700
|
+
loop$list1 = list1;
|
|
1701
|
+
loop$list2 = rest2;
|
|
1702
|
+
loop$compare = compare;
|
|
1703
|
+
loop$acc = listPrepend(first2, acc);
|
|
1704
|
+
} else if ($ instanceof $order.Eq) {
|
|
1705
|
+
loop$list1 = rest1;
|
|
1706
|
+
loop$list2 = list2;
|
|
1707
|
+
loop$compare = compare;
|
|
1708
|
+
loop$acc = listPrepend(first1, acc);
|
|
1709
|
+
} else {
|
|
1710
|
+
loop$list1 = rest1;
|
|
1711
|
+
loop$list2 = list2;
|
|
1712
|
+
loop$compare = compare;
|
|
1713
|
+
loop$acc = listPrepend(first1, acc);
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
/**
|
|
1720
|
+
* This is the same as merge_ascending_pairs but flipped for descending lists.
|
|
1721
|
+
*
|
|
1722
|
+
* @ignore
|
|
1723
|
+
*/
|
|
1724
|
+
function merge_descending_pairs(loop$sequences, loop$compare, loop$acc) {
|
|
1725
|
+
while (true) {
|
|
1726
|
+
let sequences = loop$sequences;
|
|
1727
|
+
let compare = loop$compare;
|
|
1728
|
+
let acc = loop$acc;
|
|
1729
|
+
if (sequences instanceof $Empty) {
|
|
1730
|
+
return reverse(acc);
|
|
1731
|
+
} else {
|
|
1732
|
+
let $ = sequences.tail;
|
|
1733
|
+
if ($ instanceof $Empty) {
|
|
1734
|
+
let sequence = sequences.head;
|
|
1735
|
+
return reverse(listPrepend(reverse(sequence), acc));
|
|
1736
|
+
} else {
|
|
1737
|
+
let descending1 = sequences.head;
|
|
1738
|
+
let descending2 = $.head;
|
|
1739
|
+
let rest$1 = $.tail;
|
|
1740
|
+
let ascending = merge_descendings(
|
|
1741
|
+
descending1,
|
|
1742
|
+
descending2,
|
|
1743
|
+
compare,
|
|
1744
|
+
toList([]),
|
|
1745
|
+
);
|
|
1746
|
+
loop$sequences = rest$1;
|
|
1747
|
+
loop$compare = compare;
|
|
1748
|
+
loop$acc = listPrepend(ascending, acc);
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1754
|
+
/**
|
|
1755
|
+
* Given some some sorted sequences (assumed to be sorted in `direction`) it
|
|
1756
|
+
* merges them all together until we're left with just a list sorted in
|
|
1757
|
+
* ascending order.
|
|
1758
|
+
*
|
|
1759
|
+
* @ignore
|
|
1760
|
+
*/
|
|
1761
|
+
function merge_all(loop$sequences, loop$direction, loop$compare) {
|
|
1762
|
+
while (true) {
|
|
1763
|
+
let sequences = loop$sequences;
|
|
1764
|
+
let direction = loop$direction;
|
|
1765
|
+
let compare = loop$compare;
|
|
1766
|
+
if (sequences instanceof $Empty) {
|
|
1767
|
+
return sequences;
|
|
1768
|
+
} else if (direction instanceof Ascending) {
|
|
1769
|
+
let $ = sequences.tail;
|
|
1770
|
+
if ($ instanceof $Empty) {
|
|
1771
|
+
let sequence = sequences.head;
|
|
1772
|
+
return sequence;
|
|
1773
|
+
} else {
|
|
1774
|
+
let sequences$1 = merge_ascending_pairs(sequences, compare, toList([]));
|
|
1775
|
+
loop$sequences = sequences$1;
|
|
1776
|
+
loop$direction = new Descending();
|
|
1777
|
+
loop$compare = compare;
|
|
1778
|
+
}
|
|
1779
|
+
} else {
|
|
1780
|
+
let $ = sequences.tail;
|
|
1781
|
+
if ($ instanceof $Empty) {
|
|
1782
|
+
let sequence = sequences.head;
|
|
1783
|
+
return reverse(sequence);
|
|
1784
|
+
} else {
|
|
1785
|
+
let sequences$1 = merge_descending_pairs(sequences, compare, toList([]));
|
|
1786
|
+
loop$sequences = sequences$1;
|
|
1787
|
+
loop$direction = new Ascending();
|
|
1788
|
+
loop$compare = compare;
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
|
|
1794
|
+
/**
|
|
1795
|
+
* Sorts from smallest to largest based upon the ordering specified by a given
|
|
1796
|
+
* function.
|
|
1797
|
+
*
|
|
1798
|
+
* ## Examples
|
|
1799
|
+
*
|
|
1800
|
+
* ```gleam
|
|
1801
|
+
* import gleam/int
|
|
1802
|
+
*
|
|
1803
|
+
* assert sort([4, 3, 6, 5, 4, 1, 2], by: int.compare) == [1, 2, 3, 4, 4, 5, 6]
|
|
1804
|
+
* ```
|
|
1805
|
+
*/
|
|
1806
|
+
export function sort(list, compare) {
|
|
1807
|
+
if (list instanceof $Empty) {
|
|
1808
|
+
return list;
|
|
1809
|
+
} else {
|
|
1810
|
+
let $ = list.tail;
|
|
1811
|
+
if ($ instanceof $Empty) {
|
|
1812
|
+
return list;
|
|
1813
|
+
} else {
|
|
1814
|
+
let x = list.head;
|
|
1815
|
+
let y = $.head;
|
|
1816
|
+
let rest$1 = $.tail;
|
|
1817
|
+
let _block;
|
|
1818
|
+
let $1 = compare(x, y);
|
|
1819
|
+
if ($1 instanceof $order.Lt) {
|
|
1820
|
+
_block = new Ascending();
|
|
1821
|
+
} else if ($1 instanceof $order.Eq) {
|
|
1822
|
+
_block = new Ascending();
|
|
1823
|
+
} else {
|
|
1824
|
+
_block = new Descending();
|
|
1825
|
+
}
|
|
1826
|
+
let direction = _block;
|
|
1827
|
+
let sequences$1 = sequences(
|
|
1828
|
+
rest$1,
|
|
1829
|
+
compare,
|
|
1830
|
+
toList([x]),
|
|
1831
|
+
direction,
|
|
1832
|
+
y,
|
|
1833
|
+
toList([]),
|
|
1834
|
+
);
|
|
1835
|
+
return merge_all(sequences$1, new Ascending(), compare);
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
|
|
1840
|
+
function range_loop(loop$start, loop$stop, loop$acc) {
|
|
1841
|
+
while (true) {
|
|
1842
|
+
let start = loop$start;
|
|
1843
|
+
let stop = loop$stop;
|
|
1844
|
+
let acc = loop$acc;
|
|
1845
|
+
let $ = $int.compare(start, stop);
|
|
1846
|
+
if ($ instanceof $order.Lt) {
|
|
1847
|
+
loop$start = start;
|
|
1848
|
+
loop$stop = stop - 1;
|
|
1849
|
+
loop$acc = listPrepend(stop, acc);
|
|
1850
|
+
} else if ($ instanceof $order.Eq) {
|
|
1851
|
+
return listPrepend(stop, acc);
|
|
1852
|
+
} else {
|
|
1853
|
+
loop$start = start;
|
|
1854
|
+
loop$stop = stop + 1;
|
|
1855
|
+
loop$acc = listPrepend(stop, acc);
|
|
1856
|
+
}
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
|
|
1860
|
+
export function range(start, stop) {
|
|
1861
|
+
return range_loop(start, stop, toList([]));
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
function repeat_loop(loop$item, loop$times, loop$acc) {
|
|
1865
|
+
while (true) {
|
|
1866
|
+
let item = loop$item;
|
|
1867
|
+
let times = loop$times;
|
|
1868
|
+
let acc = loop$acc;
|
|
1869
|
+
let $ = times <= 0;
|
|
1870
|
+
if ($) {
|
|
1871
|
+
return acc;
|
|
1872
|
+
} else {
|
|
1873
|
+
loop$item = item;
|
|
1874
|
+
loop$times = times - 1;
|
|
1875
|
+
loop$acc = listPrepend(item, acc);
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1880
|
+
/**
|
|
1881
|
+
* Builds a list of a given value a given number of times.
|
|
1882
|
+
*
|
|
1883
|
+
* ## Examples
|
|
1884
|
+
*
|
|
1885
|
+
* ```gleam
|
|
1886
|
+
* assert repeat("a", times: 0) == []
|
|
1887
|
+
* ```
|
|
1888
|
+
*
|
|
1889
|
+
* ```gleam
|
|
1890
|
+
* assert repeat("a", times: 5) == ["a", "a", "a", "a", "a"]
|
|
1891
|
+
* ```
|
|
1892
|
+
*/
|
|
1893
|
+
export function repeat(a, times) {
|
|
1894
|
+
return repeat_loop(a, times, toList([]));
|
|
1895
|
+
}
|
|
1896
|
+
|
|
1897
|
+
function split_loop(loop$list, loop$n, loop$taken) {
|
|
1898
|
+
while (true) {
|
|
1899
|
+
let list = loop$list;
|
|
1900
|
+
let n = loop$n;
|
|
1901
|
+
let taken = loop$taken;
|
|
1902
|
+
let $ = n <= 0;
|
|
1903
|
+
if ($) {
|
|
1904
|
+
return [reverse(taken), list];
|
|
1905
|
+
} else {
|
|
1906
|
+
if (list instanceof $Empty) {
|
|
1907
|
+
return [reverse(taken), toList([])];
|
|
1908
|
+
} else {
|
|
1909
|
+
let first$1 = list.head;
|
|
1910
|
+
let rest$1 = list.tail;
|
|
1911
|
+
loop$list = rest$1;
|
|
1912
|
+
loop$n = n - 1;
|
|
1913
|
+
loop$taken = listPrepend(first$1, taken);
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1919
|
+
/**
|
|
1920
|
+
* Splits a list in two before the given index.
|
|
1921
|
+
*
|
|
1922
|
+
* If the list is not long enough to have the given index the before list will
|
|
1923
|
+
* be the input list, and the after list will be empty.
|
|
1924
|
+
*
|
|
1925
|
+
* ## Examples
|
|
1926
|
+
*
|
|
1927
|
+
* ```gleam
|
|
1928
|
+
* assert split([6, 7, 8, 9], 0) == #([], [6, 7, 8, 9])
|
|
1929
|
+
* ```
|
|
1930
|
+
*
|
|
1931
|
+
* ```gleam
|
|
1932
|
+
* assert split([6, 7, 8, 9], 2) == #([6, 7], [8, 9])
|
|
1933
|
+
* ```
|
|
1934
|
+
*
|
|
1935
|
+
* ```gleam
|
|
1936
|
+
* assert split([6, 7, 8, 9], 4) == #([6, 7, 8, 9], [])
|
|
1937
|
+
* ```
|
|
1938
|
+
*/
|
|
1939
|
+
export function split(list, index) {
|
|
1940
|
+
return split_loop(list, index, toList([]));
|
|
1941
|
+
}
|
|
1942
|
+
|
|
1943
|
+
function split_while_loop(loop$list, loop$f, loop$acc) {
|
|
1944
|
+
while (true) {
|
|
1945
|
+
let list = loop$list;
|
|
1946
|
+
let f = loop$f;
|
|
1947
|
+
let acc = loop$acc;
|
|
1948
|
+
if (list instanceof $Empty) {
|
|
1949
|
+
return [reverse(acc), toList([])];
|
|
1950
|
+
} else {
|
|
1951
|
+
let first$1 = list.head;
|
|
1952
|
+
let rest$1 = list.tail;
|
|
1953
|
+
let $ = f(first$1);
|
|
1954
|
+
if ($) {
|
|
1955
|
+
loop$list = rest$1;
|
|
1956
|
+
loop$f = f;
|
|
1957
|
+
loop$acc = listPrepend(first$1, acc);
|
|
1958
|
+
} else {
|
|
1959
|
+
return [reverse(acc), list];
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1965
|
+
/**
|
|
1966
|
+
* Splits a list in two before the first element that a given function returns
|
|
1967
|
+
* `False` for.
|
|
1968
|
+
*
|
|
1969
|
+
* If the function returns `True` for all elements the first list will be the
|
|
1970
|
+
* input list, and the second list will be empty.
|
|
1971
|
+
*
|
|
1972
|
+
* ## Examples
|
|
1973
|
+
*
|
|
1974
|
+
* ```gleam
|
|
1975
|
+
* assert split_while([1, 2, 3, 4, 5], fn(x) { x <= 3 })
|
|
1976
|
+
* == #([1, 2, 3], [4, 5])
|
|
1977
|
+
* ```
|
|
1978
|
+
*
|
|
1979
|
+
* ```gleam
|
|
1980
|
+
* assert split_while([1, 2, 3, 4, 5], fn(x) { x <= 5 })
|
|
1981
|
+
* == #([1, 2, 3, 4, 5], [])
|
|
1982
|
+
* ```
|
|
1983
|
+
*/
|
|
1984
|
+
export function split_while(list, predicate) {
|
|
1985
|
+
return split_while_loop(list, predicate, toList([]));
|
|
1986
|
+
}
|
|
1987
|
+
|
|
1988
|
+
/**
|
|
1989
|
+
* Given a list of 2-element tuples, finds the first tuple that has a given
|
|
1990
|
+
* key as the first element and returns the second element.
|
|
1991
|
+
*
|
|
1992
|
+
* If no tuple is found with the given key then `Error(Nil)` is returned.
|
|
1993
|
+
*
|
|
1994
|
+
* This function may be useful for interacting with Erlang code where lists of
|
|
1995
|
+
* tuples are common.
|
|
1996
|
+
*
|
|
1997
|
+
* ## Examples
|
|
1998
|
+
*
|
|
1999
|
+
* ```gleam
|
|
2000
|
+
* assert key_find([#("a", 0), #("b", 1)], "a") == Ok(0)
|
|
2001
|
+
* ```
|
|
2002
|
+
*
|
|
2003
|
+
* ```gleam
|
|
2004
|
+
* assert key_find([#("a", 0), #("b", 1)], "b") == Ok(1)
|
|
2005
|
+
* ```
|
|
2006
|
+
*
|
|
2007
|
+
* ```gleam
|
|
2008
|
+
* assert key_find([#("a", 0), #("b", 1)], "c") == Error(Nil)
|
|
2009
|
+
* ```
|
|
2010
|
+
*/
|
|
2011
|
+
export function key_find(keyword_list, desired_key) {
|
|
2012
|
+
return find_map(
|
|
2013
|
+
keyword_list,
|
|
2014
|
+
(keyword) => {
|
|
2015
|
+
let key;
|
|
2016
|
+
let value;
|
|
2017
|
+
key = keyword[0];
|
|
2018
|
+
value = keyword[1];
|
|
2019
|
+
let $ = isEqual(key, desired_key);
|
|
2020
|
+
if ($) {
|
|
2021
|
+
return new Ok(value);
|
|
2022
|
+
} else {
|
|
2023
|
+
return new Error(undefined);
|
|
2024
|
+
}
|
|
2025
|
+
},
|
|
2026
|
+
);
|
|
2027
|
+
}
|
|
2028
|
+
|
|
2029
|
+
/**
|
|
2030
|
+
* Given a list of 2-element tuples, finds all tuples that have a given
|
|
2031
|
+
* key as the first element and returns the second element.
|
|
2032
|
+
*
|
|
2033
|
+
* This function may be useful for interacting with Erlang code where lists of
|
|
2034
|
+
* tuples are common.
|
|
2035
|
+
*
|
|
2036
|
+
* ## Examples
|
|
2037
|
+
*
|
|
2038
|
+
* ```gleam
|
|
2039
|
+
* assert key_filter([#("a", 0), #("b", 1), #("a", 2)], "a") == [0, 2]
|
|
2040
|
+
* ```
|
|
2041
|
+
*
|
|
2042
|
+
* ```gleam
|
|
2043
|
+
* assert key_filter([#("a", 0), #("b", 1)], "c") == []
|
|
2044
|
+
* ```
|
|
2045
|
+
*/
|
|
2046
|
+
export function key_filter(keyword_list, desired_key) {
|
|
2047
|
+
return filter_map(
|
|
2048
|
+
keyword_list,
|
|
2049
|
+
(keyword) => {
|
|
2050
|
+
let key;
|
|
2051
|
+
let value;
|
|
2052
|
+
key = keyword[0];
|
|
2053
|
+
value = keyword[1];
|
|
2054
|
+
let $ = isEqual(key, desired_key);
|
|
2055
|
+
if ($) {
|
|
2056
|
+
return new Ok(value);
|
|
2057
|
+
} else {
|
|
2058
|
+
return new Error(undefined);
|
|
2059
|
+
}
|
|
2060
|
+
},
|
|
2061
|
+
);
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
function key_pop_loop(loop$list, loop$key, loop$checked) {
|
|
2065
|
+
while (true) {
|
|
2066
|
+
let list = loop$list;
|
|
2067
|
+
let key = loop$key;
|
|
2068
|
+
let checked = loop$checked;
|
|
2069
|
+
if (list instanceof $Empty) {
|
|
2070
|
+
return new Error(undefined);
|
|
2071
|
+
} else {
|
|
2072
|
+
let k = list.head[0];
|
|
2073
|
+
if (isEqual(k, key)) {
|
|
2074
|
+
let rest$1 = list.tail;
|
|
2075
|
+
let v = list.head[1];
|
|
2076
|
+
return new Ok([v, reverse_and_prepend(checked, rest$1)]);
|
|
2077
|
+
} else {
|
|
2078
|
+
let first$1 = list.head;
|
|
2079
|
+
let rest$1 = list.tail;
|
|
2080
|
+
loop$list = rest$1;
|
|
2081
|
+
loop$key = key;
|
|
2082
|
+
loop$checked = listPrepend(first$1, checked);
|
|
2083
|
+
}
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
|
|
2088
|
+
/**
|
|
2089
|
+
* Given a list of 2-element tuples, finds the first tuple that has a given
|
|
2090
|
+
* key as the first element. This function will return the second element
|
|
2091
|
+
* of the found tuple and list with tuple removed.
|
|
2092
|
+
*
|
|
2093
|
+
* If no tuple is found with the given key then `Error(Nil)` is returned.
|
|
2094
|
+
*
|
|
2095
|
+
* ## Examples
|
|
2096
|
+
*
|
|
2097
|
+
* ```gleam
|
|
2098
|
+
* assert key_pop([#("a", 0), #("b", 1)], "a") == Ok(#(0, [#("b", 1)]))
|
|
2099
|
+
* ```
|
|
2100
|
+
*
|
|
2101
|
+
* ```gleam
|
|
2102
|
+
* assert key_pop([#("a", 0), #("b", 1)], "b") == Ok(#(1, [#("a", 0)]))
|
|
2103
|
+
* ```
|
|
2104
|
+
*
|
|
2105
|
+
* ```gleam
|
|
2106
|
+
* assert key_pop([#("a", 0), #("b", 1)], "c") == Error(Nil)
|
|
2107
|
+
* ```
|
|
2108
|
+
*/
|
|
2109
|
+
export function key_pop(list, key) {
|
|
2110
|
+
return key_pop_loop(list, key, toList([]));
|
|
2111
|
+
}
|
|
2112
|
+
|
|
2113
|
+
function key_set_loop(loop$list, loop$key, loop$value, loop$inspected) {
|
|
2114
|
+
while (true) {
|
|
2115
|
+
let list = loop$list;
|
|
2116
|
+
let key = loop$key;
|
|
2117
|
+
let value = loop$value;
|
|
2118
|
+
let inspected = loop$inspected;
|
|
2119
|
+
if (list instanceof $Empty) {
|
|
2120
|
+
return reverse(listPrepend([key, value], inspected));
|
|
2121
|
+
} else {
|
|
2122
|
+
let k = list.head[0];
|
|
2123
|
+
if (isEqual(k, key)) {
|
|
2124
|
+
let rest$1 = list.tail;
|
|
2125
|
+
return reverse_and_prepend(inspected, listPrepend([k, value], rest$1));
|
|
2126
|
+
} else {
|
|
2127
|
+
let first$1 = list.head;
|
|
2128
|
+
let rest$1 = list.tail;
|
|
2129
|
+
loop$list = rest$1;
|
|
2130
|
+
loop$key = key;
|
|
2131
|
+
loop$value = value;
|
|
2132
|
+
loop$inspected = listPrepend(first$1, inspected);
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
}
|
|
2137
|
+
|
|
2138
|
+
/**
|
|
2139
|
+
* Given a list of 2-element tuples, inserts a key and value into the list.
|
|
2140
|
+
*
|
|
2141
|
+
* If there was already a tuple with the key then it is replaced, otherwise it
|
|
2142
|
+
* is added to the end of the list.
|
|
2143
|
+
*
|
|
2144
|
+
* ## Examples
|
|
2145
|
+
*
|
|
2146
|
+
* ```gleam
|
|
2147
|
+
* assert key_set([#(5, 0), #(4, 1)], 4, 100) == [#(5, 0), #(4, 100)]
|
|
2148
|
+
* ```
|
|
2149
|
+
*
|
|
2150
|
+
* ```gleam
|
|
2151
|
+
* assert key_set([#(5, 0), #(4, 1)], 1, 100) == [#(5, 0), #(4, 1), #(1, 100)]
|
|
2152
|
+
* ```
|
|
2153
|
+
*/
|
|
2154
|
+
export function key_set(list, key, value) {
|
|
2155
|
+
return key_set_loop(list, key, value, toList([]));
|
|
2156
|
+
}
|
|
2157
|
+
|
|
2158
|
+
/**
|
|
2159
|
+
* Calls a function for each element in a list, discarding the return value.
|
|
2160
|
+
*
|
|
2161
|
+
* Useful for calling a side effect for every item of a list.
|
|
2162
|
+
*
|
|
2163
|
+
* ```gleam
|
|
2164
|
+
* import gleam/io
|
|
2165
|
+
*
|
|
2166
|
+
* assert each(["1", "2", "3"], io.println) == Nil
|
|
2167
|
+
* // 1
|
|
2168
|
+
* // 2
|
|
2169
|
+
* // 3
|
|
2170
|
+
* ```
|
|
2171
|
+
*/
|
|
2172
|
+
export function each(loop$list, loop$f) {
|
|
2173
|
+
while (true) {
|
|
2174
|
+
let list = loop$list;
|
|
2175
|
+
let f = loop$f;
|
|
2176
|
+
if (list instanceof $Empty) {
|
|
2177
|
+
return undefined;
|
|
2178
|
+
} else {
|
|
2179
|
+
let first$1 = list.head;
|
|
2180
|
+
let rest$1 = list.tail;
|
|
2181
|
+
f(first$1);
|
|
2182
|
+
loop$list = rest$1;
|
|
2183
|
+
loop$f = f;
|
|
2184
|
+
}
|
|
2185
|
+
}
|
|
2186
|
+
}
|
|
2187
|
+
|
|
2188
|
+
/**
|
|
2189
|
+
* Calls a `Result` returning function for each element in a list, discarding
|
|
2190
|
+
* the return value. If the function returns `Error` then the iteration is
|
|
2191
|
+
* stopped and the error is returned.
|
|
2192
|
+
*
|
|
2193
|
+
* Useful for calling a side effect for every item of a list.
|
|
2194
|
+
*
|
|
2195
|
+
* ## Examples
|
|
2196
|
+
*
|
|
2197
|
+
* ```gleam
|
|
2198
|
+
* assert
|
|
2199
|
+
* try_each(
|
|
2200
|
+
* over: [1, 2, 3],
|
|
2201
|
+
* with: function_that_might_fail,
|
|
2202
|
+
* )
|
|
2203
|
+
* == Ok(Nil)
|
|
2204
|
+
* ```
|
|
2205
|
+
*/
|
|
2206
|
+
export function try_each(loop$list, loop$fun) {
|
|
2207
|
+
while (true) {
|
|
2208
|
+
let list = loop$list;
|
|
2209
|
+
let fun = loop$fun;
|
|
2210
|
+
if (list instanceof $Empty) {
|
|
2211
|
+
return new Ok(undefined);
|
|
2212
|
+
} else {
|
|
2213
|
+
let first$1 = list.head;
|
|
2214
|
+
let rest$1 = list.tail;
|
|
2215
|
+
let $ = fun(first$1);
|
|
2216
|
+
if ($ instanceof Ok) {
|
|
2217
|
+
loop$list = rest$1;
|
|
2218
|
+
loop$fun = fun;
|
|
2219
|
+
} else {
|
|
2220
|
+
return $;
|
|
2221
|
+
}
|
|
2222
|
+
}
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2226
|
+
function partition_loop(loop$list, loop$categorise, loop$trues, loop$falses) {
|
|
2227
|
+
while (true) {
|
|
2228
|
+
let list = loop$list;
|
|
2229
|
+
let categorise = loop$categorise;
|
|
2230
|
+
let trues = loop$trues;
|
|
2231
|
+
let falses = loop$falses;
|
|
2232
|
+
if (list instanceof $Empty) {
|
|
2233
|
+
return [reverse(trues), reverse(falses)];
|
|
2234
|
+
} else {
|
|
2235
|
+
let first$1 = list.head;
|
|
2236
|
+
let rest$1 = list.tail;
|
|
2237
|
+
let $ = categorise(first$1);
|
|
2238
|
+
if ($) {
|
|
2239
|
+
loop$list = rest$1;
|
|
2240
|
+
loop$categorise = categorise;
|
|
2241
|
+
loop$trues = listPrepend(first$1, trues);
|
|
2242
|
+
loop$falses = falses;
|
|
2243
|
+
} else {
|
|
2244
|
+
loop$list = rest$1;
|
|
2245
|
+
loop$categorise = categorise;
|
|
2246
|
+
loop$trues = trues;
|
|
2247
|
+
loop$falses = listPrepend(first$1, falses);
|
|
2248
|
+
}
|
|
2249
|
+
}
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2252
|
+
|
|
2253
|
+
/**
|
|
2254
|
+
* Partitions a list into a tuple/pair of lists
|
|
2255
|
+
* by a given categorisation function.
|
|
2256
|
+
*
|
|
2257
|
+
* ## Examples
|
|
2258
|
+
*
|
|
2259
|
+
* ```gleam
|
|
2260
|
+
* import gleam/int
|
|
2261
|
+
*
|
|
2262
|
+
* assert [1, 2, 3, 4, 5] |> partition(int.is_odd) == #([1, 3, 5], [2, 4])
|
|
2263
|
+
* ```
|
|
2264
|
+
*/
|
|
2265
|
+
export function partition(list, categorise) {
|
|
2266
|
+
return partition_loop(list, categorise, toList([]), toList([]));
|
|
2267
|
+
}
|
|
2268
|
+
|
|
2269
|
+
function window_loop(loop$acc, loop$list, loop$n) {
|
|
2270
|
+
while (true) {
|
|
2271
|
+
let acc = loop$acc;
|
|
2272
|
+
let list = loop$list;
|
|
2273
|
+
let n = loop$n;
|
|
2274
|
+
let window$1 = take(list, n);
|
|
2275
|
+
let $ = length(window$1) === n;
|
|
2276
|
+
if ($) {
|
|
2277
|
+
loop$acc = listPrepend(window$1, acc);
|
|
2278
|
+
loop$list = drop(list, 1);
|
|
2279
|
+
loop$n = n;
|
|
2280
|
+
} else {
|
|
2281
|
+
return reverse(acc);
|
|
2282
|
+
}
|
|
2283
|
+
}
|
|
2284
|
+
}
|
|
2285
|
+
|
|
2286
|
+
/**
|
|
2287
|
+
* Returns a list of sliding windows.
|
|
2288
|
+
*
|
|
2289
|
+
* ## Examples
|
|
2290
|
+
*
|
|
2291
|
+
* ```gleam
|
|
2292
|
+
* assert window([1,2,3,4,5], 3) == [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
|
|
2293
|
+
* ```
|
|
2294
|
+
*
|
|
2295
|
+
* ```gleam
|
|
2296
|
+
* assert window([1, 2], 4) == []
|
|
2297
|
+
* ```
|
|
2298
|
+
*/
|
|
2299
|
+
export function window(list, n) {
|
|
2300
|
+
let $ = n <= 0;
|
|
2301
|
+
if ($) {
|
|
2302
|
+
return toList([]);
|
|
2303
|
+
} else {
|
|
2304
|
+
return window_loop(toList([]), list, n);
|
|
2305
|
+
}
|
|
2306
|
+
}
|
|
2307
|
+
|
|
2308
|
+
/**
|
|
2309
|
+
* Returns a list of tuples containing two contiguous elements.
|
|
2310
|
+
*
|
|
2311
|
+
* ## Examples
|
|
2312
|
+
*
|
|
2313
|
+
* ```gleam
|
|
2314
|
+
* assert window_by_2([1,2,3,4]) == [#(1, 2), #(2, 3), #(3, 4)]
|
|
2315
|
+
* ```
|
|
2316
|
+
*
|
|
2317
|
+
* ```gleam
|
|
2318
|
+
* assert window_by_2([1]) == []
|
|
2319
|
+
* ```
|
|
2320
|
+
*/
|
|
2321
|
+
export function window_by_2(list) {
|
|
2322
|
+
return zip(list, drop(list, 1));
|
|
2323
|
+
}
|
|
2324
|
+
|
|
2325
|
+
/**
|
|
2326
|
+
* Drops the first elements in a given list for which the predicate function returns `True`.
|
|
2327
|
+
*
|
|
2328
|
+
* ## Examples
|
|
2329
|
+
*
|
|
2330
|
+
* ```gleam
|
|
2331
|
+
* assert drop_while([1, 2, 3, 4], fn (x) { x < 3 }) == [3, 4]
|
|
2332
|
+
* ```
|
|
2333
|
+
*/
|
|
2334
|
+
export function drop_while(loop$list, loop$predicate) {
|
|
2335
|
+
while (true) {
|
|
2336
|
+
let list = loop$list;
|
|
2337
|
+
let predicate = loop$predicate;
|
|
2338
|
+
if (list instanceof $Empty) {
|
|
2339
|
+
return list;
|
|
2340
|
+
} else {
|
|
2341
|
+
let first$1 = list.head;
|
|
2342
|
+
let rest$1 = list.tail;
|
|
2343
|
+
let $ = predicate(first$1);
|
|
2344
|
+
if ($) {
|
|
2345
|
+
loop$list = rest$1;
|
|
2346
|
+
loop$predicate = predicate;
|
|
2347
|
+
} else {
|
|
2348
|
+
return listPrepend(first$1, rest$1);
|
|
2349
|
+
}
|
|
2350
|
+
}
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
|
|
2354
|
+
function take_while_loop(loop$list, loop$predicate, loop$acc) {
|
|
2355
|
+
while (true) {
|
|
2356
|
+
let list = loop$list;
|
|
2357
|
+
let predicate = loop$predicate;
|
|
2358
|
+
let acc = loop$acc;
|
|
2359
|
+
if (list instanceof $Empty) {
|
|
2360
|
+
return reverse(acc);
|
|
2361
|
+
} else {
|
|
2362
|
+
let first$1 = list.head;
|
|
2363
|
+
let rest$1 = list.tail;
|
|
2364
|
+
let $ = predicate(first$1);
|
|
2365
|
+
if ($) {
|
|
2366
|
+
loop$list = rest$1;
|
|
2367
|
+
loop$predicate = predicate;
|
|
2368
|
+
loop$acc = listPrepend(first$1, acc);
|
|
2369
|
+
} else {
|
|
2370
|
+
return reverse(acc);
|
|
2371
|
+
}
|
|
2372
|
+
}
|
|
2373
|
+
}
|
|
2374
|
+
}
|
|
2375
|
+
|
|
2376
|
+
/**
|
|
2377
|
+
* Takes the first elements in a given list for which the predicate function returns `True`.
|
|
2378
|
+
*
|
|
2379
|
+
* ## Examples
|
|
2380
|
+
*
|
|
2381
|
+
* ```gleam
|
|
2382
|
+
* assert take_while([1, 2, 3, 2, 4], fn (x) { x < 3 }) == [1, 2]
|
|
2383
|
+
* ```
|
|
2384
|
+
*/
|
|
2385
|
+
export function take_while(list, predicate) {
|
|
2386
|
+
return take_while_loop(list, predicate, toList([]));
|
|
2387
|
+
}
|
|
2388
|
+
|
|
2389
|
+
function chunk_loop(
|
|
2390
|
+
loop$list,
|
|
2391
|
+
loop$f,
|
|
2392
|
+
loop$previous_key,
|
|
2393
|
+
loop$current_chunk,
|
|
2394
|
+
loop$acc
|
|
2395
|
+
) {
|
|
2396
|
+
while (true) {
|
|
2397
|
+
let list = loop$list;
|
|
2398
|
+
let f = loop$f;
|
|
2399
|
+
let previous_key = loop$previous_key;
|
|
2400
|
+
let current_chunk = loop$current_chunk;
|
|
2401
|
+
let acc = loop$acc;
|
|
2402
|
+
if (list instanceof $Empty) {
|
|
2403
|
+
return reverse(listPrepend(reverse(current_chunk), acc));
|
|
2404
|
+
} else {
|
|
2405
|
+
let first$1 = list.head;
|
|
2406
|
+
let rest$1 = list.tail;
|
|
2407
|
+
let key = f(first$1);
|
|
2408
|
+
let $ = isEqual(key, previous_key);
|
|
2409
|
+
if ($) {
|
|
2410
|
+
loop$list = rest$1;
|
|
2411
|
+
loop$f = f;
|
|
2412
|
+
loop$previous_key = key;
|
|
2413
|
+
loop$current_chunk = listPrepend(first$1, current_chunk);
|
|
2414
|
+
loop$acc = acc;
|
|
2415
|
+
} else {
|
|
2416
|
+
let new_acc = listPrepend(reverse(current_chunk), acc);
|
|
2417
|
+
loop$list = rest$1;
|
|
2418
|
+
loop$f = f;
|
|
2419
|
+
loop$previous_key = key;
|
|
2420
|
+
loop$current_chunk = toList([first$1]);
|
|
2421
|
+
loop$acc = new_acc;
|
|
2422
|
+
}
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2426
|
+
|
|
2427
|
+
/**
|
|
2428
|
+
* Returns a list of chunks in which
|
|
2429
|
+
* the return value of calling `f` on each element is the same.
|
|
2430
|
+
*
|
|
2431
|
+
* ## Examples
|
|
2432
|
+
*
|
|
2433
|
+
* ```gleam
|
|
2434
|
+
* assert [1, 2, 2, 3, 4, 4, 6, 7, 7] |> chunk(by: fn(n) { n % 2 })
|
|
2435
|
+
* == [[1], [2, 2], [3], [4, 4, 6], [7, 7]]
|
|
2436
|
+
* ```
|
|
2437
|
+
*/
|
|
2438
|
+
export function chunk(list, f) {
|
|
2439
|
+
if (list instanceof $Empty) {
|
|
2440
|
+
return list;
|
|
2441
|
+
} else {
|
|
2442
|
+
let first$1 = list.head;
|
|
2443
|
+
let rest$1 = list.tail;
|
|
2444
|
+
return chunk_loop(rest$1, f, f(first$1), toList([first$1]), toList([]));
|
|
2445
|
+
}
|
|
2446
|
+
}
|
|
2447
|
+
|
|
2448
|
+
function sized_chunk_loop(
|
|
2449
|
+
loop$list,
|
|
2450
|
+
loop$count,
|
|
2451
|
+
loop$left,
|
|
2452
|
+
loop$current_chunk,
|
|
2453
|
+
loop$acc
|
|
2454
|
+
) {
|
|
2455
|
+
while (true) {
|
|
2456
|
+
let list = loop$list;
|
|
2457
|
+
let count = loop$count;
|
|
2458
|
+
let left = loop$left;
|
|
2459
|
+
let current_chunk = loop$current_chunk;
|
|
2460
|
+
let acc = loop$acc;
|
|
2461
|
+
if (list instanceof $Empty) {
|
|
2462
|
+
if (current_chunk instanceof $Empty) {
|
|
2463
|
+
return reverse(acc);
|
|
2464
|
+
} else {
|
|
2465
|
+
let remaining = current_chunk;
|
|
2466
|
+
return reverse(listPrepend(reverse(remaining), acc));
|
|
2467
|
+
}
|
|
2468
|
+
} else {
|
|
2469
|
+
let first$1 = list.head;
|
|
2470
|
+
let rest$1 = list.tail;
|
|
2471
|
+
let chunk$1 = listPrepend(first$1, current_chunk);
|
|
2472
|
+
let $ = left > 1;
|
|
2473
|
+
if ($) {
|
|
2474
|
+
loop$list = rest$1;
|
|
2475
|
+
loop$count = count;
|
|
2476
|
+
loop$left = left - 1;
|
|
2477
|
+
loop$current_chunk = chunk$1;
|
|
2478
|
+
loop$acc = acc;
|
|
2479
|
+
} else {
|
|
2480
|
+
loop$list = rest$1;
|
|
2481
|
+
loop$count = count;
|
|
2482
|
+
loop$left = count;
|
|
2483
|
+
loop$current_chunk = toList([]);
|
|
2484
|
+
loop$acc = listPrepend(reverse(chunk$1), acc);
|
|
2485
|
+
}
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
}
|
|
2489
|
+
|
|
2490
|
+
/**
|
|
2491
|
+
* Returns a list of chunks containing `count` elements each.
|
|
2492
|
+
*
|
|
2493
|
+
* If the last chunk does not have `count` elements, it is instead
|
|
2494
|
+
* a partial chunk, with less than `count` elements.
|
|
2495
|
+
*
|
|
2496
|
+
* For any `count` less than 1 this function behaves as if it was set to 1.
|
|
2497
|
+
*
|
|
2498
|
+
* ## Examples
|
|
2499
|
+
*
|
|
2500
|
+
* ```gleam
|
|
2501
|
+
* assert [1, 2, 3, 4, 5, 6] |> sized_chunk(into: 2)
|
|
2502
|
+
* == [[1, 2], [3, 4], [5, 6]]
|
|
2503
|
+
* ```
|
|
2504
|
+
*
|
|
2505
|
+
* ```gleam
|
|
2506
|
+
* assert [1, 2, 3, 4, 5, 6, 7, 8] |> sized_chunk(into: 3)
|
|
2507
|
+
* == [[1, 2, 3], [4, 5, 6], [7, 8]]
|
|
2508
|
+
* ```
|
|
2509
|
+
*/
|
|
2510
|
+
export function sized_chunk(list, count) {
|
|
2511
|
+
return sized_chunk_loop(list, count, count, toList([]), toList([]));
|
|
2512
|
+
}
|
|
2513
|
+
|
|
2514
|
+
/**
|
|
2515
|
+
* This function acts similar to fold, but does not take an initial state.
|
|
2516
|
+
* Instead, it starts from the first element in the list
|
|
2517
|
+
* and combines it with each subsequent element in turn using the given
|
|
2518
|
+
* function. The function is called as `fun(accumulator, current_element)`.
|
|
2519
|
+
*
|
|
2520
|
+
* Returns `Ok` to indicate a successful run, and `Error` if called on an
|
|
2521
|
+
* empty list.
|
|
2522
|
+
*
|
|
2523
|
+
* ## Examples
|
|
2524
|
+
*
|
|
2525
|
+
* ```gleam
|
|
2526
|
+
* assert [] |> reduce(fn(acc, x) { acc + x }) == Error(Nil)
|
|
2527
|
+
* ```
|
|
2528
|
+
*
|
|
2529
|
+
* ```gleam
|
|
2530
|
+
* assert [1, 2, 3, 4, 5] |> reduce(fn(acc, x) { acc + x }) == Ok(15)
|
|
2531
|
+
* ```
|
|
2532
|
+
*/
|
|
2533
|
+
export function reduce(list, fun) {
|
|
2534
|
+
if (list instanceof $Empty) {
|
|
2535
|
+
return new Error(undefined);
|
|
2536
|
+
} else {
|
|
2537
|
+
let first$1 = list.head;
|
|
2538
|
+
let rest$1 = list.tail;
|
|
2539
|
+
return new Ok(fold(rest$1, first$1, fun));
|
|
2540
|
+
}
|
|
2541
|
+
}
|
|
2542
|
+
|
|
2543
|
+
function scan_loop(loop$list, loop$accumulator, loop$accumulated, loop$fun) {
|
|
2544
|
+
while (true) {
|
|
2545
|
+
let list = loop$list;
|
|
2546
|
+
let accumulator = loop$accumulator;
|
|
2547
|
+
let accumulated = loop$accumulated;
|
|
2548
|
+
let fun = loop$fun;
|
|
2549
|
+
if (list instanceof $Empty) {
|
|
2550
|
+
return reverse(accumulated);
|
|
2551
|
+
} else {
|
|
2552
|
+
let first$1 = list.head;
|
|
2553
|
+
let rest$1 = list.tail;
|
|
2554
|
+
let next = fun(accumulator, first$1);
|
|
2555
|
+
loop$list = rest$1;
|
|
2556
|
+
loop$accumulator = next;
|
|
2557
|
+
loop$accumulated = listPrepend(next, accumulated);
|
|
2558
|
+
loop$fun = fun;
|
|
2559
|
+
}
|
|
2560
|
+
}
|
|
2561
|
+
}
|
|
2562
|
+
|
|
2563
|
+
/**
|
|
2564
|
+
* Similar to `fold`, but yields the state of the accumulator at each stage.
|
|
2565
|
+
*
|
|
2566
|
+
* ## Examples
|
|
2567
|
+
*
|
|
2568
|
+
* ```gleam
|
|
2569
|
+
* assert scan(over: [1, 2, 3], from: 100, with: fn(acc, i) { acc + i })
|
|
2570
|
+
* == [101, 103, 106]
|
|
2571
|
+
* ```
|
|
2572
|
+
*/
|
|
2573
|
+
export function scan(list, initial, fun) {
|
|
2574
|
+
return scan_loop(list, initial, toList([]), fun);
|
|
2575
|
+
}
|
|
2576
|
+
|
|
2577
|
+
/**
|
|
2578
|
+
* Returns the last element in the given list.
|
|
2579
|
+
*
|
|
2580
|
+
* Returns `Error(Nil)` if the list is empty.
|
|
2581
|
+
*
|
|
2582
|
+
* This function runs in linear time.
|
|
2583
|
+
*
|
|
2584
|
+
* ## Examples
|
|
2585
|
+
*
|
|
2586
|
+
* ```gleam
|
|
2587
|
+
* assert last([]) == Error(Nil)
|
|
2588
|
+
* ```
|
|
2589
|
+
*
|
|
2590
|
+
* ```gleam
|
|
2591
|
+
* assert last([1, 2, 3, 4, 5]) == Ok(5)
|
|
2592
|
+
* ```
|
|
2593
|
+
*/
|
|
2594
|
+
export function last(loop$list) {
|
|
2595
|
+
while (true) {
|
|
2596
|
+
let list = loop$list;
|
|
2597
|
+
if (list instanceof $Empty) {
|
|
2598
|
+
return new Error(undefined);
|
|
2599
|
+
} else {
|
|
2600
|
+
let $ = list.tail;
|
|
2601
|
+
if ($ instanceof $Empty) {
|
|
2602
|
+
let last$1 = list.head;
|
|
2603
|
+
return new Ok(last$1);
|
|
2604
|
+
} else {
|
|
2605
|
+
let rest$1 = $;
|
|
2606
|
+
loop$list = rest$1;
|
|
2607
|
+
}
|
|
2608
|
+
}
|
|
2609
|
+
}
|
|
2610
|
+
}
|
|
2611
|
+
|
|
2612
|
+
/**
|
|
2613
|
+
* Return unique combinations of elements in the list.
|
|
2614
|
+
*
|
|
2615
|
+
* ## Examples
|
|
2616
|
+
*
|
|
2617
|
+
* ```gleam
|
|
2618
|
+
* assert combinations([1, 2, 3], 2) == [[1, 2], [1, 3], [2, 3]]
|
|
2619
|
+
* ```
|
|
2620
|
+
*
|
|
2621
|
+
* ```gleam
|
|
2622
|
+
* assert combinations([1, 2, 3, 4], 3)
|
|
2623
|
+
* == [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]
|
|
2624
|
+
* ```
|
|
2625
|
+
*/
|
|
2626
|
+
export function combinations(items, n) {
|
|
2627
|
+
if (n === 0) {
|
|
2628
|
+
return toList([toList([])]);
|
|
2629
|
+
} else if (items instanceof $Empty) {
|
|
2630
|
+
return items;
|
|
2631
|
+
} else {
|
|
2632
|
+
let first$1 = items.head;
|
|
2633
|
+
let rest$1 = items.tail;
|
|
2634
|
+
let _pipe = rest$1;
|
|
2635
|
+
let _pipe$1 = combinations(_pipe, n - 1);
|
|
2636
|
+
let _pipe$2 = map(
|
|
2637
|
+
_pipe$1,
|
|
2638
|
+
(combination) => { return listPrepend(first$1, combination); },
|
|
2639
|
+
);
|
|
2640
|
+
let _pipe$3 = reverse(_pipe$2);
|
|
2641
|
+
return fold(
|
|
2642
|
+
_pipe$3,
|
|
2643
|
+
combinations(rest$1, n),
|
|
2644
|
+
(acc, c) => { return listPrepend(c, acc); },
|
|
2645
|
+
);
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
|
|
2649
|
+
function combination_pairs_loop(loop$items, loop$acc) {
|
|
2650
|
+
while (true) {
|
|
2651
|
+
let items = loop$items;
|
|
2652
|
+
let acc = loop$acc;
|
|
2653
|
+
if (items instanceof $Empty) {
|
|
2654
|
+
return reverse(acc);
|
|
2655
|
+
} else {
|
|
2656
|
+
let first$1 = items.head;
|
|
2657
|
+
let rest$1 = items.tail;
|
|
2658
|
+
let first_combinations = map(
|
|
2659
|
+
rest$1,
|
|
2660
|
+
(other) => { return [first$1, other]; },
|
|
2661
|
+
);
|
|
2662
|
+
let acc$1 = reverse_and_prepend(first_combinations, acc);
|
|
2663
|
+
loop$items = rest$1;
|
|
2664
|
+
loop$acc = acc$1;
|
|
2665
|
+
}
|
|
2666
|
+
}
|
|
2667
|
+
}
|
|
2668
|
+
|
|
2669
|
+
/**
|
|
2670
|
+
* Return unique pair combinations of elements in the list.
|
|
2671
|
+
*
|
|
2672
|
+
* ## Examples
|
|
2673
|
+
*
|
|
2674
|
+
* ```gleam
|
|
2675
|
+
* assert combination_pairs([1, 2, 3]) == [#(1, 2), #(1, 3), #(2, 3)]
|
|
2676
|
+
* ```
|
|
2677
|
+
*/
|
|
2678
|
+
export function combination_pairs(items) {
|
|
2679
|
+
return combination_pairs_loop(items, toList([]));
|
|
2680
|
+
}
|
|
2681
|
+
|
|
2682
|
+
function take_firsts(loop$rows, loop$column, loop$remaining_rows) {
|
|
2683
|
+
while (true) {
|
|
2684
|
+
let rows = loop$rows;
|
|
2685
|
+
let column = loop$column;
|
|
2686
|
+
let remaining_rows = loop$remaining_rows;
|
|
2687
|
+
if (rows instanceof $Empty) {
|
|
2688
|
+
return [reverse(column), reverse(remaining_rows)];
|
|
2689
|
+
} else {
|
|
2690
|
+
let $ = rows.head;
|
|
2691
|
+
if ($ instanceof $Empty) {
|
|
2692
|
+
let rest$1 = rows.tail;
|
|
2693
|
+
loop$rows = rest$1;
|
|
2694
|
+
loop$column = column;
|
|
2695
|
+
loop$remaining_rows = remaining_rows;
|
|
2696
|
+
} else {
|
|
2697
|
+
let rest_rows = rows.tail;
|
|
2698
|
+
let first$1 = $.head;
|
|
2699
|
+
let remaining_row = $.tail;
|
|
2700
|
+
let remaining_rows$1 = listPrepend(remaining_row, remaining_rows);
|
|
2701
|
+
loop$rows = rest_rows;
|
|
2702
|
+
loop$column = listPrepend(first$1, column);
|
|
2703
|
+
loop$remaining_rows = remaining_rows$1;
|
|
2704
|
+
}
|
|
2705
|
+
}
|
|
2706
|
+
}
|
|
2707
|
+
}
|
|
2708
|
+
|
|
2709
|
+
function transpose_loop(loop$rows, loop$columns) {
|
|
2710
|
+
while (true) {
|
|
2711
|
+
let rows = loop$rows;
|
|
2712
|
+
let columns = loop$columns;
|
|
2713
|
+
if (rows instanceof $Empty) {
|
|
2714
|
+
return reverse(columns);
|
|
2715
|
+
} else {
|
|
2716
|
+
let $ = take_firsts(rows, toList([]), toList([]));
|
|
2717
|
+
let column;
|
|
2718
|
+
let rest$1;
|
|
2719
|
+
column = $[0];
|
|
2720
|
+
rest$1 = $[1];
|
|
2721
|
+
if (column instanceof $Empty) {
|
|
2722
|
+
loop$rows = rest$1;
|
|
2723
|
+
loop$columns = columns;
|
|
2724
|
+
} else {
|
|
2725
|
+
loop$rows = rest$1;
|
|
2726
|
+
loop$columns = listPrepend(column, columns);
|
|
2727
|
+
}
|
|
2728
|
+
}
|
|
2729
|
+
}
|
|
2730
|
+
}
|
|
2731
|
+
|
|
2732
|
+
/**
|
|
2733
|
+
* Transpose rows and columns of the list of lists.
|
|
2734
|
+
*
|
|
2735
|
+
* Notice: This function is not tail recursive,
|
|
2736
|
+
* and thus may exceed stack size if called,
|
|
2737
|
+
* with large lists (on the JavaScript target).
|
|
2738
|
+
*
|
|
2739
|
+
* ## Examples
|
|
2740
|
+
*
|
|
2741
|
+
* ```gleam
|
|
2742
|
+
* assert transpose([[1, 2, 3], [101, 102, 103]])
|
|
2743
|
+
* == [[1, 101], [2, 102], [3, 103]]
|
|
2744
|
+
* ```
|
|
2745
|
+
*/
|
|
2746
|
+
export function transpose(list_of_lists) {
|
|
2747
|
+
return transpose_loop(list_of_lists, toList([]));
|
|
2748
|
+
}
|
|
2749
|
+
|
|
2750
|
+
/**
|
|
2751
|
+
* Make a list alternating the elements from the given lists
|
|
2752
|
+
*
|
|
2753
|
+
* ## Examples
|
|
2754
|
+
*
|
|
2755
|
+
* ```gleam
|
|
2756
|
+
* assert interleave([[1, 2], [101, 102], [201, 202]])
|
|
2757
|
+
* == [1, 101, 201, 2, 102, 202]
|
|
2758
|
+
* ```
|
|
2759
|
+
*/
|
|
2760
|
+
export function interleave(list) {
|
|
2761
|
+
let _pipe = list;
|
|
2762
|
+
let _pipe$1 = transpose(_pipe);
|
|
2763
|
+
return flatten(_pipe$1);
|
|
2764
|
+
}
|
|
2765
|
+
|
|
2766
|
+
function shuffle_pair_unwrap_loop(loop$list, loop$acc) {
|
|
2767
|
+
while (true) {
|
|
2768
|
+
let list = loop$list;
|
|
2769
|
+
let acc = loop$acc;
|
|
2770
|
+
if (list instanceof $Empty) {
|
|
2771
|
+
return acc;
|
|
2772
|
+
} else {
|
|
2773
|
+
let elem_pair = list.head;
|
|
2774
|
+
let enumerable = list.tail;
|
|
2775
|
+
loop$list = enumerable;
|
|
2776
|
+
loop$acc = listPrepend(elem_pair[1], acc);
|
|
2777
|
+
}
|
|
2778
|
+
}
|
|
2779
|
+
}
|
|
2780
|
+
|
|
2781
|
+
function do_shuffle_by_pair_indexes(list_of_pairs) {
|
|
2782
|
+
return sort(
|
|
2783
|
+
list_of_pairs,
|
|
2784
|
+
(a_pair, b_pair) => { return $float.compare(a_pair[0], b_pair[0]); },
|
|
2785
|
+
);
|
|
2786
|
+
}
|
|
2787
|
+
|
|
2788
|
+
/**
|
|
2789
|
+
* Takes a list, randomly sorts all items and returns the shuffled list.
|
|
2790
|
+
*
|
|
2791
|
+
* This function uses `float.random` to decide the order of the elements.
|
|
2792
|
+
*
|
|
2793
|
+
* ## Example
|
|
2794
|
+
*
|
|
2795
|
+
* ```gleam
|
|
2796
|
+
* [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] |> shuffle
|
|
2797
|
+
* // -> [1, 6, 9, 10, 3, 8, 4, 2, 7, 5]
|
|
2798
|
+
* ```
|
|
2799
|
+
*/
|
|
2800
|
+
export function shuffle(list) {
|
|
2801
|
+
let _pipe = list;
|
|
2802
|
+
let _pipe$1 = fold(
|
|
2803
|
+
_pipe,
|
|
2804
|
+
toList([]),
|
|
2805
|
+
(acc, a) => { return listPrepend([$float.random(), a], acc); },
|
|
2806
|
+
);
|
|
2807
|
+
let _pipe$2 = do_shuffle_by_pair_indexes(_pipe$1);
|
|
2808
|
+
return shuffle_pair_unwrap_loop(_pipe$2, toList([]));
|
|
2809
|
+
}
|
|
2810
|
+
|
|
2811
|
+
function max_loop(loop$list, loop$compare, loop$max) {
|
|
2812
|
+
while (true) {
|
|
2813
|
+
let list = loop$list;
|
|
2814
|
+
let compare = loop$compare;
|
|
2815
|
+
let max = loop$max;
|
|
2816
|
+
if (list instanceof $Empty) {
|
|
2817
|
+
return max;
|
|
2818
|
+
} else {
|
|
2819
|
+
let first$1 = list.head;
|
|
2820
|
+
let rest$1 = list.tail;
|
|
2821
|
+
let $ = compare(first$1, max);
|
|
2822
|
+
if ($ instanceof $order.Lt) {
|
|
2823
|
+
loop$list = rest$1;
|
|
2824
|
+
loop$compare = compare;
|
|
2825
|
+
loop$max = max;
|
|
2826
|
+
} else if ($ instanceof $order.Eq) {
|
|
2827
|
+
loop$list = rest$1;
|
|
2828
|
+
loop$compare = compare;
|
|
2829
|
+
loop$max = max;
|
|
2830
|
+
} else {
|
|
2831
|
+
loop$list = rest$1;
|
|
2832
|
+
loop$compare = compare;
|
|
2833
|
+
loop$max = first$1;
|
|
2834
|
+
}
|
|
2835
|
+
}
|
|
2836
|
+
}
|
|
2837
|
+
}
|
|
2838
|
+
|
|
2839
|
+
/**
|
|
2840
|
+
* Takes a list and a comparator, and returns the maximum element in the list
|
|
2841
|
+
*
|
|
2842
|
+
* ## Examples
|
|
2843
|
+
*
|
|
2844
|
+
* ```gleam
|
|
2845
|
+
* assert [1, 2, 3, 4, 5] |> list.max(int.compare) == Ok(5)
|
|
2846
|
+
* ```
|
|
2847
|
+
*
|
|
2848
|
+
* ```gleam
|
|
2849
|
+
* assert ["a", "c", "b"] |> list.max(string.compare) == Ok("c")
|
|
2850
|
+
* ```
|
|
2851
|
+
*/
|
|
2852
|
+
export function max(list, compare) {
|
|
2853
|
+
if (list instanceof $Empty) {
|
|
2854
|
+
return new Error(undefined);
|
|
2855
|
+
} else {
|
|
2856
|
+
let first$1 = list.head;
|
|
2857
|
+
let rest$1 = list.tail;
|
|
2858
|
+
return new Ok(max_loop(rest$1, compare, first$1));
|
|
2859
|
+
}
|
|
2860
|
+
}
|
|
2861
|
+
|
|
2862
|
+
function build_reservoir_loop(loop$list, loop$size, loop$reservoir) {
|
|
2863
|
+
while (true) {
|
|
2864
|
+
let list = loop$list;
|
|
2865
|
+
let size = loop$size;
|
|
2866
|
+
let reservoir = loop$reservoir;
|
|
2867
|
+
let reservoir_size = $dict.size(reservoir);
|
|
2868
|
+
let $ = reservoir_size >= size;
|
|
2869
|
+
if ($) {
|
|
2870
|
+
return [reservoir, list];
|
|
2871
|
+
} else {
|
|
2872
|
+
if (list instanceof $Empty) {
|
|
2873
|
+
return [reservoir, toList([])];
|
|
2874
|
+
} else {
|
|
2875
|
+
let first$1 = list.head;
|
|
2876
|
+
let rest$1 = list.tail;
|
|
2877
|
+
let reservoir$1 = $dict.insert(reservoir, reservoir_size, first$1);
|
|
2878
|
+
loop$list = rest$1;
|
|
2879
|
+
loop$size = size;
|
|
2880
|
+
loop$reservoir = reservoir$1;
|
|
2881
|
+
}
|
|
2882
|
+
}
|
|
2883
|
+
}
|
|
2884
|
+
}
|
|
2885
|
+
|
|
2886
|
+
/**
|
|
2887
|
+
* Builds the initial reservoir used by Algorithm L.
|
|
2888
|
+
* This is a dictionary with keys ranging from `0` up to `n - 1` where each
|
|
2889
|
+
* value is the corresponding element at that position in `list`.
|
|
2890
|
+
*
|
|
2891
|
+
* This also returns the remaining elements of `list` that didn't end up in
|
|
2892
|
+
* the reservoir.
|
|
2893
|
+
*
|
|
2894
|
+
* @ignore
|
|
2895
|
+
*/
|
|
2896
|
+
function build_reservoir(list, n) {
|
|
2897
|
+
return build_reservoir_loop(list, n, $dict.new$());
|
|
2898
|
+
}
|
|
2899
|
+
|
|
2900
|
+
function log_random() {
|
|
2901
|
+
let $ = $float.logarithm($float.random() + min_positive);
|
|
2902
|
+
let random;
|
|
2903
|
+
if ($ instanceof Ok) {
|
|
2904
|
+
random = $[0];
|
|
2905
|
+
} else {
|
|
2906
|
+
throw makeError(
|
|
2907
|
+
"let_assert",
|
|
2908
|
+
FILEPATH,
|
|
2909
|
+
"gleam/list",
|
|
2910
|
+
2257,
|
|
2911
|
+
"log_random",
|
|
2912
|
+
"Pattern match failed, no pattern matched the value.",
|
|
2913
|
+
{
|
|
2914
|
+
value: $,
|
|
2915
|
+
start: 55515,
|
|
2916
|
+
end: 55586,
|
|
2917
|
+
pattern_start: 55526,
|
|
2918
|
+
pattern_end: 55536
|
|
2919
|
+
}
|
|
2920
|
+
)
|
|
2921
|
+
}
|
|
2922
|
+
return random;
|
|
2923
|
+
}
|
|
2924
|
+
|
|
2925
|
+
function sample_loop(loop$list, loop$reservoir, loop$n, loop$w) {
|
|
2926
|
+
while (true) {
|
|
2927
|
+
let list = loop$list;
|
|
2928
|
+
let reservoir = loop$reservoir;
|
|
2929
|
+
let n = loop$n;
|
|
2930
|
+
let w = loop$w;
|
|
2931
|
+
let _block;
|
|
2932
|
+
{
|
|
2933
|
+
let $ = $float.logarithm(1.0 - w);
|
|
2934
|
+
let log;
|
|
2935
|
+
if ($ instanceof Ok) {
|
|
2936
|
+
log = $[0];
|
|
2937
|
+
} else {
|
|
2938
|
+
throw makeError(
|
|
2939
|
+
"let_assert",
|
|
2940
|
+
FILEPATH,
|
|
2941
|
+
"gleam/list",
|
|
2942
|
+
2240,
|
|
2943
|
+
"sample_loop",
|
|
2944
|
+
"Pattern match failed, no pattern matched the value.",
|
|
2945
|
+
{
|
|
2946
|
+
value: $,
|
|
2947
|
+
start: 55076,
|
|
2948
|
+
end: 55122,
|
|
2949
|
+
pattern_start: 55087,
|
|
2950
|
+
pattern_end: 55094
|
|
2951
|
+
}
|
|
2952
|
+
)
|
|
2953
|
+
}
|
|
2954
|
+
_block = $float.round($float.floor(divideFloat(log_random(), log)));
|
|
2955
|
+
}
|
|
2956
|
+
let skip = _block;
|
|
2957
|
+
let $ = drop(list, skip);
|
|
2958
|
+
if ($ instanceof $Empty) {
|
|
2959
|
+
return reservoir;
|
|
2960
|
+
} else {
|
|
2961
|
+
let first$1 = $.head;
|
|
2962
|
+
let rest$1 = $.tail;
|
|
2963
|
+
let reservoir$1 = $dict.insert(reservoir, $int.random(n), first$1);
|
|
2964
|
+
let w$1 = w * $float.exponential(
|
|
2965
|
+
divideFloat(log_random(), $int.to_float(n)),
|
|
2966
|
+
);
|
|
2967
|
+
loop$list = rest$1;
|
|
2968
|
+
loop$reservoir = reservoir$1;
|
|
2969
|
+
loop$n = n;
|
|
2970
|
+
loop$w = w$1;
|
|
2971
|
+
}
|
|
2972
|
+
}
|
|
2973
|
+
}
|
|
2974
|
+
|
|
2975
|
+
/**
|
|
2976
|
+
* Returns a random sample of up to n elements from a list using reservoir
|
|
2977
|
+
* sampling via [Algorithm L](https://en.wikipedia.org/wiki/Reservoir_sampling#Optimal:_Algorithm_L).
|
|
2978
|
+
* Returns an empty list if the sample size is less than or equal to 0.
|
|
2979
|
+
*
|
|
2980
|
+
* Order is not random, only selection is.
|
|
2981
|
+
*
|
|
2982
|
+
* ## Examples
|
|
2983
|
+
*
|
|
2984
|
+
* ```gleam
|
|
2985
|
+
* sample([1, 2, 3, 4, 5], 3)
|
|
2986
|
+
* // -> [2, 4, 5] // A random sample of 3 items
|
|
2987
|
+
* ```
|
|
2988
|
+
*/
|
|
2989
|
+
export function sample(list, n) {
|
|
2990
|
+
let $ = build_reservoir(list, n);
|
|
2991
|
+
let reservoir;
|
|
2992
|
+
let rest$1;
|
|
2993
|
+
reservoir = $[0];
|
|
2994
|
+
rest$1 = $[1];
|
|
2995
|
+
let $1 = $dict.is_empty(reservoir);
|
|
2996
|
+
if ($1) {
|
|
2997
|
+
return toList([]);
|
|
2998
|
+
} else {
|
|
2999
|
+
let w = $float.exponential(divideFloat(log_random(), $int.to_float(n)));
|
|
3000
|
+
return $dict.values(sample_loop(rest$1, reservoir, n, w));
|
|
3001
|
+
}
|
|
3002
|
+
}
|
|
3003
|
+
|
|
3004
|
+
function permutation_zip(list, rest, acc) {
|
|
3005
|
+
if (list instanceof $Empty) {
|
|
3006
|
+
return reverse(acc);
|
|
3007
|
+
} else {
|
|
3008
|
+
let head = list.head;
|
|
3009
|
+
let tail = list.tail;
|
|
3010
|
+
return permutation_prepend(
|
|
3011
|
+
head,
|
|
3012
|
+
permutations(reverse_and_prepend(rest, tail)),
|
|
3013
|
+
tail,
|
|
3014
|
+
listPrepend(head, rest),
|
|
3015
|
+
acc,
|
|
3016
|
+
);
|
|
3017
|
+
}
|
|
3018
|
+
}
|
|
3019
|
+
|
|
3020
|
+
/**
|
|
3021
|
+
* Returns all the permutations of a list.
|
|
3022
|
+
*
|
|
3023
|
+
* ## Examples
|
|
3024
|
+
*
|
|
3025
|
+
* ```gleam
|
|
3026
|
+
* assert permutations([1, 2]) == [[1, 2], [2, 1]]
|
|
3027
|
+
* ```
|
|
3028
|
+
*/
|
|
3029
|
+
export function permutations(list) {
|
|
3030
|
+
if (list instanceof $Empty) {
|
|
3031
|
+
return toList([toList([])]);
|
|
3032
|
+
} else {
|
|
3033
|
+
let l = list;
|
|
3034
|
+
return permutation_zip(l, toList([]), toList([]));
|
|
3035
|
+
}
|
|
3036
|
+
}
|
|
3037
|
+
|
|
3038
|
+
function permutation_prepend(
|
|
3039
|
+
loop$el,
|
|
3040
|
+
loop$permutations,
|
|
3041
|
+
loop$list_1,
|
|
3042
|
+
loop$list_2,
|
|
3043
|
+
loop$acc
|
|
3044
|
+
) {
|
|
3045
|
+
while (true) {
|
|
3046
|
+
let el = loop$el;
|
|
3047
|
+
let permutations = loop$permutations;
|
|
3048
|
+
let list_1 = loop$list_1;
|
|
3049
|
+
let list_2 = loop$list_2;
|
|
3050
|
+
let acc = loop$acc;
|
|
3051
|
+
if (permutations instanceof $Empty) {
|
|
3052
|
+
return permutation_zip(list_1, list_2, acc);
|
|
3053
|
+
} else {
|
|
3054
|
+
let head = permutations.head;
|
|
3055
|
+
let tail = permutations.tail;
|
|
3056
|
+
loop$el = el;
|
|
3057
|
+
loop$permutations = tail;
|
|
3058
|
+
loop$list_1 = list_1;
|
|
3059
|
+
loop$list_2 = list_2;
|
|
3060
|
+
loop$acc = listPrepend(listPrepend(el, head), acc);
|
|
3061
|
+
}
|
|
3062
|
+
}
|
|
3063
|
+
}
|