blog-roll.md (16217B)
1 This is a list of blog-ish websites where I found insightful stuff 2 that I would like not to forget. 3 4 # [Bartosz Ciechanowski](https://ciechanow.ski/) 5 6 ## [Alpha Compositing] 7 8 The good, bad and ugly of how we discretize colors, and 9 color-blending. With helpful interactive simulations. 10 11 [Alpha Compositing]: https://ciechanow.ski/alpha-compositing/ 12 13 # [Evanmiller.org](https://www.evanmiller.org/) 14 15 I mostly only read the articles dealing with programming languages. 16 The down-to-earth commentary made me feel like the author both 17 appreciates the thought process that went into the design, and has 18 enough hindsight to find where that thought process fell short. 19 20 ## [A Taste of Rust] 21 22 An overview of some of the language's features. Some comments 23 resonated particularly well with me, e.g. on nested functions: 24 25 > With other languages, I’m never quite sure where to put helper 26 > functions. I’m usually wary of factoring code into small, 27 > “beautiful” functions because I’m afraid they’ll end up under the 28 > couch cushions, or behind the radiator next to my car keys. With 29 > Rust, I can build up a kind of organic tree of function definitions, 30 > each scoped to the place where they’re actually going to be used, 31 > and promote them up the tree as they take on the Platonic form of 32 > Reusable Code. 33 34 [A Taste of Rust]: https://www.evanmiller.org/a-taste-of-rust.html 35 36 # [fasterthanli.me](https://fasterthanli.me/) 37 38 :::: tags 39 - Rust 40 - Go 41 - Language design 42 :::: 43 44 In-depth explorations of various topics (I mostly read posts covering 45 programming language mechanics), told in a dialectic and very 46 entertaining style that sustains interest over their Homeric lengths. 47 48 ## [What's in the box?](https://fasterthanli.me/articles/whats-in-the-box) 49 50 :::: tags 51 - Rust 52 - Go 53 :::: 54 55 > The Rust compiler is trying to help us. "You can't just return a 56 > reference to something", it pleads. "You need to tell me how long 57 > the thing that's referenced is will live". 58 59 > * How does one return different error types without forcing a heap 60 > allocation? 61 62 … preferably without having to maintain an ever-shifting enumeration 63 of possible error types? 64 65 Spoiler: there's no escaping the `enum`, but at least 66 [`thiserror`](https://lib.rs/crates/thiserror) lets us focus on *just* 67 the enumeration, and generates the boilerplate for the `Display` and 68 `From` traits. 69 70 # [Et tu, Cthulhu](https://hpjansson.org/blag/) 71 72 ## [A hash table re-hash] 73 74 A benchmark of hash tables that manages to succinctly explain common 75 performance issues and tradeoffs with this data structure, to show 76 results across a wide range of implementations, and to provide very 77 understandable interepretations for those results. 78 79 [A hash table re-hash]: https://hpjansson.org/blag/2018/07/24/a-hash-table-re-hash/ 80 81 # [Joe Duffy's Blog](http://joeduffyblog.com/) 82 83 ## [The Error Model] 84 85 An in-depth look at what "errors" are in the context of software, how 86 some languages choose to deal with them, and what model the Midori 87 team implemented. 88 89 > Our overall solution was to offer a two-pronged error model. On one 90 > hand, you had fail-fast – we called it abandonment – for programming 91 > bugs. And on the other hand, you had statically checked exceptions 92 > for recoverable errors. 93 94 Starts by outlining the "performance metrics" for a good error model, 95 then goes over unsatisfactory models: 96 97 - **Error codes** clutter a function's signature with an extra return 98 value, and the resulting branches degrade performance; they do not 99 interrupt execution unless checked manually, thus when bugs finally 100 show up, it can be hard to track their origin down. 101 - Though the Midori team did provide their developers with an 102 escape hatch that lets them ignore return values, their `ignore` 103 keyword is at least auditable. 104 105 - **Unchecked exceptions** make it hard to reason about a program's 106 flow. They persist because in the grand scheme of things, they stay 107 out of the way When Things Work™. 108 109 - **Exceptions in general** tend to come with some performance baggage 110 (e.g. symbols for stack traces), and encourage coarse error-handling 111 (i.e. throwing a `try` blanket spanning several statements instead 112 of focusing on individual calls). 113 114 All of these models conflate *recoverable errors* (e.g. invalid 115 program inputs) that the application can act on (by telling users 116 about their mistakes, assuming a transient environment failure and 117 re-trying, or ignoring the error) with *bugs*, i.e. unexpected 118 conditions that, when unhandled, create bogus states and transitions 119 in the program, and may only have visible impacts further down the 120 line. 121 122 As these bugs are "unrecoverable", the team chose the 123 "**abandonment**" strategy (aka "fail-fast") to deal with them. 124 125 > My impression is that, largely because of the continued success of 126 > monolithic kernels, the world at large hasn’t yet made the leap to 127 > “operating system as a distributed system” insight. Once you do, 128 > however, a lot of design principles become apparent. 129 130 > As with most distributed systems, our architecture assumed process 131 > failure was inevitable. 132 133 The micro-kernel architecture, where basic kernel features such as 134 "the scheduler, memory manager, filesystem, networking stack, and even 135 device drivers" are all run as isolated user-mode processes, 136 encourages "wholesale abandonment" as an error-handling stragegy, 137 since the failure remains contained and does not bring down the whole 138 system. 139 140 They implemented **contracts** using dedicated syntax and made them 141 part of a function's interface. Delegating contract-checking to a 142 library would have buried pre- and post-conditions as regular calls 143 inside a function's definition, whereas they wanted them to become 144 part of the function's metadata, where they can be analyzed by 145 optimizers, IDEs, etc. 146 147 > Contracts begin where the type system leaves off. 148 149 Contract violations trigger (at worst) program abandonment; 150 **type-system** violations plainly prevent the program from existing. 151 152 Since "90%" of their contracts were either null or range checks, they 153 found a way to encode nullability and ranges in the type-system, 154 reducing this: 155 156 public virtual int Read(char[] buffer, int index, int count) 157 requires buffer != null 158 requires index >= 0 159 requires count >= 0 160 requires buffer.Length - index < count { 161 ... 162 } 163 164 To this: 165 166 public virtual int Read(char[] buffer) { 167 ... 168 } 169 170 While preserving the same guarantees, checked at compile-time. 171 172 **Nullable** types were designated with `T?`; `T` implicitly converted 173 to `T?`, but conversion from `T?` to `T` required noisy 174 (i.e. auditable) operators which would trigger abandonment when 175 needed. 176 177 *Recoverable errors* were handled with checked exceptions, which were 178 part of a function's signature. Since most bugs were dealt with 179 through abandonment, most of their APIs didn't throw. 180 181 To make it easier to reason about control flow, callers had to 182 explicitly say `try` before calling a function that might throw, which 183 did what Rust's deprecated `try!()` did: yield the return value on the 184 happy path, else re-throw. 185 186 Covers performance concerns, composition with concurrency; muddies the 187 waters somewhat with "aborts" which kind of look like `longjmp`s to 188 me? Except it runs the code in `catch` blocks it finds while crawling 189 back the stack? 190 191 [The Error Model]: http://joeduffyblog.com/2016/02/07/the-error-model/ 192 193 # [Julia Evans](https://jvns.ca/) 194 195 Laconically, ["XKCD's Simple Writer"](https://xkcd.com/simplewriter/) for programmers. 196 197 Lures me in with Yotsuba-like "Wonder!" and "PUZZLEMENT", then pulls 198 `strace`s and `/proc` dumps on me; by the end of the articles, I often 199 learned about (a) the article's stated topic (b) very useful tools I 200 might not otherwise reach for, that are actually broadly applicable to 201 everyday sysadmin life. 202 203 Article structure emphasizes both "the layperson experience" and "the 204 scientist's survival guide to computers": observations are made, 205 questions are asked (readers are polled), hypotheses are made, 206 experiments are conducted; final statements are wrapped in a neat 207 little bow with authoritative documentation. 208 209 Sample topics: 210 211 - [Git:](https://jvns.ca/categories/git/) it's not just you; Git _does_ take time to grok, what with 212 the [extensive terminology](https://jvns.ca/blog/2023/11/01/confusing-git-terminology/) it throws at you, its confusing 213 notion of [branches](https://jvns.ca/blog/2023/11/23/branches-intuition-reality/) (backed [by survey](https://jvns.ca/blog/2024/03/28/git-poll-results/#branches)) and [commits](https://jvns.ca/blog/2024/01/05/do-we-think-of-git-commits-as-diffs--snapshots--or-histories/). 214 215 - [Terminals:](https://jvns.ca/categories/terminal/) tracing [the journey of a keypress](https://jvns.ca/blog/2022/07/20/pseudoterminals/), finding uses 216 for [job control](https://jvns.ca/blog/2024/07/03/reasons-to-use-job-control/), untangling [CLI app conventions](https://jvns.ca/blog/2024/11/26/terminal-rules/) from the 217 OS, the shell & the terminal emulator's features, exposing [the 218 kerfuffle](https://jvns.ca/blog/2025/01/11/getting-a-modern-terminal-setup/) that holds the [modern]{.wow} terminal experience 219 together. 220 221 - Also, communication & culture: write a [brag document](https://jvns.ca/blog/brag-documents/), help your 222 manager [help you](https://jvns.ca/blog/things-your-manager-might-not-know/), chill about [opensource](https://jvns.ca/blog/2014/04/26/i-dont-feel-guilty-about-not-contributing-to-open-source/){.wow}. 223 224 Maintains a [TIL](https://jvns.ca/til/). Writes [zines](https://wizardzines.com/). 225 226 Showed us how funny [statistically generated BS](https://web.archive.org/web/20181228051203/http://www.uliaea.ca/) can be, before the 227 industry missed the joke and drowned us in slop. 228 229 # [LispCast](https://lispcast.com/category/writing/) 230 231 Eric Normand's musings on programming paradigms and their application, 232 with a soft spot for functional programming. 233 234 ## [When in doubt, refactor at the bottom] 235 236 Quoting Sandi Metz: 237 238 > Duplication is far cheaper than the wrong abstraction. 239 240 The point being that blindly following the letter of the DRY law can 241 lead developers to add complexity to extracted functions because "it 242 almost does what I want; if I could add just one more parameter to 243 it…". 244 245 Normand and Metz encourage developers to "mechanically" extract small 246 pieces of logic; even if they are not re-usable, bundling things 247 together and naming them helps make the potential abstractions more 248 visible. 249 250 ## [Programming Paradigms and the Procedural Paradox] 251 252 A discussion on our tendency to conflate *paradigms* with their 253 *features*; for example, when trying to answer "can this language 254 express that paradigm?", we often reduce the question to "does this 255 language possess those features?". 256 257 Normand wonders whether we do this because the procedural paradigm's 258 metaphor (a series of steps that each may contain any number of 259 sub-tasks) maps so well to its features (sequential statements, 260 subroutines) that it trained us to mix those up. 261 262 [When in doubt, refactor at the bottom]: https://lispcast.com/refactor-bottom/ 263 [Programming Paradigms and the Procedural Paradox]: https://lispcast.com/procedural-paradox/ 264 265 # Motherfucking websites 266 267 :::: tags 268 - Web design 269 :::: 270 271 Satirical websites fighting [web bloat] with minimalist designs. 272 273 - <https://motherfuckingwebsite.com/> 274 No style at all, content only. 275 276 - <http://bettermotherfuckingwebsite.com/> 277 Increased line spacing, bigger text, reduced line length. 278 279 - <https://evenbettermotherfucking.website/> 280 Less contrast, better fonts. 281 282 - <https://thebestmotherfuckingwebsite.co/> 283 Satire of the satire, to show that it's possible to be fancy 284 and stay lightweight. 285 286 - <https://thebestmotherfucking.website/> 287 Less contrast, better fonts. 288 289 - <https://bestmotherfucking.website/> 290 Use fonts the user already have, compress content. 291 292 - <https://perfectmotherfuckingwebsite.com/> 293 Think of internationalization. 294 295 [web bloat]: https://idlewords.com/talks/website_obesity.htm 296 297 # [null program](http://nullprogram.com/index/) 298 299 Chris Wellons's in-depth looks into a fairly wide range of programming 300 techniques and applications. The articles often come with 301 illustrative code samples, which are always broken down into 302 bite-sized chunks that are easy to grok. 303 304 Some recurring topics I enjoy reading about: 305 306 - GNU/Linux plumbing 307 - [Raw Linux Threads via System Calls] 308 - [Appending to a File from Multiple Processes] 309 - [A Magnetized Needle and a Steady Hand] 310 311 - C programming tricks 312 - [Global State: A Tale of Two Bad C APIs] 313 - [C Closures as a Library] 314 315 - Software portability 316 - [How to Write Portable C Without Complicating Your Build] 317 - [A Tutorial on Portable Makefiles] 318 - [Test cross-architecture without leaving home] 319 320 - Algorithmics 321 - [Inspecting C's qsort Through Animation] 322 - [A Branchless UTF-8 Decoder] 323 - [Render Multimedia in Pure C] 324 325 - Emacs Lisp plumbing 326 - [Some Performance Advantages of Lexical Scope] 327 - [What's in an Emacs Lambda] 328 329 [Raw Linux Threads via System Calls]: https://nullprogram.com/blog/2015/05/15/ 330 [Appending to a File from Multiple Processes]: https://nullprogram.com/blog/2016/08/03/ 331 [A Magnetized Needle and a Steady Hand]: https://nullprogram.com/blog/2016/11/17/ 332 [Global State: A Tale of Two Bad C APIs]: https://nullprogram.com/blog/2014/10/12/ 333 [C Closures as a Library]: https://nullprogram.com/blog/2017/01/08/ 334 [How to Write Portable C Without Complicating Your Build]: https://nullprogram.com/blog/2017/03/30/ 335 [A Tutorial on Portable Makefiles]: https://nullprogram.com/blog/2017/08/20/ 336 [Test cross-architecture without leaving home]: https://nullprogram.com/blog/2021/08/21/ 337 [Inspecting C's qsort Through Animation]: https://nullprogram.com/blog/2016/09/05/ 338 [A Branchless UTF-8 Decoder]: https://nullprogram.com/blog/2017/10/06/ 339 [Render Multimedia in Pure C]: https://nullprogram.com/blog/2017/11/03/ 340 [Some Performance Advantages of Lexical Scope]: https://nullprogram.com/blog/2016/12/22/ 341 [What's in an Emacs Lambda]: https://nullprogram.com/blog/2017/12/14/ 342 343 # [Red Hat Developer](https://developers.redhat.com/blog/) 344 345 ## [10 tips for reviewing code you don't like] 346 347 The article could basically be included as-is in a [nonviolent 348 communication] textbook and renamed "application to code reviews". 349 350 AFAICT the underlying principle to all these tips is: scrub judgmental 351 statements out of your responses, and state your concerns openly. 352 Nobody should expect you to hold all the answers; express your 353 uncertainty, and let the submitter do the work of convincing you 354 (e.g. checking for performance regressions, splitting patch series). 355 356 [10 tips for reviewing code you don't like]: https://developers.redhat.com/blog/2019/07/08/10-tips-for-reviewing-code-you-dont-like/ 357 [nonviolent communication]: https://en.wikipedia.org/wiki/Nonviolent_Communication 358 359 # [Without boats](https://without.boats/) 360 361 ## [Not Explicit] 362 363 :::: tags 364 - Rust 365 - Language design 366 :::: 367 368 Picking up where Aaron Turon's ["reasoning footprint"] post left off, 369 and breaking down "explicit" into more precise epithets: 370 371 "Noisy" 372 : `try!()` is noisier than `?`, which works in the latter's 373 favor. 374 375 > Often - especially when forwarding errors, as `?` does - the early 376 > return is the least important part of the source code to me. 377 378 "Burdensome" 379 : aka "syntactic salt"; can be deliberate in order to 380 discourage. 381 382 "Manual" or "opt-in" 383 : e.g. if Rust required an explicit `.drop()` on variables, instead 384 of systematically freeing them when they go out of scope. As 385 things stand, a variable's eventual de-allocation is "explicit", 386 as in, it follows non-ambiguously from reading the source code; 387 yet it is also **automatic**. 388 389 "Local" 390 : "explicit within some scope". Method resolution is explicit (as 391 in, deterministic and unambiguous) but one('s IDE) must jump 392 around to figure it out. `?` is local to the very line where the 393 early return happens. 394 395 [Not Explicit]: https://without.boats/blog/things-explicit-is-not/ 396 ["reasoning footprint"]: https://blog.rust-lang.org/2017/03/02/lang-ergonomics.html