summaryrefslogtreecommitdiffstats
path: root/2024/info/transducers-after.md
blob: 8888c875362afada0f383ce9b71ce8acdf8cf4e1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
<!-- Automatically generated by emacsconf-publish-after-page -->


<a name="transducers-mainVideo-transcript"></a>
# Transcript


[[!template new="1" text="""Intro""" start="00:00:00.000" video="mainVideo-transducers" id="subtitle"]]

[[!template text="""Hi everyone, this is EmacsConf 2024. I'm Colin, and today""" start="00:00:00.000" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""I'll be talking about transducers.""" start="00:00:10.800" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""After introducing them, I'll share a bit of history about""" start="00:00:17.320" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""transducers and the problems that they solve, some basics""" start="00:00:21.880" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""about how we can use them, how they work, like how they're""" start="00:00:25.360" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""implemented, some demonstrations of how we can actually""" start="00:00:28.880" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""use them in the wild, and then some other discussions about""" start="00:00:32.400" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""issues that they have.""" start="00:00:36.960" video="mainVideo-transducers" id="subtitle"]]

[[!template new="1" text="""What are transducers?""" start="00:00:41.520" video="mainVideo-transducers" id="subtitle"]]

[[!template text="""Okay, let's get right in. What are transducers?""" start="00:00:41.520" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Transducers are a way to do streaming iteration with a""" start="00:00:46.400" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""modern API.""" start="00:00:49.680" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Who are transducers for, and thereby, who is""" start="00:00:55.680" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""this talk for? Well, it's for people who want to do streamed""" start="00:01:00.360" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""data processing in Emacs. It's for people who perhaps""" start="00:01:05.600" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""aren't satisfied with the existing APIs, for example, the""" start="00:01:10.520" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""seq API, or some other common libraries that provide""" start="00:01:14.200" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""similar functionality. Maybe you're not a fan of the loop""" start="00:01:19.360" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""macro. Some people find it difficult to understand. Or""" start="00:01:23.720" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""maybe you've done a bunch of Clojure before, and you'd like""" start="00:01:29.080" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""more aspects of Clojure in your Emacs Lisp. Or maybe you're""" start="00:01:32.720" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""just interested in transducers in general, because the""" start="00:01:36.880" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""pattern has now been ported to multiple different Lisps.""" start="00:01:40.240" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""So I'm Colin. I'm fosskers on everything online, and I do""" start="00:01:48.840" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""mainly back-end programming work and a lot of open source""" start="00:01:55.040" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""software. I wrote Haskell for a long time, both as a hobbyist""" start="00:01:58.520" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""and professionally. Since the COVID years, I've been""" start="00:02:05.160" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""writing Rust, both open source and professionally. But now""" start="00:02:09.080" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""I find that in my spare time, I'm mostly writing Common Lisp.""" start="00:02:13.440" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Some things I learned from my years of Haskell was that a lot""" start="00:02:19.720" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""of programming is just altering the shape of data. You know,""" start="00:02:22.720" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""sometimes we work through our algorithm line by line. We're""" start="00:02:27.520" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""trying to just tell the computer exactly what to do. But if we""" start="00:02:31.360" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""step back, a lot of the time we're just getting in data of some""" start="00:02:36.240" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""shape, changing it, and then passing it along. A lot of""" start="00:02:39.640" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""these patterns are common, identified""" start="00:02:44.120" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""decades ago. For instance, we have some collection, and we""" start="00:02:49.280" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""want to transform every element of that collection and then""" start="00:02:53.640" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""pass it on. Or maybe we're trying to filter out bad elements""" start="00:02:57.000" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""in that collection. Or maybe we're looking for a specific""" start="00:03:01.200" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""element in that collection. Yes, you could write all that""" start="00:03:04.800" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""with for loops, but these kind of common patterns were""" start="00:03:07.760" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""identified and given names decades ago. So why not use them?""" start="00:03:11.840" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""They say that there are two major problems in computer""" start="00:03:18.560" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""science, one being cache validation and the other being""" start="00:03:21.880" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""naming things.""" start="00:03:25.760" video="mainVideo-transducers" id="subtitle"]]

[[!template new="1" text="""Common issues""" start="00:03:27.590" video="mainVideo-transducers" id="subtitle"]]

[[!template text="""I've identified five other problems that""" start="00:03:27.590" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""come up when we're trying to deal with collections of data,""" start="00:03:29.800" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""or big streams of data. One is that if we were trying to""" start="00:03:33.200" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""load a file all into memory all at once and process the whole""" start="00:03:40.600" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""thing, sometimes we can have memory problems. You've""" start="00:03:45.280" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""probably seen out-of-memory errors or such things.""" start="00:03:48.280" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""A second issue that comes up is that if we were looking at a""" start="00:03:55.000" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""giant for loop, in particular a nested for loop or such""" start="00:03:58.200" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""things, it can be hard to tell just by looking at the code what""" start="00:04:01.800" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""it's trying to do, what it intends. If we don't go character""" start="00:04:06.080" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""by character or line by line, it can be hard to understand it.""" start="00:04:11.040" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Furthermore, and this is particularly an issue with Emacs""" start="00:04:16.440" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Lisp, is that if one call, for instance, to seq-map, then""" start="00:04:20.040" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""piped into seq-filter, for instance, will have an""" start="00:04:26.400" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""intermediate allocation, the map will take the source""" start="00:04:29.320" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""container, allocate a new one, and then the filter will""" start="00:04:33.600" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""operate over the second one. This is wasteful.""" start="00:04:37.640" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Furthermore, it can often be difficult to abort a stream.""" start="00:04:40.320" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""For instance, if we were filtering through our collection,""" start="00:04:48.880" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""but we knew we only wanted to go halfway, for instance, for""" start="00:04:53.200" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""some reason, we have no way to stop it halfway through. We""" start="00:04:57.320" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""just have to process the whole thing, even if we know we don't""" start="00:05:01.760" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""need to. Another issue is that for languages that have""" start="00:05:05.480" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""traits, or in Haskell they're called type classes, if you""" start="00:05:11.920" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""are defining what it means to map over something, you often""" start="00:05:18.040" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""have to redefine that for every kind of container or thing""" start="00:05:22.400" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""that you're iterating over. Wouldn't it be nice if we could""" start="00:05:27.040" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""define things like map just once and then reuse them""" start="00:05:31.240" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""everywhere? Now, transducers solve all five of these,""" start="00:05:34.720" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""without the addition of new language features, and with""" start="00:05:39.840" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""little more than plain old function composition.""" start="00:05:44.040" video="mainVideo-transducers" id="subtitle"]]

[[!template new="1" text="""Transducers""" start="00:05:47.280" video="mainVideo-transducers" id="subtitle"]]

[[!template text="""If this is your first time hearing of transducers, yeah,""" start="00:05:47.280" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""no problem. They were originally invented in Clojure by""" start="00:05:53.120" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Rich Hickey, and this is a quote from him. He thinks""" start="00:05:57.440" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""transducers are a fundamental primitive that decouple""" start="00:06:01.040" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""critical logic from list or sequence processing, and if he""" start="00:06:05.440" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""had to do Clojure all over, he'd put them at the bottom, at the""" start="00:06:10.080" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""very bottom of all the fundamental primitives. Now, that's""" start="00:06:14.000" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Rich speaking quite highly of them. And I think he has a point""" start="00:06:19.280" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""here.""" start="00:06:24.600" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""They were invented originally in Clojure. In more""" start="00:06:25.160" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""recent years, they were brought over to Scheme""" start="00:06:32.400" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""via SRFI 171. That's where I found them""" start="00:06:34.773" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""when I was learning the Guile language.""" start="00:06:38.775" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""In the process of submitting a patch, I realized""" start="00:06:41.522" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""that there were other things to be improved. So I ported the""" start="00:06:43.920" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""pattern to Common Lisp, then Fennel, and then more""" start="00:06:48.200" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""recently, Emacs Lisp. The Common Lisp and Emacs Lisp APIs""" start="00:06:51.400" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""are identical. And the Fennel one is not identical, but""" start="00:06:56.640" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""fairly similar. Overall, everywhere you find""" start="00:07:01.200" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""transducers, they should basically be fairly uniform.""" start="00:07:05.800" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""When I originally made the Common Lisp variant first, I""" start="00:07:10.280" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""sampled the APIs from a number of different languages and""" start="00:07:15.760" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""came up with what I believed to be a representative sample of""" start="00:07:18.800" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""what most people would want out of such a library. I gave""" start="00:07:23.440" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""functions their common modern names. For instance, map""" start="00:07:27.960" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""is map and filter is filter and so on.""" start="00:07:32.440" video="mainVideo-transducers" id="subtitle"]]

[[!template new="1" text="""Using transducers""" start="00:07:35.280" video="mainVideo-transducers" id="subtitle"]]

[[!template text="""What does the usage of transducers look like? Well,""" start="00:07:35.280" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""these examples will all be the Emacs Lisp variant, but the""" start="00:07:42.600" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Common Lisp will look basically exactly the same, minus""" start="00:07:48.960" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""this little t- prefix.""" start="00:07:52.360" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Running transducers requires three things. It requires a""" start="00:07:54.080" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""source. This could be an obvious thing like a list or a""" start="00:08:00.920" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""vector, but it could be other things like a file, or in Emacs""" start="00:08:06.440" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""list in particular, a buffer.""" start="00:08:11.480" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""A reducer is a function. It's something like""" start="00:08:16.349" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""the + operator or the \* operator,""" start="00:08:20.113" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""or certain constructors of various containers.""" start="00:08:22.640" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""It takes values and collates them into some final version.""" start="00:08:26.786" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Now, finally, we have what we're calling here""" start="00:08:32.126" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""a transducer chain. This could be one transducer function""" start="00:08:33.947" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""or it could be multiple composed together. These are the""" start="00:08:37.568" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""functions that actually take data and transform them""" start="00:08:43.480" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""somehow. For instance, this. We have a list of three""" start="00:08:47.080" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""elements. We want to reduce it into a vector. How we are""" start="00:08:55.280" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""going to transform the elements along the way: we are doing""" start="00:09:04.200" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""plus one to each of them. If this syntax is new to you, just""" start="00:09:07.520" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""know that this #' just means that this thing that""" start="00:09:13.360" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""comes after it is the name of the function. In Common Lisp and""" start="00:09:18.040" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Emacs Lisp, this is necessary, but for Clojure and Scheme,""" start="00:09:22.080" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""it is not. So we can see here that just this example is not much""" start="00:09:26.080" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""different than any other normal map call you might see made,""" start="00:09:32.720" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""but if nothing else, it's a handy way to convert a list to a""" start="00:09:36.120" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""vector or anything else. There are many, many reducers""" start="00:09:40.240" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""available and many different forms that we can""" start="00:09:45.000" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""collate the final value into.""" start="00:09:48.240" video="mainVideo-transducers" id="subtitle"]]

[[!template new="1" text="""A more involved example with comp""" start="00:09:52.625" video="mainVideo-transducers" id="subtitle"]]

[[!template text="""Let's see a more involved example.""" start="00:09:52.625" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Okay, now we've got some more meat here.""" start="00:09:55.087" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Here we can see usage of the comp function""" start="00:09:58.050" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""and a custom source, ints.""" start="00:10:01.773" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Ints is an infinite generator of integer values. That's not""" start="00:10:05.256" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""like a list or a file. It will generate infinitely.""" start="00:10:11.080" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Comp is letting us compose multiple transducer functions""" start="00:10:14.784" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""together. Notice that this is the opposite order of what""" start="00:10:19.440" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""we'd usually be used to from a function like comp. The order""" start="00:10:23.760" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""here is top to bottom, basically, so that the map goes first,""" start="00:10:28.080" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""then the filter, and then the take. So effectively is what""" start="00:10:32.680" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""we're doing is taking all the integers that exist,""" start="00:10:37.840" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""positive, adding one to them, filtering out only the even""" start="00:10:40.920" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""ones, but then just taking 10. Cons here is a function that""" start="00:10:45.400" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""just produces the ending result as a list. So what happens""" start="00:10:50.040" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""here specifically is how we are avoiding intermediate""" start="00:10:57.040" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""allocations. First, the number 0 will come through.""" start="00:11:00.480" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""It will be pulled out of this source internally by transduce.""" start="00:11:04.239" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""It will make its way into the map. The map will add it. Then it""" start="00:11:07.880" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""will immediately go into this filter step. So it's not like""" start="00:11:10.920" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""all the maps occur, and then all the filters occur. We do""" start="00:11:15.800" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""everything for each element. So the 0 comes in, now it's 1.""" start="00:11:19.120" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""The filter would occur. Well, it's going to fail that""" start="00:11:24.040" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""because it's not even, so it will just bail there. Now we'll""" start="00:11:27.560" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""go to the next one. Now 1 will come, it will become 2, then""" start="00:11:31.120" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""it will be saved by this evenp call, and then the take will""" start="00:11:35.240" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""capture it, because we only want 10 values here. You can""" start="00:11:39.120" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""see 2, 4, 6, 8, and so on is the result that we""" start="00:11:42.600" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""expect. So let's play around a little bit.""" start="00:11:45.240" video="mainVideo-transducers" id="subtitle"]]

[[!template new="1" text="""In Emacs""" start="00:11:49.333" video="mainVideo-transducers" id="subtitle"]]

[[!template text="""Let's jump into Emacs and see what we can do.""" start="00:11:49.333" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Alright, you should see my Emacs screen here.""" start="00:11:53.337" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""These are the actual notes for the actual""" start="00:11:58.501" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""presentation done in Org Mode. I'll boost that up in size for""" start="00:12:04.360" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""a little bit. That should be more than big enough for you.""" start="00:12:08.960" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Just by changing the reducer, we can change the result.""" start="00:12:12.640" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Okay, now it's a vector. Well, what else can we do to it? Well,""" start="00:12:17.720" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""let's just add up the results. Maybe we just want to count the""" start="00:12:21.080" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""results. Oh, indeed, there were 10. What if we want to find""" start="00:12:25.960" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""the average of the results? What if we want to find the median""" start="00:12:30.920" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""of the results? And so on. Here's some more interesting""" start="00:12:36.960" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""things that we could do. We could add different steps. So""" start="00:12:40.960" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""here we have all the integers. Let's add, hmm, okay, we'll""" start="00:12:45.840" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""keep that. We're going to add t-enumerate. What enumerate does""" start="00:12:51.240" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""is for each item that comes through, it is""" start="00:12:57.400" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""going to add a sort of index to it and make it a pair. In this""" start="00:13:00.880" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""case, it's going to be equal to what came in here. Well, we can""" start="00:13:06.040" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""change it. If we start this at 1, now it will be different.""" start="00:13:08.720" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""1 will be paired with 0, and then 2 would be paired""" start="00:13:12.400" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""with 1, and so on. We'll accept that the even call will change""" start="00:13:15.520" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""that a little bit. Why we're doing this is because we want""" start="00:13:19.560" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""to form a hash table. Let's move that down to 3, maybe""" start="00:13:24.040" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""we'll get a better result. What do we see? Okay, here now the""" start="00:13:27.280" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""result is a hash table. What are its values? Well, 0 seems""" start="00:13:31.440" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""to have... The key of 0 seems to be paired with 2, the key of""" start="00:13:37.360" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""1 seems to be paired with 4,""" start="00:13:40.480" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""and 2 seems to be paired with 6.""" start="00:13:42.910" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Maybe let's jazz that up even a little bit more.""" start="00:13:47.412" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""We're going to start from a string""" start="00:13:51.294" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""and we'll call it hello.""" start="00:13:52.974" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""That's not going to work anymore""" start="00:13:57.944" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""and neither is that, but what we could do is""" start="00:13:59.565" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""we could say t-map #'string.""" start="00:14:02.586" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""I believe we'll do that.""" start="00:14:05.499" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Let's see if that works. It did. So that's""" start="00:14:08.628" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""going to convert a character into a string.""" start="00:14:08.960" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Let's just go two""" start="00:14:13.590" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""just to make it a little easier. Now you can see that we've""" start="00:14:14.680" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""constructed a hash table here. The key of 0 is mapped to the""" start="00:14:18.400" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""string of h and 1 is mapped to e. Now, I really like having""" start="00:14:21.920" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""this reducer in particular.""" start="00:14:27.080" video="mainVideo-transducers" id="subtitle"]]

[[!template new="1" text="""Hash tables""" start="00:14:29.469" video="mainVideo-transducers" id="subtitle"]]

[[!template text="""Know that hash tables are""" start="00:14:29.469" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""also legal sources. I find that both in Emacs Lisp and in""" start="00:14:30.640" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Common Lisp, dealing with hash tables--like creating them""" start="00:14:34.200" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""and altering them--can be a bit of a pain. Having them""" start="00:14:37.120" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""immediately available like this with transducers is very""" start="00:14:41.600" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""handy, I find. We can work with something that wasn't a hash""" start="00:14:45.680" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""table. We can construct it in a way that makes it amenable to""" start="00:14:49.080" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""that, and then reduce it down into a hash table, and here you""" start="00:14:53.280" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""go. Very handy.""" start="00:14:56.200" video="mainVideo-transducers" id="subtitle"]]

[[!template new="1" text="""Clarity""" start="00:14:58.040" video="mainVideo-transducers" id="subtitle"]]

[[!template text="""One last point is that you can see very clearly what""" start="00:14:58.040" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""this is attempting to do, as opposed to, say, a for loop. It's""" start="00:15:06.400" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""very clear what that step is doing, and then you can see what""" start="00:15:10.480" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""that is doing, and you know that the result is going to be two.""" start="00:15:12.720" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Each line is kind of its own declarative step, and it should""" start="00:15:15.120" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""be clear, just by staring at this, basically what you're""" start="00:15:18.560" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""going to get out. This is one main difference from other""" start="00:15:22.160" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""languages that have things--say, for instance, Rust's""" start="00:15:25.400" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""iterator API--is the difference between the transducers""" start="00:15:29.600" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""and the reducers. If we go up here, for example, the""" start="00:15:35.440" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""difference between the transducers and the reducers and""" start="00:15:41.640" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""the sources is not explicitly laid out, whereas with""" start="00:15:44.680" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""transducers, it is. You have to be aware of how these things""" start="00:15:48.120" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""are different. I think that that helps clarity.""" start="00:15:53.120" video="mainVideo-transducers" id="subtitle"]]

[[!template new="1" text="""How do transducers work?""" start="00:15:55.800" video="mainVideo-transducers" id="subtitle"]]

[[!template text="""Moving on. How do transducers work? Well,""" start="00:15:55.800" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""we want to go see the README.""" start="00:16:02.000" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""So, what we're going to do is""" start="00:16:09.858" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""we're going to go to here.""" start="00:16:11.400" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""You should still be able to see this.""" start="00:16:19.103" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""This is the CL example, actually.""" start="00:16:21.960" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Let's go to transducers.el.""" start="00:16:28.584" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Their APIs and READMEs are the same,""" start="00:16:32.280" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""but just for the sake of it, we will go see""" start="00:16:37.745" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""how this looks on the Emacs side,""" start="00:16:39.920" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""just so that nothing is a surprise.""" start="00:16:45.727" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""But recall that the APIs are essentially the same""" start="00:16:48.047" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""between the two. If you go to this section, writing your""" start="00:16:50.240" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""own primitives, you can read about how transducers are""" start="00:16:53.680" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""actually formed, whether or not you want to write them""" start="00:16:56.840" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""yourself or not. We can see here t-map. We accept the""" start="00:17:01.000" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""function that you want to operate with. Then you've got""" start="00:17:06.800" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""this extra little lambda here that's coming in, and it's""" start="00:17:10.240" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""receiving a thing that is named reducer. Now, while here""" start="00:17:13.320" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""we're calling it reducer, it's actually the chain of all the""" start="00:17:17.080" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""composed functions together. It's all those main""" start="00:17:20.440" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""transducer steps. Finally, it's the reducer all""" start="00:17:25.160" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""composed together with normal function composition.""" start="00:17:28.480" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""That will matter very soon. Now here's the actual meat.""" start="00:17:31.880" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""We can see the accumulative result that's coming in with the""" start="00:17:35.878" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""current element. Now we need to operate on this.""" start="00:17:40.520" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Were it normally mapped, we would see us""" start="00:17:45.740" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""applying the F to the input.""" start="00:17:47.841" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""But here, you can see us applying the F to the input and then""" start="00:17:49.920" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""continuing on. So us calling the rest of the composed chain""" start="00:17:53.520" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""here is the effect of, in the previous slide, moving to the""" start="00:17:58.680" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""next step. We could ignore this line for now.""" start="00:18:03.160" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""If you're curious, please read the README in detail.""" start="00:18:07.157" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Now, what about reducers?""" start="00:18:13.820" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""What do those look like? Well, let's just scroll""" start="00:18:15.580" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""down here. Recall that a reducer is a function that's""" start="00:18:18.880" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""consuming a stream, right? Zoom that up for you a little bit.""" start="00:18:22.440" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Now, in the case of count, recall that this is how it's""" start="00:18:26.960" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""working, how we saw a moment ago. So clearly this list of five""" start="00:18:33.920" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""elements only has five things in it. Well, a reducer by""" start="00:18:37.680" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""structure is a function of two, one, or zero arguments. So we""" start="00:18:42.200" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""can see here in the case of two, this is the normal iterative""" start="00:18:47.600" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""case. We don't care about the input for count, we just care""" start="00:18:50.640" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""about the current accumulated count that we're doing, and""" start="00:18:54.520" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""we add one to it, and that's it. This then goes back to""" start="00:18:58.560" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""the loop and the whole process starts again with the next""" start="00:19:02.880" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""element. In this kind of done case, this is used internal to""" start="00:19:06.360" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""that sort of the supervising function transduce. It's just""" start="00:19:10.880" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""confirming the final result. Sometimes some""" start="00:19:16.880" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""post-processing is necessary here, but in the case of""" start="00:19:19.640" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""count, as it is so simple, that is not necessary. And now""" start="00:19:21.840" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""here's the base case. This is also used within that""" start="00:19:26.040" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""supervising transduce function at the very top. Well, if""" start="00:19:29.360" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""you're counting, you have to start from somewhere, right?""" start="00:19:34.320" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""In this case, well, what you're starting with is zero.""" start="00:19:36.680" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""In the case of cons, you'd be starting with an empty list.""" start="00:19:37.350" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""In the case of vector, you'd be starting""" start="00:19:40.252" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""with an empty vector and so on.""" start="00:19:44.435" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Once again, if you are more curious, please take a look at""" start="00:19:54.000" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""the README.""" start="00:19:56.800" video="mainVideo-transducers" id="subtitle"]]

[[!template new="1" text="""Transducers in the wild - CSV""" start="00:20:00.520" video="mainVideo-transducers" id="subtitle"]]

[[!template text="""Okay, transducers in the wild. Well, let's go take a look at""" start="00:20:00.520" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""processing some CSV data.""" start="00:20:06.040" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""We're going to open up a new Emacs Lisp bracket here. So I have""" start="00:20:07.640" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""a file. And in this file, let's just go look at C-x b right""" start="00:20:21.320" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""there, you will see that we've got some bank transaction""" start="00:20:28.840" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""information. It's got these transactions from a whole""" start="00:20:34.840" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""bunch of different people into different accounts,""" start="00:20:37.880" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""whether it's money coming in, money going out, and then a""" start="00:20:40.200" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""basic description. How's your Latin? But for this little""" start="00:20:43.880" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""test, what we want to do is we want to find Bob's final bank""" start="00:20:47.840" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""balance. Let's get on to it. First of all, let's""" start="00:20:53.680" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""just confirm, let's do some basic stuff.""" start="00:20:59.680" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""with-current-buffer, find-file-noselect.""" start="00:21:04.445" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""What's the name of that file?""" start="00:21:10.845" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""This is pre-organized, so you""" start="00:21:15.543" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""will just see it right here.""" start="00:21:17.440" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""t-transduce and t-comp. We don't know what we're going to comp""" start="00:21:20.880" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""yet. Actually, I'll just pass to show you. And then we will""" start="00:21:27.000" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""see, let's just do a little t-count just to confirm. What's""" start="00:21:33.040" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""our source? Well, our source is a buffer, t-buffer-read.""" start="00:21:37.000" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""And note that because we're using with-current-buffer,""" start="00:21:45.113" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""if we go like this, if we go current-buffer, this will just work. So""" start="00:21:50.154" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""now let's... Well, that was odd. I should have done it like""" start="00:21:55.080" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""that. There we go. So now we should make that a little smaller""" start="00:21:59.920" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""so you can see what it is. Now if we hit RET, we should get the""" start="00:22:02.160" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""right result. Okay, so there are 50,001 lines in this file,""" start="00:22:04.800" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""but the one extra one is the name of the headers, right?""" start="00:22:09.560" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""We want to process this file in more detail. So how can we do""" start="00:22:13.517" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""that? Well, let's start by just automatically""" start="00:22:18.080" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""interpreting the results as CSV. If we do that, okay, well""" start="00:22:22.080" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""now we only have 50,000 entries as we expected, right?""" start="00:22:28.800" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Because it's going to pull out the header line. If we now say""" start="00:22:31.560" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""we want to just filter out, you know, We only want Bob, right?""" start="00:22:36.760" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""So if... gethash, it was in the row of name. Each line here is""" start="00:22:42.680" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""made into, at least by default, is made into a hash map. So if""" start="00:22:53.680" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""we go like this, we should see that. Okay, so 12,000 of these""" start="00:22:57.080" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""lines or thereabout belong to Bob.""" start="00:23:02.760" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Let's just move that over a little bit. Actually, I suppose we don't even""" start="00:23:05.640" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""need that anymore. I'll just keep that full size for you.""" start="00:23:13.840" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Okay, so all right, there's about 12,000 results for Bob of""" start="00:23:17.800" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""the 50,000. What's next? Well, we want to confirm,""" start="00:23:24.400" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""we want to pull out everything,""" start="00:23:32.480" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""all of the in and the out entries.""" start="00:23:40.040" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Thank you. So, string to number, because we know that""" start="00:23:43.080" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""everything came in as strings. Unfortunately, the from-csv""" start="00:23:56.280" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""doesn't try to be smart at all, it's just pulling everything""" start="00:24:01.240" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""in as string values. If you want actual things to be""" start="00:24:03.800" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""numbers or whatever, that is up to you to do the parsing""" start="00:24:09.480" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""yourself. Okay, so we have those two values now. We know""" start="00:24:13.400" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""that we saw from the data just a moment ago that you're only""" start="00:24:20.680" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""going to have a value in one column or the other. It's either""" start="00:24:23.880" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""going to be 0 in the empty one, or you're going to have some""" start="00:24:27.000" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""number in the other. So we know that we can just naively add""" start="00:24:29.120" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""them. If it was in, it would always be positive. So we'll just""" start="00:24:32.160" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""add that. But in the negative case, we want to just make it""" start="00:24:35.480" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""negative really briefly before we add them all together.""" start="00:24:41.520" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""let's now just prove to ourselves that we are sane here. What""" start="00:24:45.280" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""we're going to do is we're going to quickly go say take""" start="00:24:50.520" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""5 just to convince ourselves, and we'll go cons, and let's""" start="00:24:52.480" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""see if we get kind of results that make sense. Okay, these""" start="00:24:57.040" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""sort of make sense. It looks like you know Bob's got some big""" start="00:24:59.840" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""expenses here. If we take say 15, does it look any better?""" start="00:25:02.800" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Okay, looks like he had a payday. All right, good job Bob.""" start="00:25:07.680" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Let's get back in there. Now we only really care about""" start="00:25:10.320" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""adding the final result, right? So there we go. Add that all""" start="00:25:15.440" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""together and we'll see what we get in a moment. Okay, wow,""" start="00:25:20.120" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Bob's rich. Okay, so it looks like in his 12,000""" start="00:25:24.560" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""transaction, Bob has an overall net worth of $8.5 million.""" start="00:25:27.520" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Looking pretty good.""" start="00:25:32.280" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""So here's an example of how you can, particularly in Emacs""" start="00:25:34.440" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Lisp, how you can very easily just get a file, consider it the""" start="00:25:39.000" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""current buffer, and then just do whatever you want to it.""" start="00:25:42.960" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Note that there is sort of first-class support for both CSV""" start="00:25:45.880" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""and JSON, and then you have, and both of those bring in their""" start="00:25:50.360" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""values as hash maps, and then you're just free to do whatever""" start="00:25:54.360" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""you want and process them, potentially both writing them""" start="00:25:57.720" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""back out as CSV or JSON once again.""" start="00:26:00.440" video="mainVideo-transducers" id="subtitle"]]

[[!template new="1" text="""Issues and next steps""" start="00:26:03.240" video="mainVideo-transducers" id="subtitle"]]

[[!template text="""Some issues with transducers that can come up is""" start="00:26:03.240" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""that one, a zip operator is missing, but I'm working on it.""" start="00:26:10.720" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""Two is that performance, particularly in Emacs Lisp, isn't""" start="00:26:14.920" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""that great. It could be due to the sort of nested lambda calls""" start="00:26:19.400" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""that have to occur internally, but the common Lisp""" start="00:26:24.120" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""implementation is quite good. and there's yet no support""" start="00:26:27.760" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""for parallelism. You can imagine that a lot of those steps""" start="00:26:32.240" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""you could potentially perform in parallel depending on the""" start="00:26:35.400" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""platform, but research has not yet gotten that far. Okay,""" start="00:26:38.560" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""that's all. Thank you very much. If you have any questions,""" start="00:26:44.400" video="mainVideo-transducers" id="subtitle"]]
[[!template text="""please contact me.""" start="00:26:47.640" video="mainVideo-transducers" id="subtitle"]]



Captioner: sachac

Questions or comments? Please e-mail [emacsconf-org-private@gnu.org](mailto:emacsconf-org-private@gnu.org?subject=Comment%20for%20EmacsConf%202023%20transducers%3A%20Transducers%3A%20finally%2C%20ergonomic%20data%20processing%20for%20Emacs%21)


<!-- End of emacsconf-publish-after-page -->