1
- {new} = import '@fink/js-interop/reflect.fnk'
2
- {Symbol, Set} = import '@fink/js-interop/globals.fnk'
1
+ # TODO: should all js-interop imports be virtual imports from e.g. @fink/runtime/*
2
+ # and have the compiler translate it to the appropriate runtime module
3
+ {_iter_, _next_} = import '@fink/js-interop/runtime.js'
4
+ {_len_, _is_empty_, _join_, _reverse_, _sort_, _zip_} = import '@fink/js-interop/runtime.js'
3
5
4
6
{max_int} = import './num.fnk'
5
7
{is_fn} = import './fn.fnk'
6
8
7
9
8
10
9
- length = fn iterable:
10
- match iterable:
11
- {length: {}}: iterable.length
12
- {size: {}}: iterable.size
13
- {(Symbol.iterator): {}}: [...iterable].length
14
- else: -1
11
+ iter = _iter_
12
+ next = _next_
15
13
14
+ is_empty = _is_empty_
15
+ length = _len_
16
16
17
+ zip = _zip_
18
+ reverse = _reverse_
19
+ join = _join_
20
+ sort = _sort_
17
21
18
- is_empty = fn iterable:
19
- match iterable:
20
- {length: {}}: iterable.length == 0
21
- {size: {}}: iterable.size == 0
22
- {(Symbol.iterator): {}}: is_empty [...iterable | take 1]
23
- else: true
24
22
25
23
24
+ drop = fn num_items:
25
+ filter , idx=0:
26
+ [idx >= num_items, idx + 1]
26
27
27
- drop = fn num_items: fn iterable:
28
+
29
+
30
+ drop_last = fn num_items: fn iterable:
28
31
pipe iterable:
29
- filter , idx=0:
30
- [idx >= num_items, idx + 1]
32
+ map item, buffer=[]:
33
+ ...match buffer:
34
+ num_items > length ?:
35
+ [[], [...buffer, item]]
36
+ else:
37
+ [out, ...rest] = buffer
38
+ [[out], [...rest, item]]
31
39
32
40
33
41
34
42
take = fn num_items: fn iterable:
35
43
match num_items:
36
- 0:
37
- []
44
+ 0: []
38
45
else:
39
- pipe iterable:
40
- until , ctr=1:
41
- [ctr >= num_items, ctr + 1]
46
+ iterable | until , ctr=1:
47
+ [ctr >= num_items, ctr + 1]
48
+
49
+
50
+
51
+ take_last = fn num_items: fn iterable:
52
+ last = {}
53
+
54
+ pipe iterable:
55
+ chain [last]
56
+ map item, buffer=[]:
57
+ ...match item:
58
+ last:
59
+ [buffer, []]
60
+ else:
61
+ match buffer:
62
+ num_items > length ?:
63
+ [[], [...buffer, item]]
64
+ else:
65
+ [, ...rest] = buffer
66
+ [[], [...rest, item]]
42
67
43
68
44
69
45
70
slice = fn start, end=max_int: fn iterable:
46
71
match true:
47
- start + end < 0:
48
- # TODO: use a sliding buffer while iterating over items
49
- [...iterable].slice start, end
72
+ end - start == 0:
73
+ []
74
+
75
+ start < 0 and end < 0:
76
+ pipe iterable:
77
+ take_last -start
78
+ drop_last -end
79
+
80
+ start < 0:
81
+ pipe iterable:
82
+ take_last -start
83
+ take end + start
84
+
85
+ end < 0:
86
+ pipe iterable:
87
+ drop start
88
+ drop_last -end
50
89
51
90
else:
52
91
pipe iterable:
@@ -93,72 +132,49 @@ equals = fn it1, it2:
93
132
94
133
95
134
96
- # TODO: should this live in str?
97
- # TODO: should it be fn iterable, sep?
98
- join = fn sep: fn iterable:
99
- [...iterable].join sep
135
+ enumerate = fn start=0, step=1:
136
+ map item, cntr=start:
137
+ [[cntr, item], cntr + step]
100
138
101
139
102
140
103
- enumerate = fn start=0, step=1: fn iterable:
104
- pipe iterable:
105
- map item, cntr=start:
106
- [[cntr, item], cntr + step]
141
+ cycle = unfold items:
142
+ ...items
143
+
144
+
145
+
146
+ flatten = map items:
147
+ ...items
107
148
108
149
109
150
110
151
chain = fn ...iterables: fn iterable:
111
- pipe [iterable, ...iterables]:
112
- map iterable:
113
- ...iterable
152
+ flatten [iterable, ...iterables]
153
+
154
+
155
+
156
+ unique = filter item, known=[]:
157
+ [not item in known, [...known, item]]
114
158
115
159
116
160
117
- insert_at = fn idx, insert_items : fn iterable:
161
+ insert_at = fn idx, items : fn iterable:
118
162
ignore = {}
119
163
120
164
pipe iterable:
121
165
chain [ignore]
122
166
123
167
map item, curr=0:
124
168
all = match curr:
125
- idx: insert_items | chain [item]
169
+ idx: items | chain [item]
126
170
else: [item]
127
-
128
171
...[all, curr + 1]
129
172
130
173
filter item:
131
174
item != ignore
132
175
133
176
134
177
135
- cycle = fn iterable:
136
- pipe iterable:
137
- unfold items:
138
- ...items
139
-
140
-
141
-
142
- flatten = map iterable:
143
- ...iterable
144
-
145
-
146
-
147
- reverse = fn iterable:
148
- [...iterable].reverse _
149
-
150
-
151
-
152
- sort = fn compare: fn iterable:
153
- [...iterable].sort compare
154
-
155
-
156
-
157
- unique = fn iterable:
158
- new Set, iterable
159
-
160
-
161
-
162
178
find_index = fn item_to_find: fn iterable:
163
179
[[, idx]] = pipe iterable:
164
180
map item, idx=0:
@@ -175,37 +191,16 @@ find_index = fn item_to_find: fn iterable:
175
191
176
192
177
193
178
- _next_values = fn iters:
179
- pipe iters:
180
- map iter:
181
- {value, done} = iter.next _
182
- ... match done:
183
- true: []
184
- else: [value]
194
+ item_at = fn idx: fn iterable:
195
+ [item] = iterable | filter , curr_idx=0:
196
+ [idx == curr_idx, curr_idx + 1]
197
+ item
185
198
186
199
187
200
188
- zip = fn ...iterables:
189
- min_len = length iterables
190
-
191
- pipe:
192
- unfold _, iters=false:
193
- # JS iterators are stateful, thus we must recreate them
194
- # each time a zip iterable is (re)iterated.
195
- # TODO: it might be good to investigate using a custom iterator
196
- # protocoll that provides a (item, next_fn, descr) tuple
197
- # for each iteration step, allowing us to pass lazy ...rests around
198
- # without making things stateful.
199
- [...its] = match iters:
200
- false: iterables | map iterable:
201
- iterable.(Symbol.iterator) _
202
- else:
203
- iters
204
-
205
- [[... _next_values its], its]
206
-
207
- while item:
208
- min_len == length item
201
+ select = fn indices: fn iterable:
202
+ indices | map idx:
203
+ iterable | item_at idx
209
204
210
205
211
206
@@ -223,16 +218,12 @@ product = fn ...iterables:
223
218
0 == length ?:
224
219
iterable | map item: [item]
225
220
else:
226
- [...pools] = rest | map items: [...items]
227
- iterable | map item:
228
- ... pipe product ...pools:
229
- map items:
230
- [item, ...items]
231
-
232
-
233
-
234
- select = fn indices: fn iterable:
235
- indices | map idx: iterable.(idx)
221
+ # [...pools] = rest | map items: [...items]
222
+ pipe iterable:
223
+ map item:
224
+ ... pipe product ...rest: #...pools:
225
+ map items:
226
+ [item, ...items]
236
227
237
228
238
229
@@ -293,11 +284,3 @@ chunks = fn len, fill: fn iterable:
293
284
else:
294
285
[[], items]
295
286
296
-
297
-
298
- is_iter = fn obj:
299
- match obj:
300
- {(Symbol.iterator): is_fn ?}: true
301
- {(Symbol.asyncIterator): is_fn ?}: true
302
- else: false
303
-
0 commit comments