-
Notifications
You must be signed in to change notification settings - Fork 1
/
atom.xml
1599 lines (1566 loc) · 104 KB
/
atom.xml
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
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>silky.github.io</title>
<link href="https://silky.github.io/atom.xml" rel="self" />
<link href="https://silky.github.io" />
<id>https://silky.github.io/atom.xml</id>
<author>
<name>Noon van der Silk</name>
<email>[email protected]</email>
</author>
<updated>2024-05-06T00:00:00Z</updated>
<entry>
<title>HTMX and Servant: Seamless and powerful handling of HTTP errors in HTMX</title>
<link href="https://silky.github.io/posts/htmx-haskell-interview.html" />
<id>https://silky.github.io/posts/htmx-haskell-interview.html</id>
<published>2024-05-06T00:00:00Z</published>
<updated>2024-05-06T00:00:00Z</updated>
<summary type="html"><![CDATA[<div class="info">
Posted on May 6, 2024
by Noon van der Silk
</div>
<p>As part of the interview process for a company I was recently rejected by, I
wrote a blog post about HTMX and Haskell (and, JavaScript, but that was just a
requirement :D).</p>
<p>I think the post is interesting in any case, so here it is :) The Haskell
component is in the <code>Bonus content</code>. If you want to skip straight to the code,
you can just go direct to the repo:
<a href="https://github.com/silky/htmx-servant-js-post">htmx-servant-js-example</a>.</p>
<h1 id="seamless-and-powerful-handling-of-http-errors-in-htmx">Seamless and powerful handling of HTTP errors in HTMX</h1>
<p><a href="https://htmx.org/">HTMX</a> is a popular front-end JavaScript library that can
be used to create simple dynamic UIs. But how robust is it? Is it ready for
production use? And what are its features, anyway? Let’s explore it
together by building an image conversion app.</p>
<h2 id="problem">Problem</h2>
<p>You are building a dynamic UI and calling endpoints that will either fail or
return some content to render. You want to handle both these cases with the
simplest code possible.</p>
<p>A typical workflow somewhere in your code is to query the endpoint, check the
status of what happened, and act accordingly:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">fetch</span>(url)</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span><span class="fu">then</span>( (result) <span class="kw">=></span> {</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> <span class="cf">if</span> (result<span class="op">.</span><span class="at">ok</span>) {</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a> <span class="co">// Everything is good!</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a> } <span class="cf">else</span> {</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a> <span class="co">// Something else ...</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a> }</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a>})</span></code></pre></div>
<p>It’s a bit of a hassle to write this logic all over the place. Can HTMX help
us out here? How does it look for something non-trivial, and what are the
caveats we should be aware of?</p>
<h2 id="solution">Solution</h2>
<p>Let’s take the example of uploading an image and converting it from a PNG to a
JPG.</p>
<p>Naturally, HTMX can do the happy-path, when there are no errors, easily. We
define the form, with the <a href="https://htmx.org/reference/">HTMX attributes</a> to
define how the DOM changes based on the result:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="co"><!-- index.html --></span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="kw"><script</span> <span class="er">src</span><span class="ot">=</span><span class="st">"https://unpkg.com/[email protected]"</span><span class="kw">></script></span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a>...</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="kw"><body></span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a> <span class="kw"><form</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a><span class="ot"> hx-encoding=</span><span class="st">"multipart/form-data"</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="ot"> hx-post=</span><span class="st">"/upload"</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="ot"> hx-target=</span><span class="st">"#result"</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="ot"> hx-swap=</span><span class="st">"innerHTML"</span></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a> <span class="kw">></span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a> <span class="kw"><input</span> <span class="er">type</span><span class="ot">=</span><span class="st">"file"</span> <span class="er">name</span><span class="ot">=</span><span class="st">"image"</span> <span class="er">accept</span><span class="ot">=</span><span class="st">"image/png"</span> <span class="kw">/></span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a> <span class="kw"><button></span>Upload<span class="kw"></button></span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a> <span class="kw"></form></span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a> <span class="kw"><div</span> <span class="er">id</span><span class="ot">=</span><span class="st">"result"</span><span class="kw">></div></span></span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true" tabindex="-1"></a><span class="kw"></bod></span></span></code></pre></div>
<p>On the server, at the <code>/upload</code> route, we return an HTML element:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="co">// server.js endpoint definition</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>app<span class="op">.</span><span class="fu">post</span>(<span class="st">"/upload"</span><span class="op">,</span> <span class="kw">async</span> <span class="kw">function</span>(req<span class="op">,</span> resp) {</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a> <span class="co">// image conversion steps; new image in `newPath`.</span></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a> <span class="co">// ...</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a> <span class="co">// send the resulting path back as an "img" tag</span></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a> resp<span class="op">.</span><span class="fu">send</span>(<span class="vs">`<img src="</span><span class="sc">${</span>newPath<span class="sc">}</span><span class="vs">" />`</span>)<span class="op">;</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a> })<span class="op">;</span></span></code></pre></div>
<p>Here’s what it looks like:</p>
<center>
<img width="600" src="/images/happy-path.gif" />
</center>
<p>It’s interesting to note:</p>
<ul>
<li>It looks pretty smooth!</li>
<li>We tell HTMX which element to update (via a CSS selector) with <code>hx-target</code>,</li>
<li>We tell it how with <a href="https://htmx.org/attributes/hx-swap/"><code>hx-swap</code></a> (it’s
important that we use <code>innerHTML</code> so the main target element persists if we
upload a different image),</li>
</ul>
<p>These are some questions I’m asking myself at this point:</p>
<ul>
<li>What would happen if we didn’t return a HTML element from the response?</li>
<li>What would happen if we didn’t return HTTP status 200?</li>
</ul>
<p>We can actually already answer the first question, given what we know about
<code>innerHTML</code>: whatever text is returned from our <code>/upload</code> route is
directly set as the <code>innerHTML</code>, so we best make sure it’s valid HTML :)</p>
<p>For our second question, let’s just try it!</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode javascript"><code class="sourceCode javascript"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="co">// update server.js to just through an error:</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>app<span class="op">.</span><span class="fu">post</span>(<span class="st">"/upload"</span><span class="op">,</span> <span class="kw">async</span> <span class="kw">function</span>(req<span class="op">,</span> resp) {</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> resp<span class="op">.</span><span class="fu">status</span>(<span class="dv">500</span>)<span class="op">.</span><span class="fu">send</span>(<span class="vs">`Sorry, no thanks.`</span>)<span class="op">;</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<p>Then:</p>
<center>
<img width="600" src="/images/500-error.gif" />
</center>
<p>We can see that nothing gets rendered, and we see the errors in the console.</p>
<p>With what we’ve seen so far, we would be justified in assuming that the text
<code>Sorry, no thanks</code> might have come through to the <code><div id="result"></code> element,
but in fact if the response is a HTTP error code HTMX doesn’t perform
subsequent steps (typically a good idea when something has gone wrong!)</p>
<p>Luckily, there is an extension:
<a href="https://htmx.org/extensions/response-targets/">response-targets</a> that we can
use to get the behaviour we are after. Phew! We can make the following
modifications to our <code>index.html</code> page:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="co"><!-- index.html --></span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="kw"><script</span> <span class="er">src</span><span class="ot">=</span><span class="st">"https://unpkg.com/[email protected]"</span><span class="kw">></script></span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="kw"><script</span> <span class="er">src</span><span class="ot">=</span><span class="st">"https://unpkg.com/[email protected]/dist/ext/response-targets.js"</span><span class="kw">></script></span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>...</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a><span class="kw"><body</span> <span class="er">hx-ext</span><span class="ot">=</span><span class="st">"response-targets"</span><span class="kw">></span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a> <span class="kw"><form</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a><span class="ot"> hx-encoding=</span><span class="st">"multipart/form-data"</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a><span class="ot"> hx-post=</span><span class="st">"/upload"</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a><span class="ot"> hx-target=</span><span class="st">"#result"</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a><span class="ot"> hx-target-error=</span><span class="st">"#result"</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a><span class="ot"> hx-swap=</span><span class="st">"innerHTML"</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a> <span class="kw">></span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a> <span class="kw"><input</span> <span class="er">type</span><span class="ot">=</span><span class="st">"file"</span> <span class="er">name</span><span class="ot">=</span><span class="st">"image"</span> <span class="er">accept</span><span class="ot">=</span><span class="st">"image/png"</span> <span class="kw">/></span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a> <span class="kw"><button></span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a> Upload</span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a> <span class="kw"></button></span></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a> <span class="kw"></form></span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a> <span class="kw"><div</span> <span class="er">id</span><span class="ot">=</span><span class="st">"result"</span><span class="kw">></div></span></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a><span class="kw"></body></span></span></code></pre></div>
<p>What did we do?</p>
<ul>
<li>We added a dependency on <code>dist/ext/response-targets.js</code></li>
<li>We added `hx-ext=“response-targets” to the <em>parent</em> of the elements we want to
use it on (<a href="https://htmx.org/attributes/hx-ext/">read more about hx-ext</a>; I
forgot this initially and was wondering why it didn’t work!)</li>
<li>We used the catch-all <code>hx-target-error</code> to send all errors to the
<code>id="result"</code> element, just for simplicity (<a href="https://htmx.org/extensions/response-targets/#wildcard-resolution">you can target specific error
codes if you wish</a>).</li>
</ul>
<p>Here’s how it looks now:</p>
<center>
<img width="600" src="/images/render-error.gif" />
</center>
<p>Success! We see the error rendered in the page! And in the case that we don’t
hit an error, we will still render the image directly as well. That’s exactly
what we wanted! :)</p>
<h2 id="discussion">Discussion</h2>
<p>It’s pretty nice to use HTMX to handle HTTP errors from your API: use
<a href="https://htmx.org/extensions/response-targets/">response-targets</a> to pick up
specific errors, or all of them, and render the contents directly in the page!</p>
<p>A small detail that I came across along the way is the difference between
<code>outerHTML</code> and <code>innerHTML</code> and what you might consider <em>repeated behaviour</em>
while preserving the most “meaningful” structure for your HTMX documents.</p>
<p>The scenario is this: Imagine you want to repeatedly convert images; then you
need to make sure that the HTML element of <code>hx-target</code> persists; with
<code>innerHTML</code> it always will, but with <code>outerHTML</code> it will be replaced. The
advantage of <code>outerHTML</code> is it’s a bit more “meaningful” to replace an <code><img></code>
tag with another <code><img></code> tag; and likewise. But, ultimately, it’s up to you to
pick the style you prefer.</p>
<h2 id="bonus-content-the-server-is-now-in-haskell">Bonus content: The server is now in Haskell</h2>
<p>HTMX is, after all, a front-end technology, so we can continue to use it if we
have our server in a different language.</p>
<p>It turns out Haskell will let us express one interesting requirement
of using HTMX: our routes should return <em>HTML</em>, not, say, JSON, or plain text.</p>
<p>In the <a href="https://www.servant.dev/">Servant</a> ecosystem, you would having
something like the following<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> to define the <code>/upload</code> endpoint:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- Main.hs</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Routes</span> mode <span class="ot">=</span> <span class="dt">Routes</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a> {<span class="ot"> upload ::</span> mode <span class="op">:-</span> <span class="st">"upload"</span> <span class="op">:></span> <span class="dt">MultipartForm</span> <span class="dt">Mem</span> (<span class="dt">MultipartData</span> <span class="dt">Mem</span>) <span class="op">:></span> <span class="dt">Post</span> '[<span class="dt">HTML</span>] <span class="dt">Html</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a> , <span class="op">...</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a> }</span></code></pre></div>
<p>And then something like this 👇 (with a few details left out) to do what the
JavaScript <code>server.js</code> was doing before: read exactly one image from the form,
throw an error if not, and otherwise take the image, convert it to
a JPG, and return the new path as an <code><img ... /></code> tag:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- Main.hs</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="ot">uploadAndConvert ::</span> <span class="dt">MultipartData</span> <span class="dt">Mem</span> <span class="ot">-></span> <span class="dt">Handler</span> <span class="dt">Html</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>uploadAndConvert form <span class="ot">=</span> <span class="kw">do</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a> newPath <span class="ot"><-</span> <span class="kw">case</span> (files form) <span class="kw">of</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a> [] <span class="ot">-></span> oops <span class="st">"No files uploaded!"</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a> f <span class="op">:</span> [] <span class="ot">-></span> liftIO <span class="op">$</span> <span class="kw">do</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> jpg <span class="ot">=</span> <span class="op">...</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a> newPath <span class="ot">=</span> <span class="op">...</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a> BIO.writeFile newPath jpg</span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a> <span class="fu">pure</span> newPath</span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a> <span class="op">...</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a> <span class="fu">pure</span> <span class="op">$</span> [shamlet| <span class="kw"><img </span><span class="er">src=#{newPath}</span><span class="kw"> /></span> |]</span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true" tabindex="-1"></a> oops m <span class="ot">=</span> throwError <span class="op">$</span> err500 { errBody <span class="ot">=</span> m }</span></code></pre></div>
<p>It is a requirement of the type system to make sure that this particular
endpoint returns <em>HTML</em>! It’s then a small exercise to ensure that any <em>error</em>
content comes through with the appropriate HTML wrapping :) Happy Haskelling!</p>
<section class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>Note we’ve left off important import statements, but you can find
these in the <a href="https://github.com/silky/htmx-servant-js-post/tree/main/haskell-image-converter/src/Main.hs">full code snippet</a>.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
]]></summary>
</entry>
<entry>
<title>Zen Kanban</title>
<link href="https://silky.github.io/posts/zen-kanban.html" />
<id>https://silky.github.io/posts/zen-kanban.html</id>
<published>2024-04-06T00:00:00Z</published>
<updated>2024-04-06T00:00:00Z</updated>
<summary type="html"><![CDATA[<div class="info">
Posted on April 6, 2024
by Noon van der Silk
</div>
<p>We are all familiar with the standard kanban/agile board settings:</p>
<ul>
<li>Backlog: Things we’re ignoring for now</li>
<li>Todo: Stuff we’ve got to do this “sprint”</li>
<li>In progress: Stuff we’re working on now</li>
<li>Done</li>
<li>Blocked</li>
</ul>
<p>There are many variants on these names, but they’ve remained pretty standard
over all the organisations I’ve worked in.</p>
<p>I myself now prefer a buddhist-inspired variant; namely:</p>
<ul>
<li>Background (was: <code>backlog</code>): Items floating in the expanse of consciousness.</li>
<li>Awareness (was: <code>todo</code>): Items present in the mind.</li>
<li>Sparking joy (was: <code>in progress</code>): Items presently being enjoyed directly.</li>
<li>Thank you (was <code>done</code>): Items that have passed their time with us, for now.</li>
<li>Impermanence (was <code>blocked</code>): Items temporarily on hold.</li>
</ul>
<p>It at least lets me feel more relaxed about almost every column :)</p>
]]></summary>
</entry>
<entry>
<title>Stepping down from SciRate maintainership</title>
<link href="https://silky.github.io/posts/scirate-maintainership.html" />
<id>https://silky.github.io/posts/scirate-maintainership.html</id>
<published>2022-03-29T00:00:00Z</published>
<updated>2022-03-29T00:00:00Z</updated>
<summary type="html"><![CDATA[<div class="info">
Posted on March 29, 2022
by Noon van der Silk
</div>
<h4 id="background">Background</h4>
<p>I can’t remember when I first stumbled across <a href="https://scirate.com/">SciRate</a>.</p>
<p>I’d had a fascination with scientific papers
for many years, well before actually attending university (as a mature-age
student) and starting to learn more formally. I would store them in a
variety of ways, print them out and hang them up in my house; send them to
myself on a mailing list that I created just for that purpose, or a public
subreddit where I would post the papers I wanted to read, so I wouldn’t forget
about them. Evidently, the “bookmarking” feature in the browser wasn’t one I
found particularly useful.</p>
<p>Eventually, I discovered <a href="https://www.jabref.org/">JabRef</a>, which I used for
several years. I stored all the papers that I was interested in (at the time,
quantum computing), and learned all about bibliography management. I even
stored all the PDFs, and the metadata from the JabRef system, in git, horribly
offending bitbuckets storage limits by having a repository ~10GB in size (I
think it doesn’t clone successfully anymore; it’s been several years since
I tried.)</p>
<p>After some time I became tired with JabRef, and built my own (very very
terrible) reference management program: <a href="https://github.com/silky/super-reference">super-reference</a>.</p>
<p>Eventually, I discovered <a href="https://scirate.com/">SciRate</a>. I think the version
I found was called “SciRate 2”. It was in the hands of Bill Rosgen. I got
incredibly excited and signed up immediately. Because the code was open-source
(I actually can’t remember, but I think it might’ve been a personally-hosted git
repository somewhere), I added possibly one of my first “impactful” changes:
MathJax support! This was neat; now we could see rendered math while reading
abstracts and titles! I think <a href="https://arxiv.org/">arXiv.org</a> only added this
feature a few years ago.</p>
<p>But, aside from this very minor hacking on the code, I immediately started
finding SciRate actually useful! I could browse it every day; see which papers
would pop up, and track papers I was interested in. Fairly quickly, it became
a very addictive habit for me. I began to learn the time of day that it would
update, and made sure I would scour the website shortly after to browse the
“freshest” papers.</p>
<p>I did this for several years (actually, I only stopped recently, maybe a few
months ago). I read many papers (but not every one that I would “scite”);
made several nice connections, and even used my personal SciRate data to teach
my first deep learning workshops. SciRate stuck with me as my interests varied
from quantum computing, theoretical physics, black holes, philosophy, AI, deep
learning, computer vision, generative art, category theory, astrophysics, and
the stranger maths papers. For a while my favourite thing was discovering the
“best paper title” of the week.</p>
<p>The most memorable moment was when, many years later (after the scirate3
re-write), I met people who “knew” me from SciRate, only because they had
seen that I would “scite” a lot of papers (in fact, someone told me that they
didn’t think I was a real person; only a scite-making bot.) To date, <a href="https://scirate.com/noonsilk">I’ve
amassed more than one hundred thousand “scites”</a>.
And yes, most of this was done by clicking manually; but in the last year or
two I’ve used a custom program I wrote: <a href="https://github.com/silky/scirate-cli">the
scirate-cli</a>.</p>
<p>In any case, by a very strange coincidence, during my Masters program I
happened to learn that SciRate was undergoing a re-write, amazingly by a
company based in Melbourne (where I lived); just down the road from my
university! I happened to have a conversation with the founder of that
company, <a href="https://bentoner.com/">Ben Toner</a>, relating to my masters project,
but it was a curious connection.</p>
<p>That re-write ended up going, in my view, quite well. But I think, at some
point, it stopped being funded, and fell on the shoulders of
<a href="https://github.com/mispy-archive">mispy</a>. Mispy funded SciRate for a while,
out of their own pocket, until I decided to take it over from them.</p>
<p>That was, now, 5 years ago.</p>
<p>All I’ve really been doing in the mean time is keeping things afloat.
Upgrading the various packages as is required; managing the server, and
the occasional bugfixes.</p>
<p>The only interesting thing I did, in recent times, was to <a href="https://github.com/scirate/scirate/commit/2e7ecbce9ee6db4d70d88597b61b6b2101968ba9">add a “jobs”
feature</a>
to SciRate. This was actually moderately successful, but in the end it was
more effort for me to maintain than it was worth, so I disabled it.</p>
<h4 id="current">Current</h4>
<p>SciRate needs a new maintainer. I’ve decided that, personally, my focus has to
shift elsewhere. You can read about that in the <a href="#addendum">Addendum</a> below.</p>
<p>Here’s what you’ll need to do:</p>
<ol type="1">
<li>Take ownership of the <a href="https://github.com/scirate/scirate">scirate</a>
repository,</li>
<li>Update the codebase occasionally, maintain deployments, fix the occasional
bug,</li>
<li>Manage the error emails that come in,</li>
<li>Restart the server when it dies,</li>
<li>???</li>
<li><strong>Extend it in interesting ways!</strong></li>
</ol>
<p>The last one is actually quite important! SciRate has lacked any real new
features for a very long time; but there’s certainly some interesting things
that could be done! Notable among them could be:</p>
<ul>
<li><a href="https://github.com/scirate/scirate/issues/366">Support for “reading groups”</a>,</li>
<li><a href="https://github.com/scirate/scirate/issues/382">A recommendation engine</a>,</li>
<li>…?</li>
</ul>
<p>The world is (somewhat) your oyster. Clearly there are some rules on how we’d
like SciRate to develop; after all, there is a solid and growing user base,
who have some expectation on how it will operate.</p>
<p>In any case, if you’re interested in getting involved, reach out to
<a href="https://web.mit.edu/aram/www">Aram</a> and myself by sending us an email:</p>
<ul>
<li><a href="mailto:[email protected]">[email protected]</a></li>
<li><a href="mailto:[email protected]">[email protected]</a></li>
</ul>
<p>We’d love to hear from you.</p>
<hr />
<h4 id="addendum">Addendum <a name="addendum"></a></h4>
<p>The central reason I’ve decided to stop spending time on SciRate is because of
the climate emergency. I’ve been reading <a href="https://betweenbooks.com.au/tags/climate.html">a lot of
books</a> and it’s become
increasingly important to me to spend my energy learning more and doing more
(<a href="https://en.wikipedia.org/wiki/Jevons_paradox">or less!</a>) in this space. If
you’re interested in this too, then please reach out; I’d love to chat!</p>
]]></summary>
</entry>
<entry>
<title>You Have Already Accomplished Everything</title>
<link href="https://silky.github.io/posts/everything.html" />
<id>https://silky.github.io/posts/everything.html</id>
<published>2022-03-16T00:00:00Z</published>
<updated>2022-03-16T00:00:00Z</updated>
<summary type="html"><![CDATA[<div class="info">
Posted on March 16, 2022
by Noon van der Silk
</div>
<p>You were born, cried, learned, made friends, and talked to no-one.</p>
<p>You have survived off the land; launched a startup (the best one), managed
thousands of people, and never been able to get a job, no matter what your
resume says or how you change your name.</p>
<p>You have travelled; and you have lived alone, isolated, and cold.</p>
<p>You have been the best and succeeded all your life.</p>
<p>You have failed; only, just missed out, and never tried again.</p>
<p>You made people happy; shown them the best time, given them everything, and
hurt them, taken it all for yourself, and killed them.</p>
<p>You have died after every breath, and before your first.</p>
<p>You have already accomplished everything.</p>
<p>What do you want to do next?</p>
]]></summary>
</entry>
<entry>
<title>☐ He died with a todo list in his hand ...</title>
<link href="https://silky.github.io/posts/died-todo-list.html" />
<id>https://silky.github.io/posts/died-todo-list.html</id>
<published>2021-06-03T00:00:00Z</published>
<updated>2021-06-03T00:00:00Z</updated>
<summary type="html"><![CDATA[<div class="info">
Posted on June 3, 2021
by Noon van der Silk
</div>
<center>
<img width="600" src="/images/todo-list.png"/>
<br />
<a href="https://www.imdb.com/title/tt0172543/">A classic Australian
movie</a>:
A nightmare chase through hell in a never-ending, unrequited daisy chain of
desire… .
</center>
<p>What is time? How do we measure a life? How many things did you get done
today? What are you working on tomorrow!? Can you come hang out on Sunday!!?</p>
<hr />
<p>Recently, and also always, I’ve been thinking about how to manage a list of
todos. During an internal knowledge-sharing session <a href="https://www.tweag.io/">at
work</a> I was prompted to reflect on all the different
schemes I’ve tried:</p>
<ul>
<li>Random pieces of paper</li>
<li><a href="https://en.wikipedia.org/wiki/Microsoft_Notepad">Notepad</a></li>
<li><a href="https://www.youtube.com/watch?v=fZj0WLxj-T0">Windows sticky notes</a></li>
<li><a href="https://tiddlywiki.com/">Tiddlywiki</a></li>
<li><a href="https://www.mediawiki.org/wiki/MediaWiki">Mediawiki</a></li>
<li><a href="https://en.wikipedia.org/wiki/Jira_(software)">Jira</a></li>
<li><a href="https://www.phpbb.com/">phpBB</a> and other misc BBS software</li>
<li><a href="https://www.vim.org/">Vim</a></li>
<li><a href="https://github.com/romainl/vim-qf">Vim quickfix window</a></li>
<li><a href="https://github.com/silky/utils/tree/master/find-todo">A terrible custom python script</a></li>
<li><a href="https://github.com/vimwiki/vimwiki">Vimwiki</a></li>
<li>Text files</li>
<li><a href="https://orgmode.org/">Org-Mode</a> (I gave up almost immediately)</li>
<li>Emails to myself</li>
<li>A private mailing list I made up</li>
<li><a href="https://en.wikipedia.org/wiki/Pomodoro_Technique">Pomodoro</a></li>
<li><a href="https://github.com/silky/ideas/issues">Github issues</a></li>
<li><a href="https://en.wikipedia.org/wiki/Trello">Trello</a></li>
<li><a href="https://www.notion.so/">Notion</a></li>
<li><a href="https://asana.com/">Asana</a></li>
<li><a href="https://en.wikipedia.org/wiki/README">Readme files</a></li>
<li><a href="https://taskwarrior.org/">Taskwarrior</a></li>
<li><a href="https://bulletjournal.com/pages/learn">Bullet journal</a> (for <4 minutes)</li>
<li>Physical notebooks</li>
<li>Fancy notebooks</li>
<li>Cheap notebooks</li>
<li><a href="https://en.wikipedia.org/wiki/Kanban_board">Physical ‘kanban’ cards</a></li>
<li><a href="https://github.com/silky/ideas#complete">A whiteboard</a></li>
<li>My head</li>
<li>Nothing</li>
<li>Random pieces of paper</li>
</ul>
<p>Right now I’m back to a whiteboard (by luck I happen to have one behind me
where I work), and ‘todo’ notes in code + github issues.</p>
<hr />
<p>My friend Ruth told me something that perhaps is very obvious but was also
surprisingly calming to me: You’ll die with items on your todo list. So don’t
worry about it!</p>
<p>I think there’s a few ways to think about this:</p>
<ol type="1">
<li>The optimisic view: Amazing that I am lucky enough to have things I intend
to do and look forward to!</li>
<li>The pessimistic view: Sad that I had goals that I was never able to
achieve!</li>
<li>The Buddhist view: Your big mistake is having desires at all!</li>
</ol>
<p>I want to live around option (3) and (1) at the moment, but of course option
(2) is a very very strong driving force; and often necessary (for example, at
work!); the only time I was brave enough to enact option (3) at a work
setting was when <a href="https://braneshop.com.au/posts/Braneshop-A-Living-Business-Part-1.html">I ran my own
business</a>!</p>
<p>Another interesting thing that came up as part of the work discussion was that
in some ways what you want to do depends on your mood. No doubt! So … maybe
mood can be a parameter?!</p>
<hr />
<p>I think, secretly, for the rest of my life, I will believe that there is a True
answer out there; an ultimate organisation scheme; the Four-Fold path to Life
Efficiency: Right Editing, Right Organisation, Right Workflow and Right
History.</p>
<p>But I also think that I should never think about this again. But on the other
hand, I was inspired at the talk today; so I might give task-warrior another
go.</p>
<p>But, you didn’t come here for that! Maybe you came here for advice? So, here
it is (it’s not even my advice! Gala claims it’s her idea which is probably
true):</p>
<blockquote>
<p>If you can, don’t even write the thing down; just do it immediately, or,
alternatively, convince yourself you don’t need to think about it now.</p>
</blockquote>
<p>Maybe it’s part of my personality, but this works <em>surprisingly</em> well for me.
Especially if it’s something that I’m working on with someone else; instead of
delaying my part, I can just try and make as much progress as I can
immediately, and send it back to the other person! Another way of saying this:
I can offset storing my todo list to you!</p>
<p>I find this idea to be quite operaitonal; I often find myself using this rule
to do something sooner rather than later.</p>
<p>Here’s one thing I know about myself: <a href="https://scirate.com/noonsilk">I can’t be trusted with
lists</a>. I get a
bit obsessed with organising them. So I’m trying to avoid them these days.</p>
]]></summary>
</entry>
<entry>
<title>2020 Books</title>
<link href="https://silky.github.io/posts/2020-books.html" />
<id>https://silky.github.io/posts/2020-books.html</id>
<published>2021-02-14T00:00:00Z</published>
<updated>2021-02-14T00:00:00Z</updated>
<summary type="html"><![CDATA[<div class="info">
Posted on February 14, 2021
by Noon van der Silk
</div>
<style type="text/css">
div.book {
display: flex;
flex-direction: row;
padding: 10px;
}
div.book img { margin-right: 10px; width: 150px; }
div.alt { background: #eaeaea; }
</style>
<p>Continuing the tradition <a href="/posts/2019-01-03-2018-books.html">started in 2018</a>,
continued in 2019 <a href="https://braneshop.com.au/posts/2019-Books.html">over on the Braneshop
blog</a>, I was
reminded I haven’t posted the books I read in 2020 yet.</p>
<p>So, here we are:</p>
<div class="book">
<div class="img">
<img src="/images/2020-reading/how-long-til-black-future-month.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/40855636-how-long-til-black-future-month">How Long ’til Black Future Month?</a></strong> by Jemisin, N.K.</p>
<p>As a big fan of N.K. Jemisin I just wanted to read more of what she’d written.
This is good for that; it’s a really nice dip-in to the worlds she has created
and leaves you wanting more!</p>
</div>
</div>
<div class="book alt">
<div class="img">
<img src="/images/2020-reading/gravitys-century.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/40010687-gravity-s-century">Gravity’s Century: From Einstein’s Eclipse to Images of Black Holes</a></strong> by Cowen, Ron</p>
<p>Pretty good. This was a nice history of black holes and an introduction to
some of the pressing issues presently.</p>
</div>
</div>
<div class="book">
<div class="img">
<img src="/images/2020-reading/the-cloudspotters-guide.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/174372.The_Cloudspotter_s_Guide">The Cloudspotter’s Guide</a></strong> by Pretor-Pinney, Gavin</p>
<p>I picked this up after starting (but not finishing) <a href="https://www.goodreads.com/book/show/8474155-the-wavewatcher-s-companion">The Wavewatcher’s
Companion</a>,
which I found to be hilarious. This book was not as funny, but was still
pretty good. Gavin has a very nice way of appreciating the world.</p>
</div>
</div>
<div class="book alt">
<div class="img">
<img src="/images/2020-reading/altruism.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/22208239-altruism">Altruism: The Power of Compassion to Change Yourself and the World</a></strong> by Ricard, Matthieu</p>
<p>I really quite enjoyed this book, and infact wrote a longer review over on the
<a href="https://betweenbooks.com.au/reviews/2020/altruism-matthieu-ricard-2015.html">Between
Books</a>
website.</p>
</div>
</div>
<div class="book">
<div class="img">
<img src="/images/2020-reading/girl-woman-other.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/41081373-girl-woman-other">Girl, Woman, Other</a></strong> by Evaristo, Bernardine</p>
<p>A nice collection of stories featuring different women and how their lives
intersect. I think it’s quite nice to get so many stories from the everyday
lives of women; especially for me, for whom it’s a bit unknown territory.</p>
</div>
</div>
<div class="book alt">
<div class="img">
<img src="/images/2020-reading/the-white-album.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/421.The_White_Album">The White Album</a></strong> by Didion, Joan</p>
<p>The first Joan Didion book I’ve read. She’s very famous of course; and I don’t
know. It was good to read; but was it objectionably good? Maybe. It’s at least
nice to know a bit about her life and how she writes. I’ll probably read more.</p>
</div>
</div>
<div class="book">
<div class="img">
<img src="/images/2020-reading/mullumbimby.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/17319691-mullumbimby">Mullumbimby</a></strong> by Lucashenko, Melissa</p>
<p>I quite enjoyed this story. It’s also the first time I’ve read a modern
fictional Australian indigenous-centered story. Will be on the look out for
more books of this kind! Came up as part of the <a href="https://ochouse.com.au/">OC
House</a> bookclub, I think.</p>
</div>
</div>
<div class="book alt">
<div class="img">
<img src="/images/2020-reading/down-girl.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/34640834-down-girl">Down Girl: The Logic of Misogyny</a></strong> by Manne, Kate</p>
<p>This book is amazing. I found it to be written in a bit of an academic-y
style; so it can be a bit dense, but it does an amazing job of framing what
misogyny is and how it is present in all aspects of society.</p>
</div>
</div>
<div class="book">
<div class="img">
<img src="/images/2020-reading/unfree-speech.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/49964359-unfree-speech">Unfree Speech: The Threat to Global Democracy and Why We Must Act, Now</a></strong> by Wong, Joshua</p>
<p>This is a nice short history of free speech and how China is taking over Hong
Kong. It was interesting to read about how they attempted to make some large
changes to their democracy through grass-roots organisation. In some ways
quite inspiring, but also a reality check that it isn’t easy to defeat power.
Worth a read.</p>
</div>
</div>
<div class="book alt">
<div class="img">
<img src="/images/2020-reading/a-month-in-siena.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/43783430-a-month-in-siena">A Month in Siena</a></strong> by Matar, Hisham</p>
<p>This was just a nice simple book about someone getting amongst life in a new
town. In many ways I think this kind of experience is how many people wish
their holidays to go: meeting some nice stranger, integrating into the
community, and just appreciating the joy of life.</p>
</div>
</div>
<div class="book">
<div class="img">
<img src="/images/2020-reading/the-weil-conjectures.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/41940441-the-weil-conjectures">The Weil Conjectures: On Math and the Pursuit of the Unknown</a></strong> by Olsson, Karen</p>
<p>I can’t remember much about this book at this point; I think I enjoyed it.</p>
</div>
</div>
<div class="book alt">
<div class="img">
<img src="/images/2020-reading/the-worst-journey-in-the-world.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/48503.The_Worst_Journey_in_the_World">The Worst Journey in the World</a></strong> by Cherry-Garrard, Apsley</p>
<p>I read the next two books back-to-back. This one was strange. It’s written
from the English perspective; it’s quite racist at times. I wouldn’t recommend
reading it, unless you really want to compare perspectives on the journeys of
Scott and Amundsen.</p>
</div>
</div>
<div class="book">
<div class="img">
<img src="/images/2020-reading/the-last-place-on-earth.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/549488.The_Last_Place_on_Earth">The Last Place on Earth: Scott and Amundsen’s Race to the South Pole</a></strong> by Huntford, Roland</p>
<p>This was a really interesting read. It was so fascinating to compare how
Amundsen approached the journey compared to Scott. According to this book,
Scott was woefully underprepared and arrogant, and Amundsen spent many many
years training and learning the right skills from different indigenous groups
in order to survive.</p>
<p>If you want to learn about the race to the south pole; this book is definitely
better than the above.</p>
</div>
</div>
<div class="book alt">
<div class="img">
<img src="/images/2020-reading/food-rules.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/7015635-food-rules">Food Rules: An Eater’s Manual</a></strong> by Pollan, Michael</p>
<p>More of a blog post than a book; but still, nice to keep next to you somewhere
when you want to remember if it’s okay to eat chocolate everyday (probably
not) or have a wine with dinner (probably fine).</p>
</div>
</div>
<div class="book">
<div class="img">
<img src="/images/2020-reading/men-explain-things-to-me.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/18528190-men-explain-things-to-me">Men Explain Things to Me</a></strong> by Solnit, Rebecca</p>
<p>Hilarious. This is a collection of stories; some funnier than others, but
overall great.</p>
</div>
</div>
<div class="book alt">
<div class="img">
<img src="/images/2020-reading/the-shadow-of-the-sun.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/9541.The_Shadow_of_the_Sun">The Shadow of the Sun</a></strong> by Kapuściński, Ryszard</p>
<p>I enjoyed this as a nice way to get a bit of, albeit an outsiders, insight
into how different people live in some of the poorer parts of Africa.</p>
</div>
</div>
<div class="book">
<div class="img">
<img src="/images/2020-reading/capital-and-ideology.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/50849430-capital-and-ideology">Capital and Ideology</a></strong> by Piketty, Thomas</p>
<p>I really enjoyed this book, and wrote about it more over on <a href="https://betweenbooks.com.au/reviews/2020/capital-and-ideology-thomas-piketty-2020.html">Between
Books - Capital and Ideology</a></p>
</div>
</div>
<div class="book alt">
<div class="img">
<img src="/images/2020-reading/capital-in-the-twenty-first-century.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/18736925-capital-in-the-twenty-first-century">Capital in the Twenty-First Century</a></strong> by Piketty, Thomas</p>
<p>This one I also enjoyed; I don’t think you really need to read it first before
Ideology, but I opted to do so. Reading this really inspired a love and
interest of economics, and Piketty seems to do an amazing job of exploring
these topics in an approachable way.</p>
</div>
</div>
<div class="book">
<div class="img">
<img src="/images/2020-reading/affluence-without-abundance.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/31451192-affluence-without-abundance">Affluence Without Abundance: The Disappearing World of the Bushmen</a></strong> by Suzman, James</p>
<p>This book wasn’t bad; it’s an exploration of life with a marginalised tribe
referred to as the Bushmen. It doesn’t totally take the expected view that the
simple life is better; but it does discuss how politics and the community
encroaches on this tribe, and how they live life.</p>
</div>
</div>
<div class="book alt">
<div class="img">
<img src="/images/2020-reading/a-woman-in-the-polar-night.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/8266887-a-woman-in-the-polar-night">A Woman in the Polar Night</a></strong> by Ritter, Christiane</p>
<p>I think this is a classic book; it’s a little strange, but it does show one
persons journey into the Arctic and how she learned to love it. It didn’t
exactly inspire me to go and life there, but I do admire her approach!</p>
</div>
</div>
<div class="book">
<div class="img">
<img src="/images/2020-reading/touching-the-void.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/18600.Touching_the_Void">Touching the Void: The True Story of One Man’s Miraculous Survival</a></strong> by Simpson, Joe</p>
<p>This is amazing. I read this assuming a particular fact about the story (I
won’t spoil it by telling you), but it turned out that my mind was blown by
what actually happened. I’ll probably read it again!</p>
</div>
</div>
<div class="book alt">
<div class="img">
<img src="/images/2020-reading/into-thin-air.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/1898.Into_Thin_Air">Into Thin Air: A Personal Account of the Mount Everest Disaster</a></strong> by Krakauer, Jon</p>
<p>I bought this I think after the one above; desperate for more books about
climbing. This is also an amazing story; I think if anything it made me feel
certain that I’ll never attempt to climb Everest.</p>
</div>
</div>
<div class="book">
<div class="img">
<img src="/images/2020-reading/honjin.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/5863774-the-case-of-the-honjin-murder">The Case of the Honjin Murder</a></strong> by Yokomizo, Seishi</p>
<p>I just happened across this one in the bookshop and thought I’d give it a go.
I can’t say it was the best; it was quite sexist. The story was probably
pretty good, if you could ignore that; but I couldn’t.</p>
</div>
</div>
<div class="book alt">
<div class="img">
<img src="/images/2020-reading/tall-man.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/3901371-tall-man">Tall Man: The Death of Doomadgee</a></strong> by Hooper, Chloe</p>
<p>This was a good read but super aggravating. It’s really unsettling to learn
how terrible some of the policing is; and the subsequent investigations that
yielded no useful outcome. Eye-opening for me in terms of how bad racism is in
Australia.</p>
</div>
</div>
<div class="book">
<div class="img">
<img src="/images/2020-reading/mountains-of-the-mind.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/839157.Mountains_of_the_Mind">Mountains of the Mind: A History of a Fascination</a></strong> by Macfarlane, Robert</p>
<p>Pretty good. I went through a phase of reading about mountain climbing. This
was a nice little overview of how people justify climbing. Good for an
introduction to other things to read.</p>
</div>
</div>
<div class="book alt">
<div class="img">
<img src="/images/2020-reading/the-city-we-became.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/42074525-the-city-we-became">The City We Became (Great Cities, #1)</a></strong> by Jemisin, N.K.</p>
<p>For how much I loved her other books; I have to say I found this one a bit
disappointing. I think by normal sci-fi standards, it’s certainly excellent,
and I’ll definitely read the rest of the series; but if you’re looking for
something as amazing as her other books, you might not find it here.</p>
</div>
</div>
<div class="book">
<div class="img">
<img src="/images/2020-reading/annapurna.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/306659.Annapurna">Annapurna: A Woman’s Place</a></strong> by Blum, Arlene</p>
<p>I really enjoyed this one. It was interesting to compare this to other
climbing books written by men, which almost never feature much uncertainty or
collaborative leadership.</p>
</div>
</div>
<div class="book alt">
<div class="img">
<img src="/images/2020-reading/underland.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/41817481-underland">Underland: A Deep Time Journey</a></strong> by Macfarlane, Robert</p>
<p>This is just super cool. We are taken on a journey through lots of different
underground worlds. Certainly makes you want to do this kind of exploring.</p>
</div>
</div>
<div class="book">
<div class="img">
<img src="/images/2020-reading/the-eastern-curlew.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/41011110-the-eastern-curlew">The Eastern Curlew</a></strong> by Saddler, Harry</p>
<p>I read this after meeting the author at a party! I felt so cool; I’d never met
an author in real life before. Inspired by that meeting, I picked it up. It’s
really a nice story about following the migratory path of a bird, and thinking
about how their ecosystem is being impacted. Would definitely recommend!</p>
</div>
</div>
<div class="book alt">
<div class="img">
<img src="/images/2020-reading/her-body-and-other-parties.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/33375622-her-body-and-other-parties">Her Body and Other Parties</a></strong> by Machado, Carmen Maria</p>
<p>Not bad. Probably not my favourite style of book, but if you like weird kind
of magical fiction with a message, probably quite good.</p>
</div>
</div>
<div class="book">
<div class="img">
<img src="/images/2020-reading/my-sister-the-serial-killer.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/38819868-my-sister-the-serial-killer">My Sister, the Serial Killer</a></strong> by Braithwaite, Oyinkan</p>
<p>I quite enjoyed this one; it was a very quick read; so I’m looking forward to
more by this author!</p>
</div>
</div>
<div class="book alt">
<div class="img">
<img src="/images/2020-reading/in-praise-of-shadows.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/34473.In_Praise_of_Shadows">In Praise of Shadows</a></strong> by Tanizaki, Jun’ichirō</p>
<p>Pretty good. Very very short; but a thoughtful analysis of how light impacts
space. I think it’s a classic of the architecture world.</p>
</div>
</div>
<div class="book">
<div class="img">
<img src="/images/2020-reading/barbarian-days.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/18693910-barbarian-days">Barbarian Days: A Surfing Life</a></strong> by Finnegan, William</p>
<p>I really really enjoyed this one. Very nicely written, you feel like you’re
living the life alongside the author. It’s nice to read about someone who
follows their passion so directly.</p>
</div>
</div>
<div class="book alt">
<div class="img">
<img src="/images/2020-reading/why-im-no-longer-talking-to-white-people-about-race.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/33606119-why-i-m-no-longer-talking-to-white-people-about-race">Why I’m No Longer Talking to White People About Race</a></strong> by Eddo-Lodge, Reni</p>
<p>I picked this up as soon as I arrived in the UK, to gain an understanding for
how people here think about race issues. Pretty good reading.</p>
</div>
</div>
<div class="book">
<div class="img">
<img src="/images/2020-reading/kon-tiki.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/790171.Kon_Tiki">Kon-Tiki</a></strong> by Heyerdahl, Thor</p>
<p>This was a funny one. A classic kind of adventure story, from real life, I
have to say I enjoyed it.</p>
</div>
</div>
<div class="book alt">
<div class="img">
<img src="/images/2020-reading/mad-bad-dangerous-to-know.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/2060190.Mad_Bad_Dangerous_to_Know">Mad, Bad & Dangerous to Know: The Autobiography</a></strong> by Fiennes, Ranulph</p>
<p>I found this one also kind of funny. I suppose this guy is very famous in the
UK, but I’d not heard of him really. It’s funny to read about how he thinks of
endurance, and his claim that “anyone” can be like him; in terms of running 7
marathons at the age of 70 across 7 countries; or something along those lines.
Didn’t exactly encourage me to do the same, but did give me some food for
thought about willpower and energy.</p>
</div>
</div>
<div class="book">
<div class="img">
<img src="/images/2020-reading/see-what-you-made-me-do.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/43800661-see-what-you-made-me-do">See What You Made Me Do: Power, Control and Domestic Violence</a></strong> by Hill, Jess</p>
<p>This is a very hard book to read, emotionally. It contains some exceptionally
difficult stories. Definitely recommended reading, but if you want a more
academic treatment see the earlier book by Kate Manne.</p>
</div>
</div>
<div class="book alt">
<div class="img">
<img src="/images/2020-reading/becoming-bodhisattvas.jpg" />
</div>
<div class="text">
<p><strong><a href="https://www.goodreads.com//book/show/40669652-becoming-bodhisattvas">Becoming Bodhisattvas</a></strong> by Chödrön, Pema</p>
<p>Easily the best book I read last year. Of course it’s a buddhist view on how
to live life; but I found it very practical and thoughtful. I’ve read it again
during some difficult times, and found it very uplifting.</p>
</div>
</div>
]]></summary>
</entry>
<entry>
<title>New job; moving to Cambridge!</title>
<link href="https://silky.github.io/posts/melbourne-cambridge.html" />
<id>https://silky.github.io/posts/melbourne-cambridge.html</id>
<published>2020-10-12T00:00:00Z</published>
<updated>2020-10-12T00:00:00Z</updated>
<summary type="html"><![CDATA[<div class="info">
Posted on October 12, 2020
by Noon van der Silk
</div>
<p>So, I’m very excited to share that we’re moving overseas! We’re headed to
Cambridge in the UK at the end of this month.</p>
<p>I’m very lucky to be starting work with a very cool quantum computing company:
<a href="https://www.riverlane.com/">Riverlane</a>.</p>
<h2 id="leaving-melbourne">Leaving Melbourne</h2>
<p>It’s going to be interesting leaving Melbourne. I’ve lived here all my life
basically, and I’ve found a really nice group of friends. I’m going to miss
everyone.</p>
<p>I owe a big thanks to <strong>everyone</strong> that’s helped me in my career and life over the
years here. I won’t list all of you, but thanks :) I wouldn’t be where I am if
I hadn’t had your help and support. ❤️ 💖</p>
<p>In particular the meetup community has been a great place for me and somewhere
I was able to forge some really strong friendships. Specifically, I’ve had a
great time at the Melbourne Maths and Science Meetup, the Haskell Meetup, back
in the day I loved MXUG, and of course I have to thank my friend David Kemp
for being the only consistent attendee of the Quantum Lunch, started way back
in the day! I’ll also miss hanging out with the cool people who’ve come to
events I’ve helped organise, such as <a href="https://www.composeconference.org/2016-melbourne/">compose
conference</a> and
<a href="https://postpredictionconference.github.io/">post-prediction conference</a>. I
love Melbourne for the really nice connection you get between different
communities, and it’s been some of my favourite times meeting people from
outside my standard little bubble.</p>
<p>I also have to thank my friend Charles Hill from Melbourne University, who
taught me so much about quantum computing, is an amazing researcher and
very kind and generous person.</p>