mirror of
https://github.com/Smaug123/static-site-pipeline
synced 2025-10-06 00:38:39 +00:00
Compare commits
23 Commits
023d31419a
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
e38dafbd58 | ||
|
9901b1dfc4 | ||
|
80c7b2e425 | ||
|
0254b0377d | ||
|
19093d968b | ||
|
3b64e06862 | ||
|
d4b79faa07 | ||
|
bcb8a9eb60 | ||
|
ecd774c318 | ||
|
22aca8a3be | ||
|
1475932c43 | ||
|
0408056c13 | ||
|
2cd7f6839e | ||
|
6fb121da71 | ||
|
f4bfd5fbfe | ||
|
ec9323fdd3 | ||
|
d523b2bf2f | ||
|
89f12a2d39 | ||
|
f4e4564125 | ||
|
9d817b7f19 | ||
|
359647e1d2 | ||
|
cd3e6426a1 | ||
|
23ba49ce71 |
@@ -7,3 +7,12 @@ https://www.patrickstevens.co.uk/posts/2016-04-13-independence-of-choice/
|
||||
https://www.patrickstevens.co.uk/posts/2016-04-08-another-monty-hall-explanation/
|
||||
https://www.patrickstevens.co.uk/misc/AdjointFunctorTheorems/AdjointFunctorTheorems.pdf
|
||||
https://www.patrickstevens.co.uk/posts/2021-02-20-in-praise-of-dry-run/
|
||||
http://www.patrickstevens.co.uk/wordpress/archives/364
|
||||
http://www.patrickstevens.co.uk/wordpress/archives/379
|
||||
http://www.patrickstevens.co.uk/wordpress/archives/474
|
||||
http://www.patrickstevens.co.uk/wordpress/archives/584
|
||||
https://www.patrickstevens.co.uk/posts/2020-10-23-anki-learning/
|
||||
https://www.patrickstevens.co.uk/sequentially-compact-iff-compact/
|
||||
http://patrickstevens.co.uk/mathematical%20summary/2014/12/19/matrix-puzzle.html
|
||||
https://www.patrickstevens.co.uk/posts/2024-07-25-lob-theorem/
|
||||
https://patrickstevens.co.uk/cauchy-schwarz-proof/
|
||||
|
18
flake.lock
generated
18
flake.lock
generated
@@ -80,11 +80,11 @@
|
||||
"systems": "systems_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1710146030,
|
||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -188,11 +188,11 @@
|
||||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1721841206,
|
||||
"narHash": "sha256-0Q3zNYro6m8v9r2yB35y+AlGmrxmiLBcFhR5Hqto/6c=",
|
||||
"lastModified": 1741381468,
|
||||
"narHash": "sha256-w2ig7s5Afz0dOta4Sfynz7KnIWiKN4dtEW2SjS6qztU=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "a1159ff6c68901142ae41788387bc4c841f190b2",
|
||||
"rev": "79dab6b4451fb66a939e9f894fec0bd22253cf94",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -212,11 +212,11 @@
|
||||
"scripts": "scripts_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1712591670,
|
||||
"narHash": "sha256-mJCxLFGq4fGk74L3vC7ltwkXno1JEeA/aKWew426imk=",
|
||||
"lastModified": 1725713640,
|
||||
"narHash": "sha256-JBTpmQn3Gg3scVUUyLuks1gX+EzkctD+ZN3CBsxXuwQ=",
|
||||
"owner": "Smaug123",
|
||||
"repo": "static-site-pdfs",
|
||||
"rev": "34f4df8719b89d56ea1ba446488a0a16835a9acb",
|
||||
"rev": "e7133d72e6fab800aa3fd91cab47b6bc6824a0ca",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@@ -5,7 +5,7 @@ title = "Patrick Stevens"
|
||||
theme = "anatole"
|
||||
buildFuture = false
|
||||
enableEmoji = true
|
||||
paginate = 20
|
||||
pagination.pagerSize = 20
|
||||
|
||||
[params]
|
||||
profilePicture = "/images/AboutMe/profile"
|
||||
|
@@ -12,7 +12,7 @@ Any remaining decks here are CC-BY-SA.
|
||||
|
||||
* [Geography] (the deck has a misleading name; it's actually a general Geography deck). You can filter out the `london-tube` tag if you like, or `world-capitals`, or `american-geography`.
|
||||
|
||||
<a href="http://creativecommons.org/licenses/by-sa/3.0/deed.en_GB" rel="license"><img style="border-width: 0;" alt="Creative Commons Licence" src="https://licensebuttons.net/l/by-sa/3.0/88x31.png" /></a>
|
||||
This work by <a href="/anki-decks" rel="cc:attributionURL">Patrick Stevens</a> is licensed under a <a href="http://creativecommons.org/licenses/by-sa/3.0/deed.en_GB" rel="license">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.
|
||||
[](http://creativecommons.org/licenses/by-sa/3.0/deed.en_GB)
|
||||
This work by [Patrick Stevens](/anki-decks) is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License](http://creativecommons.org/licenses/by-sa/3.0/deed.en_GB).
|
||||
|
||||
[Geography]: /AnkiDecks/CapitalsOfTheWorld.apkg
|
||||
[Geography]: /AnkiDecks/CapitalsOfTheWorld.apkg
|
||||
|
@@ -7,6 +7,7 @@ layout: page
|
||||
|
||||
This page holds a list of films I have watched, spoiler-free, starting from 9th January 2015.
|
||||
|
||||
* [Dungeons and Dragons: Honour Among Thieves](https://www.imdb.com/title/tt2906216/): Really rather good! As they say, "Consider this fan serviced". Light-hearted, plenty of flashy callouts.
|
||||
* [The Grand Budapest Hotel](https://www.imdb.com/title/tt2278388/): This is one of my favourite films. In general I find Wes Anderson a bit hit-or-miss, but this film is sublime. Excellent characterisation, quick deadpan wit. Ralph Fiennes is just glorious here.
|
||||
|
||||
* [Argylle](https://www.imdb.com/title/tt15009428/): Sadly disappointing. This film was at least twice as long as it should have been. A good version would have been a short funny pastiche; what we actually got was a long boring film punctuated by moments of glorious whimsy.
|
||||
|
@@ -11,10 +11,12 @@ This page holds an incomplete list of games I have played.
|
||||
|
||||
## In progress
|
||||
|
||||
* Chants of Sennaar. An extremely impressive 81% of players have the Steam achievement for leaving the first game area, which I think tells you how gripping this game is. It's basically a particular kind of IQ test, but it's really fun. Reminiscent of _Return of the Obra Dinn_.
|
||||
* ibb and obb. Fun two-player co-op, neat and slightly mind-bending physics.
|
||||
* It Takes Two. Amusing but not worth the price, I think. This is more like a constant stream of "oh, what funny one-off mechanic have they implemented next".
|
||||
|
||||
## Not in progress
|
||||
|
||||
* Chants of Sennaar. An extremely impressive 81% of players have the Steam achievement for leaving the first game area, which I think tells you how gripping this game is. It's basically a particular kind of IQ test, but it's really fun. Reminiscent of _Return of the Obra Dinn_. I could have done with a little more variation in the languages; there are a few neat bits, but there was a broad language design space they mostly didn't touch.
|
||||
* Baldur's Gate 3 (hundreds of hours). Glorious game, aesthetically beautiful, absolutely gigantic amount of content, and sometimes succeeds at making you empathise with the characters. Having played this, I wouldn't really want to go back to playing a DnD-style RPG any other way: all the bookkeeping happens in the background.
|
||||
* Factorio, and Dyson Sphere Program (both hundreds of hours). Grouped together because they are basically the same game. I have banned myself from playing this genre of game (I gave myself RSI from it for a while). Between the two, DSP is much prettier and somewhat more forgiving, but also it has the annoying mechanic of laying your factory out on spheres. "Cannot place blueprint across tropic lines" just feels bad; you really want your factory layout not to depend on where it is situated.
|
||||
* Outer Wilds (about half an hour). Everyone raves about this game, but it makes me travel-sick very fast. No further comment.
|
||||
|
@@ -7,7 +7,7 @@ layout: page
|
||||
If I ever become rich and famous, I'm sure I'll be besieged with requests for "how to do better in life". I hereby head such requests off at the pass, by providing a list of [lifehacks] I am either using or considering the use of.
|
||||
|
||||
* For learning smallish but numerous facts (such as a list of theorems), I use [Anki], which is a [spaced-repetition] learning system, allowing you to enter flashcards and have them shown to you regularly. The time between repetitions of a certain flashcard changes, depending on how well you've been doing on that flashcard - so marking your performance on a particular card as "easy" rather than "hard" tells Anki that you don't want to see that card for a while. It's a bit like the antithesis of cramming, where you see the material exactly once and use it a short time later; Anki is designed for reviewing the material many times (at an optimal spacing) for recall whenever you need it. The idea is to make use of the [spacing effect] - an extremely powerful memory technique that is currently ignored by almost all methods of formal teaching ([Memrise] is a notable exception; I used Memrise until I used Anki).
|
||||
* A surprisingly good way of making myself work when I'm feeling unmotivated is to gather a few like-minded friends and to work in absolute silence with them (possibly on completely unrelated topics). Oddly, I'd not thought of it until reading <a title="Co-working LessWrong post" href="http://lesswrong.com/lw/gwo/coworking_collaboration_to_combat_akrasia/" target="_blank">a LessWrong post on the subject</a>. There's a kind of "all in this together" feeling, as well as the public commitment effect.
|
||||
* A surprisingly good way of making myself work when I'm feeling unmotivated is to gather a few like-minded friends and to work in absolute silence with them (possibly on completely unrelated topics). Oddly, I'd not thought of it until reading [a LessWrong post on the subject](http://lesswrong.com/lw/gwo/coworking_collaboration_to_combat_akrasia/). There's a kind of "all in this together" feeling, as well as the public commitment effect.
|
||||
* I use [f.lux], an application which dims and tints red the computer screen after dusk. I have no idea whether or not it has any effect on wakefulness at night (that is, whether or not being bathed in a standard blue glow keeps me awake), but it certainly feels nicer on the eye.
|
||||
* I am currently in the middle of learning [Dvorak], which is a keyboard layout (QWERTY is the usual one) that is supposedly easier on the hands than QWERTY. It puts vowels all together in easy-to-reach places, and the most common consonants in easy places such that words tend to be made of letters which lie in different hands. (In QWERTY, for example, the word "the" is oddly hard to type, for such a common word - all the characters are away from the home row - but in Dvorak it's just a simple flourish from right to left on the home row.) A friend tells me that [Colemak] is better than Dvorak, but I'd already half-learnt Dvorak by the time ey told me this, and Dvorak interfered heavily with my attempts to learn Colemak. It appears to be much of a muchness, anyway - both are considerably better than QWERTY.
|
||||
* I don't know if it qualifies as a lifehack - more of a biohack or something - but [lucid dreaming] is really cool, and it doesn't take an enormous amount of commitment to learn to do (it just requires the setting up of a few habits throughout the day).
|
||||
|
@@ -12,21 +12,19 @@ title: Stumbled across 9th July 2013
|
||||
---
|
||||
Being bored over the summer holiday, I decided that I would document the cool things I ran across on the Internet. Over the last week, there have been many of these. If I see anything particularly amazing, it'll go in one of these aggregation posts.
|
||||
|
||||
* Neurons are surprisingly beautiful: <http://blog.eyewire.org/gallery/image-gallery/>
|
||||
* A rather neat and very short story: <https://qntm.org/timeloop>
|
||||
* A *bit* less short but just as good a short story: <https://qntm.org/responsibility>
|
||||
* A rant with which students can all identify, in The Cambridge Student magazine: now lost from the Internet.
|
||||
* An Easter Island word "tingo" means "to borrow objects from a friend’s house one by one until there are none left": <link to the Internet Archive>("http://web.archive.org/web/20100516040410/http://blog.web-translations.com/2008/12/toujours-tingo-words-that-dont-exist-in-english/)
|
||||
* Musings on free will: <http://www.mit.edu/people/dpolicar/writing/prose/text/godTaoist.html>
|
||||
* A thing that I just have to share again: <http://nextbigfuture.com/2013/06/technical-hurdles-have-been-overcome.html>
|
||||
* The human brain is a really weird piece of kit: <http://lesswrong.com/lw/20/the_apologist_and_the_revolutionary/>
|
||||
* We *have* to make one of these at some point: <http://www.pimpthatsnack.com/project/302/1">
|
||||
* This is quite soothing in a weird kind of way: <https://thingsfittingperfectlyintothings.tumblr.com/>
|
||||
* It is possible to be deficient in arsenic. (Link to the Soylent Discourse forum is permanently defunct.)
|
||||
* A really useful website for when you don't want to have to spin up Wolfram|Alpha to work out time differences: <http://everytimezone.com/>
|
||||
* Why never to talk to the police (seriously, never talk to the police): <https://www.youtube.com/watch?v=6wXkI4t7nuc>
|
||||
* A fascinating book about the power of positive and negative reinforcement, and why they're often done wrongly: [Don’t Shoot the Dog]
|
||||
* The Church of England really took its time, but at last they've done it: <https://www.bbc.co.uk/news/uk-23215388>
|
||||
* The Hawkeye Initiative, for the liberation of women in comics: <http://thehawkeyeinitiative.com/>
|
||||
|
||||
[Don’t Shoot the Dog]: https://web.archive.org/web/20130206170903/http://www.papagalibg.com/FilesStore/karen_pryor_-_don_t_shoot_the_dog.pdf
|
||||
* [Neurons are surprisingly beautiful](http://blog.eyewire.org/gallery/image-gallery/)
|
||||
* A rather neat and very short story, [Time Loop](https://qntm.org/timeloop) by qntm
|
||||
* A bit less short but just as good a short story: [I don't know, Timmy, being God is a big responsibility](https://qntm.org/responsibility) by qntm
|
||||
* A rant with which students can all identify, in The Cambridge Student magazine: now lost from the Internet.
|
||||
* An Easter Island word "tingo" means "to borrow objects from a friend's house one by one until there are none left": [Link to the Internet Archive](http://web.archive.org/web/20100516040410/http://blog.web-translations.com/2008/12/toujours-tingo-words-that-dont-exist-in-english/)
|
||||
* Musings on free will: [Is God a Taoist?](http://www.mit.edu/people/dpolicar/writing/prose/text/godTaoist.html)
|
||||
* A thing that I just have to share again: [Technical hurdles have been overcome for the first human head transplant](http://nextbigfuture.com/2013/06/technical-hurdles-have-been-overcome.html)
|
||||
* The human brain is a really weird piece of kit: [The Apologist and the Revolutionary](http://lesswrong.com/lw/20/the_apologist_and_the_revolutionary/)
|
||||
* We *have* to make one of these at some point: [the Creme de la Creme Egg](https://www.pimpthatsnack.com/project/the-creme-de-la-creme-egg/)
|
||||
* This is quite soothing in a weird kind of way: [Things Fitting Perfectly Into Things](https://thingsfittingperfectlyintothings.tumblr.com/)
|
||||
* It is possible to be deficient in arsenic. (Link to the Soylent Discourse forum is permanently defunct.)
|
||||
* A really useful website for when you don't want to have to spin up Wolfram|Alpha to work out time differences: [Every Time Zone](http://everytimezone.com/)
|
||||
* Why never to talk to the police (seriously, never talk to the police): [Don't Talk to the Police](https://www.youtube.com/watch?v=6wXkI4t7nuc)
|
||||
* A fascinating book about the power of positive and negative reinforcement, and why they're often done wrongly: [Don't Shoot the Dog](https://web.archive.org/web/20130206170903/http://www.papagalibg.com/FilesStore/karen_pryor_-_don_t_shoot_the_dog.pdf)
|
||||
* The Church of England really took its time, but at last they've done it: [Church of England makes Chichester child abuse apology](https://www.bbc.co.uk/news/uk-23215388)
|
||||
* The Hawkeye Initiative, for the liberation of women in comics: [The Hawkeye Initiative](http://thehawkeyeinitiative.com/)
|
||||
|
@@ -8,6 +8,7 @@ date: "2013-07-29T00:00:00Z"
|
||||
aliases:
|
||||
- /stumbled_across/stumbled-across-2/
|
||||
- /stumbled-across-29-july-2013/
|
||||
- /wordpress/archives/241/
|
||||
title: Stumbled across 29th July 2013
|
||||
---
|
||||
* Hehe: <http://www.pixartheory.com/>
|
||||
|
@@ -8,6 +8,7 @@ date: "2013-07-30T00:00:00Z"
|
||||
aliases:
|
||||
- /uncategorized/on-to-do-lists-as-direction-in-life/
|
||||
- /on-to-do-lists-as-direction-in-life/
|
||||
- /wordpress/archives/268/
|
||||
title: On to-do lists as direction in life
|
||||
---
|
||||
[Getting Things Done](https://en.wikipedia.org/wiki/Getting_Things_Done) has gathered something of a [cult following](http://web.archive.org/web/20130428015707/http://www.wired.com/techbiz/people/magazine/15-10/ff_allen? "Wired article on GTD") [archived due to [link rot][1]] since its inception. As a way of getting things done, it's pretty good - separate tasks out into small bits on your to-do list so that you have mental room free to consider the bigger picture. However, there's a certain aspect of to-do lists that I've not really seen mentioned before, and which I find to be really helpful.
|
||||
|
@@ -8,6 +8,7 @@ date: "2013-08-04T00:00:00Z"
|
||||
aliases:
|
||||
- /uncategorized/new-computer-setup/
|
||||
- /new-computer-setup/
|
||||
- /wordpress/archives/36
|
||||
title: New computer setup
|
||||
---
|
||||
|
||||
|
@@ -8,6 +8,7 @@ date: "2013-08-04T00:00:00Z"
|
||||
aliases:
|
||||
- /stumbled_across/stumbled-across-3/
|
||||
- /stumbled-across-4-august-2013/
|
||||
- /wordpress/archives/267/
|
||||
title: Stumbled across 4th August 2013
|
||||
---
|
||||
* An ad developer has misgivings: <http://seriouspony.com/blog/2013/7/24/your-app-makes-me-fat>
|
||||
|
@@ -8,6 +8,7 @@ date: "2013-08-11T00:00:00Z"
|
||||
aliases:
|
||||
- /stumbled_across/stumbled-across-11th-august-2013/
|
||||
- /stumbled-across-11th-august-2013/
|
||||
- /wordpress/archives/301/
|
||||
title: Stumbled across 11th August 2013
|
||||
---
|
||||
* A thousand times this (EDIT 2022: the link is dead and I have no idea what I was referring to).
|
||||
|
@@ -9,6 +9,7 @@ math: true
|
||||
aliases:
|
||||
- /psychology/thinking-styles/
|
||||
- /thinking-styles/
|
||||
- /wordpress/archives/335/
|
||||
title: Thinking styles
|
||||
---
|
||||
All the way back into primary school (ages 4 to 11 years old, in case a non-Brit is reading this), we have been told repeatedly that "people learn things in different ways". There were two years in primary school when I had a teacher who was very into [Six Thinking Hats](https://en.wikipedia.org/wiki/Six_Thinking_Hats) (leading to the worst outbreak of headlice I've ever encountered) and [mind maps](https://en.wikipedia.org/wiki/Mind_map). I never understood mind maps, and whenever we were told to create a mind map, I'd make mine as linear and boxy as possible, out of simple frustration with the pointless task of making a picture of something that I already had perfectly well-set-out in my mind. I quickly learnt to correlate "making a mind map" with "being slow and inefficient at thinking". (This was back when my memory was still exceptionally good, so I wasn't really learning much at school - having read, and therefore memorised, a good children's encyclopaedia was enough for me - and hence relative to me, pretty much everyone else was slow and inefficient, because I'd already learnt the material.)
|
||||
|
@@ -8,6 +8,7 @@ date: "2013-08-21T00:00:00Z"
|
||||
aliases:
|
||||
- /psychology/flow/
|
||||
- /my-experiences-with-flow/
|
||||
- /wordpress/archives/326/
|
||||
title: My experiences with flow
|
||||
---
|
||||
I'm in the middle of reading [Flow](https://en.wikipedia.org/wiki/Flow_(psychology)), by [Mihály Csíkszentmihályi][1], and so far, I love it. It describes the "[flow state](https://en.wikipedia.org/wiki/Flow_%28psychology%29)" of consciousness, that state of "everything is irrelevant except for the task at hand" in which time flies past without your noticing, and you don't notice hunger or thirst or people moving around you. Flow can be induced when performing a difficult task which lies within your abilities, where immediate feedback is provided. I, at least, feel characteristically exhausted after coming out of a long period of flow - but it's a good kind of mental exhaustion, much as the tiredness after a long swim is a good kind of physical exhaustion (in contrast to tiredness-after-a-long-day-of-doing-nothing, which feels sort of lazier and unwholesome). The Wikipedia page is a good enough explanation of flow that I will not describe it further here.
|
||||
|
@@ -8,6 +8,7 @@ date: "2013-08-22T00:00:00Z"
|
||||
aliases:
|
||||
- /uncategorized/how-to-punt-in-cambridge/
|
||||
- /how-to-punt-in-cambridge/
|
||||
- /wordpress/archives/345/
|
||||
title: How to punt in Cambridge
|
||||
---
|
||||
[When in Cambridge][1]…
|
||||
|
@@ -8,6 +8,7 @@ date: "2013-08-24T00:00:00Z"
|
||||
aliases:
|
||||
- /stumbled_across/stumbled-across-4/
|
||||
- /stumbled-across-24-august-2013/
|
||||
- /wordpress/archives/329/
|
||||
title: Stumbled across 24th August 2013
|
||||
---
|
||||
* The much-vaunted Hyperloop looks really cool, if it could ever be built: <https://arstechnica.com/business/2013/08/hyperloop-a-theoretical-760-mph-transit-system-made-of-sun-air-and-magnets/>
|
||||
|
@@ -8,6 +8,7 @@ date: "2013-09-13T00:00:00Z"
|
||||
aliases:
|
||||
- /stumbled_across/stumbled-across-14th-september-2013/
|
||||
- /stumbled-across-14th-september-2013/
|
||||
- /wordpress/archives/362/
|
||||
title: Stumbled across 14th September 2013
|
||||
---
|
||||
* On the merits of silence (I wholeheartedly agree): <http://www.nytimes.com/2013/08/25/opinion/sunday/im-thinking-please-be-quiet.html>
|
||||
|
@@ -8,6 +8,7 @@ date: "2013-09-21T00:00:00Z"
|
||||
aliases:
|
||||
- /uncategorized/how-to-prove-that-you-are-a-god/
|
||||
- /how-to-prove-that-you-are-a-god/
|
||||
- /wordpress/archives/434/
|
||||
title: How to prove that you are a god
|
||||
---
|
||||
I came across an interesting question while reading the blog of [Scott Aaronson][1] today. The question was as follows:
|
||||
|
@@ -8,6 +8,7 @@ date: "2013-10-10T00:00:00Z"
|
||||
aliases:
|
||||
- /creative/plot-armour/
|
||||
- /plot-armour/
|
||||
- /wordpress/archives/445/
|
||||
title: Plot Armour
|
||||
---
|
||||
*Wherein I dabble in parodic fiction. The title refers to the TV Tropes page on [Plot Armour][1], but don't follow that link unless you first resolve not to click on any links on that page. TV Tropes is the hardest extant website from which to escape.*
|
||||
|
@@ -8,6 +8,7 @@ date: "2013-10-11T00:00:00Z"
|
||||
aliases:
|
||||
- /uncategorized/meaning-what-you-say/
|
||||
- /meaning-what-you-say/
|
||||
- /wordpress/archives/450
|
||||
title: Meaning what you say
|
||||
---
|
||||
In conversation with (say, for the purposes of propagating a sterotype) humanities students, I am often struck by how imprecisely language is used, and how much confusion arises therefrom. A case in point:
|
||||
|
@@ -8,6 +8,7 @@ date: "2013-10-13T00:00:00Z"
|
||||
aliases:
|
||||
- /psychology/training-away-mental-bias/
|
||||
- /training-away-mental-bias/
|
||||
- /wordpress/archives/455
|
||||
title: Training away mental bias
|
||||
---
|
||||
*In which I recount an experiment I have been performing. Please be aware that in this article I am in "[meaning what I say][1]" mode.*
|
||||
|
@@ -8,6 +8,7 @@ date: "2013-10-20T00:00:00Z"
|
||||
aliases:
|
||||
- /creative/the-ravenous/
|
||||
- /the-ravenous/
|
||||
- /wordpress/archives/462/
|
||||
title: The Ravenous
|
||||
sidenotes: true
|
||||
---
|
||||
|
@@ -10,6 +10,8 @@ math: true
|
||||
aliases:
|
||||
- /mathematical_summary/how-to-do-analysis-questions/
|
||||
- /how-to-do-analysis-questions/
|
||||
- /archives/474/
|
||||
- /wordpress/archives/474/
|
||||
title: How to do Analysis questions
|
||||
---
|
||||
This post is for posterity, made shortly after [Dr Paul Russell][1] lectured Analysis II in Part IB of the Maths Tripos at Cambridge. In particular, he demonstrated a way of doing certain basic questions. It may be useful to people who are only just starting the study of analysis and/or who are doing example sheets in it.
|
||||
|
@@ -8,6 +8,7 @@ date: "2013-11-07T00:00:00Z"
|
||||
aliases:
|
||||
- /uncategorized/my-quest-for-a-new-phone/
|
||||
- /my-quest-for-a-new-phone/
|
||||
- /wordpress/archives/486/
|
||||
title: My quest for a new phone
|
||||
---
|
||||
*This post is unfinished, and may never be finished - I have decided that the Nexus 5 is sufficiently cheap, nice-looking and future-proof to outweigh the boredom of continuing the research here, especially given that such research by necessity has a very short lifespan. I am one of those people who hates shopping with a fiery passion.*
|
||||
|
@@ -9,6 +9,7 @@ math: true
|
||||
aliases:
|
||||
- /mathematical_summary/markov-chain-card-trick/
|
||||
- /markov-chain-card-trick/
|
||||
- /wordpress/archives/500/
|
||||
title: Markov Chain card trick
|
||||
---
|
||||
In my latest lecture on [Markov Chains][1] in Part IB of the Mathematical Tripos, our lecturer showed us a very nice little application of the theorem that "if a discrete-time chain is aperiodic, irreducible and positive-recurrent, then there is an invariant distribution to which the chain tends as time increases". In particular, let \\(X\\) be a Markov chain on a state space consisting of "the value of a card revealed from a deck of cards", where aces count 1 and picture cards count 10. Let \\(P\\) be randomly chosen from the range \\(1 \dots 5\\), and let \\(X_0 = P\\). Proceed as follows: define \\(X_n\\) as "the value of the \\(\sum_{i=0}^{n-1} X_i\\)-th card". Stop when the newest \\(X_n\\) would be greater than \\(52\\).
|
||||
|
@@ -7,6 +7,7 @@ comments: true
|
||||
date: "2013-11-23T00:00:00Z"
|
||||
aliases:
|
||||
- uncategorized/the-jean-paul-sartre-cookbook/
|
||||
- /wordpress/archives/506/
|
||||
title: The Jean-Paul Sartre Cookbook
|
||||
---
|
||||
> Many thanks to the [Guru Bursill-Hall][1] for bringing this tract to my attention through his weekly History of Maths bulletins. It was originally written in 1987 by Marty Smith, according to the Internet.
|
||||
|
@@ -24,7 +24,7 @@ The contents of soil
|
||||
|
||||
* we eat fungi
|
||||
|
||||
* * we don't just eat mushrooms, we also are starting to eat <a title="Quorn Wikipedia page" href="https://en.wikipedia.org/wiki/Quorn">Quorn</a> etc
|
||||
* * we don't just eat mushrooms, we also are starting to eat [Quorn](https://en.wikipedia.org/wiki/Quorn) etc
|
||||
|
||||
* we eat fungi - more specifically, the reproductive organs of the mycelium
|
||||
|
||||
|
@@ -8,6 +8,7 @@ date: "2014-02-16T00:00:00Z"
|
||||
aliases:
|
||||
- /creative/rage-rage-against-the-poets-hardest-sell/
|
||||
- /rage-rage-against-the-poets-hardest-sell/
|
||||
- /wordpress/archives/563/
|
||||
title: Rage, rage against the poet’s hardest sell
|
||||
---
|
||||
I feel that I can write a sonnet well.
|
||||
|
@@ -8,6 +8,7 @@ date: "2014-03-20T00:00:00Z"
|
||||
aliases:
|
||||
- /uncategorized/a-roundup-of-some-board-games/
|
||||
- /a-roundup-of-some-board-games/
|
||||
- /wordpress/archives/576/
|
||||
title: A roundup of some board games
|
||||
---
|
||||
It has been commented to me that it's quite hard to find out (on the Internet) what different games involve. For instance, [Agricola][1] is a game about farming (and that's easy to find out), but what you actually do while playing it is not easy to discover. Here, then, is a brief overview of some games.
|
||||
|
@@ -10,6 +10,8 @@ math: true
|
||||
aliases:
|
||||
- /mathematical_summary/proof_discovery/how-to-discover-the-contraction-mapping-theorem/
|
||||
- /how-to-discover-the-contraction-mapping-theorem/
|
||||
- /archives/584/
|
||||
- /wordpress/archives/584/
|
||||
title: How to discover the Contraction Mapping Theorem
|
||||
---
|
||||
A little while ago I set myself the exercise of stating and proving the [Contraction Mapping Theorem][1]. It turned out that I mis-stated it in three different aspects ("contraction", "non-empty" and "complete"), but I was able to correct the statement because there were several points in the proof where it was very natural to do a certain thing (and where that thing turned out to rely on a correct statement of the theorem).
|
||||
|
@@ -10,6 +10,7 @@ math: true
|
||||
aliases:
|
||||
- /mathematical_summary/proof_discovery/discovering-a-proof-of-heine-borel/
|
||||
- /discovering-a-proof-of-heine-borel/
|
||||
- /wordpress/archives/589/
|
||||
title: Discovering a proof of Heine-Borel
|
||||
---
|
||||
I'm running through my Analysis proofs, trying to work out which ones are genuinely hard and which follow straightforwardly from my general knowledge base. I don't find the [Heine-Borel Theorem][1] "easy" enough that I can even forget its statement and still prove it (like [I can with the Contraction Mapping Theorem][2]), but it turns out to be easy in the sense that it follows simply from all the theorems I already know. Here, then, is my attempt to discover a proof of the theorem, using as a guide all the results I know but can't necessarily prove without lots of effort.
|
||||
|
@@ -9,6 +9,7 @@ math: true
|
||||
aliases:
|
||||
- /uncategorized/useful-conformal-mappings/
|
||||
- /useful-conformal-mappings/
|
||||
- /wordpress/archives/594/
|
||||
title: Useful conformal mappings
|
||||
---
|
||||
This post is to be a list of conformal mappings, so that I can get better at answering questions like "Find a conformal mapping from \<this domain\> to \<this domain\>". The following Mathematica code is rough-and-ready, but it is designed to demonstrate where a given region goes under a given transformation.
|
||||
|
@@ -10,6 +10,7 @@ math: true
|
||||
aliases:
|
||||
- /mathematical_summary/sample-topology-question/
|
||||
- /sample-topology-question/
|
||||
- /wordpress/archives/600/
|
||||
title: Sample topology question
|
||||
---
|
||||
As part of the recent series on how I approach maths problems, I give another one here (question 14 on the Maths Tripos IB 2007 paper 4). The question is:
|
||||
|
@@ -9,6 +9,7 @@ math: true
|
||||
aliases:
|
||||
- /mathematical_summary/cayley-hamilton-theorem/
|
||||
- /cayley-hamilton-theorem/
|
||||
- /wordpress/archives/606/
|
||||
title: Cayley-Hamilton theorem
|
||||
---
|
||||
This is to detail a much easier proof (at least, I find it so) of [Cayley-Hamilton][1] than the ones which appear on the Wikipedia page. It only applies in the case of complex vector spaces; most of the post is taken up with a proof of a lemma about complex matrices that is very useful in many contexts.
|
||||
|
@@ -10,6 +10,7 @@ math: true
|
||||
aliases:
|
||||
- /mathematical_summary/proof_discovery/sequentially-compact-iff-compact/
|
||||
- /sequentially-compact-iff-compact/
|
||||
- /wordpress/archives/620/
|
||||
title: Sequentially compact iff compact
|
||||
---
|
||||
[Prof Körner][1] told us during the [IB Metric and Topological Spaces][2] course that the real meat of the course (indeed, its hardest theorem) was "a metric space is sequentially compact iff it is compact". At the moment, all I remember of this result is that one direction requires Lebesgue's lemma (whose statement I don't remember) and that the other direction is quite easy. I'm going to try and discover a proof - I'll be honest when I have to look things up.
|
||||
|
@@ -10,6 +10,7 @@ math: true
|
||||
aliases:
|
||||
- /mathematical_summary/proof_discovery/discovering-a-proof-of-sylvesters-law-of-inertia/
|
||||
- /discovering-a-proof-of-sylvesters-law-of-inertia/
|
||||
- /wordpress/archives/591/
|
||||
title: Discovering a proof of Sylvester's Law of Inertia
|
||||
---
|
||||
*This is part of what has become a series on discovering some fairly basic mathematical results, and/or discovering their proofs. It's mostly intended so that I start finding the results intuitive - having once found a proof myself, I hope to be able to reproduce it without too much effort in the exam.*
|
||||
|
@@ -9,6 +9,7 @@ math: true
|
||||
aliases:
|
||||
- /mathematical_summary/proof-that-symmetric-matrices-are-diagonalisable/
|
||||
- /proof-that-symmetric-matrices-are-diagonalisable/
|
||||
- /wordpress/archives/658/
|
||||
title: Proof that symmetric matrices are diagonalisable
|
||||
---
|
||||
This comes up quite frequently, but I've been stuck for an easy memory-friendly way to do this. I trawled through the 1A Vectors and Matrices course notes, and found the following mechanical proof. (It's not a discovery-proof - I looked it up.)
|
||||
|
@@ -9,7 +9,7 @@ title: Crates (existentials in F#)
|
||||
summary: "An introduction to the crate pattern for representing existential quantification in F#."
|
||||
---
|
||||
|
||||
The usual blog post introducing crates in F# is [G-Research's](https://www.gresearch.co.uk/article/squeezing-more-out-of-the-f-type-system-introducing-crates/).
|
||||
The usual blog post introducing crates in F# is [G-Research's](https://web.archive.org/web/20220421204450/https://www.gresearch.co.uk/blog/article/squeezing-more-out-of-the-f-type-system-introducing-crates/).
|
||||
However, I believe that post approaches things from a much more abstract perspective than is useful.
|
||||
Instead, I will approach them by starting from the concrete.
|
||||
|
||||
|
@@ -56,7 +56,7 @@ To discover checks along both a vertical and a diagonal, it's necessary to move
|
||||
* Castling moves two pieces, but we already know the black king has moved, so it wasn't Black castling.
|
||||
* A standard capture does move two pieces, but it leaves the capturing piece in the same place as the captured piece, so it can't reveal two checks.
|
||||
* Moving a piece without capturing moves one piece, and can only reveal one check.
|
||||
* Promoting a pawn could conceivably have had this effect if this were all happening on the back rank: a pawn promoting to a knight can both discover a check from a bishop and cause check with the new knight. But both the pieces which are giving check are in the middle of the board, with neither on the back rank.
|
||||
* Promoting a pawn could conceivably have had this effect if this were all happening on the back rank: a pawn promoting to a knight can both discover a check from a rook and cause check with the new knight. But both the pieces which are giving check are in the middle of the board, with neither on the back rank.
|
||||
|
||||
There is exactly one other kind of move in the game: capturing en passant.
|
||||
This can clear a file and a diagonal at the same time.
|
||||
|
28
hugo/content/posts/2024-09-07-massage.md
Normal file
28
hugo/content/posts/2024-09-07-massage.md
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
lastmod: "2024-09-07T11:47:00.0000000+01:00"
|
||||
author: patrick
|
||||
categories:
|
||||
- uncategorized
|
||||
date: "2024-09-07T11:47:00.0000000+01:00"
|
||||
title: Lessons from a massage course
|
||||
summary: "I went to a one-day intro to massage taster course, and it was fun and interesting!"
|
||||
---
|
||||
|
||||
I recently attended the [Bodyology one-day intro to massage taster](https://bodyologymassagecourses.co.uk/courses/intro-course).
|
||||
Recommended!
|
||||
The instructor Dror was excellent, with a teaching style correctly based around telling you why things are done the way they are, and then giving you lots of time to practise finding how your own hands best achieve the goals.
|
||||
|
||||
# Why did I try massage?
|
||||
|
||||
1. The ever-present desire to find meaning (c.f. applying for the RAF reserves); it's common knowledge that [directly and viscerally helping others](https://80000hours.org/career-guide/job-satisfaction/) is something that people find very meaningful.
|
||||
2. Wouldn't that be a neat skill to be able to reveal that you're bizarrely, impossibly good at! ("Sometimes, magic is just someone spending more time on something than anyone else might reasonably expect.")
|
||||
|
||||
# Interesting lessons
|
||||
|
||||
* Move from the legs. This is obvious every single time it comes up anywhere, and it comes up all the time, but somehow I *still* never generalise the lesson so that I know it without being told in any given situation.
|
||||
* I find it *really* stressful to have no real-time feedback on what I'm doing. Pretty much everything I do has a tight feedback loop, but the feedback loop for massage is really long: it breaks the immersion to be constantly using your mouth-words during the session, and if the victim is face-down then your only source of feedback is literally just "try to read someone's back", unless you are much more empathic than I am (which would certainly come with practice). I was a lot more relaxed when my subject and I were maintaining pretty constant verbal communication.
|
||||
* This is even worse for head massage, where the subject tends to fall asleep (or get very close to it), which I guess is a positive signal but also is a complete lack of any other signals.
|
||||
* Massage also gives you no *objective* feedback, so it falls into the category of "things where my System 1 expects explicit positive feedback to be false". I can't stop myself interpreting other people's feedback as "this person is trying to make you feel better about your terrible performance", at least without a bit of time getting to know that person first.
|
||||
* Cultural hangups around grabbing a woman by the neck. There was an entire session on neck/traps/shoulder massage, and it took me a solid two minutes before I was able to grip the spinal erectors hard enough to have any massage-related effect at all. This is hard to do when for thirty years you've had a culture screaming "YOU WILL NOT GRAB A WOMAN BY THE NECK" at you! (I also suspect I was under more internal strain than I explicitly felt, because I choked up slightly when I gave a sentence explaining my light touch afterwards.)
|
||||
* A massage often begins with a simple laying-on-of-hands. This is actually a communication channel! Take it slow: you're greeting the subject, setting the terms of engagement, letting yourself adjust to their rhythm (mainly their breathing). A therapist who moves their hands around feels indecisive, and remember that time will feel like it's passing faster for the therapist because they're upright and in control. Different people communicate different things this way, which surprised me a lot. I really felt (for example) that, while I was the demo subject, the instructor was saying hello to me through his hands, and that I was replying through my body's breathing movement. (One breathing cycle lasts many seconds; if the therapist moves their hands before you've even finished one breath, that actually feels pretty rude: they're literally interrupting your communication.) By contrast, during a practice session, someone gave me a very firm and assertive greeting, "I am in control" (which is certainly not bad, it's just very different!).
|
||||
* Sunflower oil works just fine as a massage oil; in fact the instructor recommended it over other oils.
|
99
hugo/content/posts/2024-09-27-software-rant.md
Normal file
99
hugo/content/posts/2024-09-27-software-rant.md
Normal file
@@ -0,0 +1,99 @@
|
||||
---
|
||||
lastmod: "2024-09-27T18:14:00.0000000+01:00"
|
||||
author: patrick
|
||||
categories:
|
||||
- programming
|
||||
date: "2024-09-27T18:14:00.0000000+01:00"
|
||||
title: Unhinged rant about software
|
||||
summary: "Modern software practices and their sadness."
|
||||
---
|
||||
|
||||
*Epistemic status: wail of anguish*
|
||||
|
||||
I've given this rant twice recently, so will unwisely write it down to avoid giving it a third time.
|
||||
|
||||
# Most people seem bent on self-flagellation
|
||||
|
||||
Subtitle: And I Don't Think They Realise How Hard They're Making It For Themselves.
|
||||
|
||||
## Python
|
||||
|
||||
Python is touted as "simple".
|
||||
What people really mean by is that library developers put in large amounts of effort to make it *concise*.
|
||||
Python itself is pretty complicated (indeed, by design you essentially can't make *any* static guarantees), and its extreme dynamism makes it in practice *extremely complex*.
|
||||
|
||||
I recently mentioned [Pyright](https://github.com/microsoft/pyright) to a professional Python developer.
|
||||
This person tried it out, and stopped, saying "it's giving me all these false positives".
|
||||
He then described two such broad classes of false positives, *both* of which were in fact true positives: they were indicating bugs in the code.
|
||||
(I'm not talking about logic bugs here, revealed by an attempt to impose types; these are bugs arising due to the use of actual language features.)
|
||||
|
||||
A professional full-time Python developer did not know that they were bugs!
|
||||
This is not his fault: Python is really hard to understand!
|
||||
|
||||
(I shall not mention the dependency management situation because everyone already knows what a flaming mess that is.)
|
||||
|
||||
## .NET and ASP.NET
|
||||
|
||||
Idiomatic .NET code seems to be bizarrely full of galaxy-brained object orientation.
|
||||
ASP.NET is a *particularly* bad example.
|
||||
Throughout the standard libraries and chunks of the ecosystem, Microsoft and everyone else goes to extreme lengths to construct a system that's as hard as possible to understand.
|
||||
For example:
|
||||
|
||||
* ASP.NET specialises in converting all compile-time errors to runtime errors. Its total reliance on runtime dependency injection means you simply have to run your server to discover whether it even has a chance of working. This is the part of working on ASP.NET stuff that causes me literal physical pain (in my legs, if you're interested). As far as I know, you can't opt out of this insanity. [There's a correct way to do dependency injection](https://www.bartoszsypytkowski.com/dealing-with-complex-dependency-injection-in-f/), which is type-checked and compile-time-safe, but of course C# can't express it.
|
||||
* Convention Over Configuration, i.e. "don't worry your pretty little head about how this thing works; just trust Daddy Microsoft". All abstractions leak, and Microsoft's approach makes it almost completely impossible to work out what's happening when ASP.NET leaks.
|
||||
* No human is capable of writing an ASP.NET service correctly. The middleware system is notoriously brittle: it depends fundamentally and silently on chaining together all the middleware in the correct order. GitHub [is](https://github.com/aspnet/SignalR/issues/2316) [full](https://github.com/dotnet/AspNetCore.Docs/issues/28467) [of](https://github.com/IzyPro/WatchDog/issues/46) [issues](https://github.com/dotnet/aspnetcore/issues/15313) [describing](https://github.com/dotnet/aspnetcore/issues/34146) [people](https://github.com/dotnet/aspnetcore/issues/14049#issuecomment-533190098) [getting](https://github.com/dotnet/aspnetcore/issues/52295) [this](https://github.com/dotnet/AspNetCore.Docs/issues/14221#issuecomment-530436736) [wrong](https://github.com/dotnet/AspNetCore.Docs/issues/19957#issuecomment-698572231), [or](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/2641) [asking](https://github.com/dotnet/AspNetCore.Docs/issues/17031) [for](https://github.com/dotnet/aspnet-api-versioning/issues/704) [better](https://github.com/dotnet/aspnetcore/issues/45302) [documentation](https://github.com/dotnet/aspnet-api-versioning/issues/979). All common .NET languages are strongly- statically- typed; why did they decide to throw away all the help the computer can give you?
|
||||
* ASP.NET has painted itself into such a corner that they have had to start putting some *seriously* ridiculous features into C#. I'm thinking here of [interceptors](https://devblogs.microsoft.com/dotnet/new-csharp-12-preview-features/#interceptors), which they describe as "enabl[ing] exciting code patterns". I do not want exciting code patterns! If you want to generate source code, then do so; give us a macro system if you like; but don't bake this stuff into your language - you're not a Lisp!
|
||||
* Also by the way you're not Ruby. When I discovered [Harmony](https://github.com/pardeike/Harmony) in a dependency recently, I had several minutes of existential terror.
|
||||
* Why do the Microsoft identity libraries perform 80ms of reflection before decoding a JWT (we timed this)?
|
||||
|
||||
For a system which eschews compile-time safety in favour of "convention", .NET sure has terrible docs.
|
||||
Why are they so big, and why do they contain so little useful information?
|
||||
Why are all these systems built to be impossible to use without a comprehensive knowledge of their implementation, such that I have to open the .NET source code *every time* I have a question about what something does?
|
||||
Why do I [keep](https://github.com/dotnet/dotnet-api-docs/pull/9753) [on](https://github.com/dotnet/dotnet-api-docs/pull/9595) [having](https://github.com/dotnet/runtime/pull/95956) [to](https://github.com/dotnet/docs/pull/35171) [raise](https://github.com/dotnet/dotnet-api-docs/pull/9394) [docs](https://github.com/dotnet/docs/pull/42637) [PRs](https://github.com/dotnet/aspnetcore/pull/57779) adding the most basic information?
|
||||
So many questions!
|
||||
|
||||
## Golang
|
||||
|
||||
Another example of a "simple" language which it's impossible to write correctly without [a large suite of linters](https://github.com/golangci/golangci-lint) you don't get out-of-the-box.
|
||||
[Fasterthanli.me](https://fasterthanli.me/articles/i-want-off-mr-golangs-wild-ride) has written most of what I want to say about this.
|
||||
|
||||
I particularly enjoy the fact that you can identify a Golang program by the extremely cursed error messages you get out of it, where it dumps uninitialised memory to the console and that sort of thing.
|
||||
This happens with considerable regularity.
|
||||
I've even observed it in `kubectl`, so it's not just that I've been unlucky; even the best Golang programmers can't reliably avoid thinking garbage memory is a string.
|
||||
But apparently Golang error handling is great, so what would I know.
|
||||
|
||||
[Boats](https://without.boats/blog/let-futures-be-futures/):
|
||||
|
||||
> You might also decide your language should have other classic features like null pointers, default constructors, data races and GOTO, for reasons known only to you.
|
||||
|
||||
Why did the creators not put algebraic data types into the language, if they were going to do errors-as-return-values?
|
||||
|
||||
## Summary
|
||||
|
||||
The Jonathan Blow/Casey Muratori sphere of the Internet probably expresses this the most strongly, but they are completely correct.
|
||||
I think people are using *really hard environments* to solve *usually very simple problems*, and it makes their lives so much harder than necessary.
|
||||
Their work environment is absolutely full of [incidental complexity](https://en.wikipedia.org/wiki/No_Silver_Bullet).
|
||||
|
||||
To lightly paraphrase someone very senior at $WORK describing me, my schtick (a decent chunk of why I'm a "Principal Engineer" there) is to get annoyed at the existing solution to a problem and write a dumb replacement in F#, in four hours, that's orders of magnitude faster, orders of magnitude less code, and requires less than one PR of maintenance a month (and usually *much* less).
|
||||
I've done this several times now.
|
||||
(There's one thing, "Kraken" for those who know the G-Research internal environment, which doesn't fit that pattern in that I did actual extended work to create it; I think that last received a PR nearly a year ago, which is to say that it is also essentially complete. That used engineering techniques no more complicated than [diligently making sure all state was reified][dryrun] and using discriminated unions to tightly constrain the domains. None of this is rocket science!)
|
||||
|
||||
I believe I'm not a "10x engineer" but that most people are following practices which hold them back *so much*.
|
||||
|
||||
# Copilot etc
|
||||
|
||||
As an encore, I believe I have an answer to "why does everyone seem to like the Copilot-like things so much, whereas I have to turn them off within five minutes of trying them?".
|
||||
|
||||
Most people work in environments which have been built to resist understanding, for which you can't get a good mental model without vast expenditure of effort, so most people are forced to write software by vibes.
|
||||
ChatGPT and friends are astonishingly powerful vibes engines, and in any given case they can often (usually?) vibe better than a human can; in particular, they can vibe code at a human level.
|
||||
Since humans are only vibing when they write code, ChatGPT is good enough to do a large chunk of the human job.
|
||||
A human can't reliably do better because almost no human (very much including me!) can develop the superhuman systems understanding that is required to *engineer* a solution.
|
||||
|
||||
I am thinking of things like:
|
||||
|
||||
* ASP.NET (see earlier).
|
||||
* Python (see earlier).
|
||||
* CSS, which is essentially a vast collection of special cases.
|
||||
* Javascript, about whose shortcomings enough words have certainly been written elsewhere.
|
||||
|
||||
[dryrun]: {{< ref "2021-02-20-in-praise-of-dry-run" >}}
|
65
hugo/content/posts/2024-10-25-marys-room.md
Normal file
65
hugo/content/posts/2024-10-25-marys-room.md
Normal file
@@ -0,0 +1,65 @@
|
||||
---
|
||||
lastmod: "2024-10-25T23:30:00.0000000+01:00"
|
||||
author: patrick
|
||||
categories:
|
||||
- philosophy
|
||||
date: "2024-10-25T23:30:00.0000000+01:00"
|
||||
title: Mary's Room
|
||||
summary: "Last weekend I was in a discussion ostensibly about whether the mind is nonphysical. Much of the discussion ended up as a rather polite shouting match about Mary's Room. Here is what I actually believe about it."
|
||||
---
|
||||
|
||||
[Mary's Room](https://en.wikipedia.org/wiki/Knowledge_argument) is a standard thought experiment purporting to argue that "however much you know about the physical world in a forever-black-and-white environment, you still learn something new when you step out of the room and experience redness for the first time".
|
||||
I, as a physicalist, do not accept this conclusion.
|
||||
Here is why.
|
||||
|
||||
# A new quale is a new low-level label
|
||||
|
||||
If you've been thinking about something for a while, and have come to a detailed understanding of it, you might decide to write down a name for it in your notebook (or even in the dictionary).
|
||||
That doesn't mean you've *discovered* a new word, or discovered anything new about the world in the act of writing it down.
|
||||
|
||||
Similarly, putting your world-simulating engine into a position where it simulates a phenomenon it's never simulated before (in Mary's Room the chosen phenomenon is traditionally "redness") doesn't necessarily cause you to "learn" anything new.
|
||||
It's just that the same existing knowledge has been assigned a first-class primitive in the underlying mental architecture, so it's much easier to access.
|
||||
|
||||
Analogously to how you made it easier to think about a concept by giving it a word, your brain made it easier to think about redness by assigning it a primitive as soon as it first encountered something red.
|
||||
(Or possibly that primitive was already assigned and waiting to be activated; perhaps redness is hard-coded specifically in the brain. If you think redness might be hard-coded, consider the smell of ammonia or similar instead, and substitute that learned quale wherever I talk about redness.)
|
||||
|
||||
That primitive "always existed" in some mathematical sense, latent in the structure of the simulator, but it was previously not accessed or used.
|
||||
|
||||
Note that the set of available primitives is not fixed up front; the brain turns out to have a *very large* supply of available slots!
|
||||
|
||||
# Why we have qualia
|
||||
|
||||
The new first-class primitive actually makes your reasoning *more sloppy* - things can "seem red" even though they "are not red" (in the sense that they don't emit the right wavelengths of light when irradiated with standard-test-compliant light) - but reasoning with this primitive is *much* faster than reasoning without it.
|
||||
Natural selection rewards speed, so your brain's architecture is predisposed to assign a primitive to "redness" instantly on first encounter.
|
||||
|
||||
The term "[System 1](https://en.wikipedia.org/wiki/Thinking,_Fast_and_Slow)" is a shorthand for some of the reasoning that takes place using *only* these efficient primitives of the architecture.
|
||||
It's much faster, because it's much less general: it can only use primitives that are already represented efficiently, and it can't take account of the ways in which those primitives are only approximations of the world (which is why optical illusions still "feel wrong" even when you know how they work).
|
||||
|
||||
# Qualia can also be learned the hard way
|
||||
|
||||
There are some concepts which *don't* get insta-compiled like redness does: for example, the notion of a group in mathematics is one we're simply not hard-wired to convert instantly into a compatible form for System 1.
|
||||
For a fuzzier example, the notion of "prime number" is one that people can *learn* a primitive for: a number can feel "more prime" or "less prime", and the more you work with prime numbers, the more you start "actually feeling" whether a number is prime and the more System 1 starts having opinions about primality.
|
||||
|
||||
On the other hand, it was very necessary in the ancestral environment to be able to reason quickly and intuitively about things like "*precisely* what chemicals are around me" or "what vibrations are happening near me"; so natural selection eventually predisposed the brain to go absolutely wild in immediately assigning unique highly-accessible identifiers to smells and sounds.
|
||||
|
||||
# Mary is a just-in-time compiler
|
||||
|
||||
Mary carefully built up a knowledge of redness through years of study.
|
||||
She defined a symbolic representation - an [opcode](https://en.wikipedia.org/wiki/Opcode) - and became able to manipulate it through her System 2 reasoning process.
|
||||
|
||||
When Mary stepped out of the room, it's a bit like that opcode was suddenly [JIT](https://en.wikipedia.org/wiki/Just-in-time_compilation)-compiled into machine code, making it *extremely* accessible to System 1.
|
||||
Her brain already came preloaded with a large unused space of appropriate instructions in the machine code architecture; the brain selected one of those instructions (perhaps at random, or perhaps in a way that's common to most humans thanks to shared genetic coding for that specific structure).
|
||||
That JIT didn't happen until her brain actually received the input for the first time.
|
||||
|
||||
I have a more speculative claim, which isn't central to the argument but if true would simply refute Mary's Room entirely, by showing that the experiment could never be performed: if she were well practised with meditation and dream-control and so forth, I claim she could make this JIT process happen without ever seeing red in the world.
|
||||
As evidence, I gesture towards the fact that humans can enter the [jhanas](https://en.wikipedia.org/wiki/Dhyana_in_Buddhism) and find genuinely new experiences this way.
|
||||
(However, it's possible that the human brain architecturally just can't induce these low-level hacks on itself. My bet is that it can, but if she can't, I think that's a reflection of her bounded access to her own hardware, rather than showing that there were some fundamentally non-physical truths.)
|
||||
|
||||
# Inverted spectrum
|
||||
|
||||
["Is my red the same as your red?"](https://en.wikipedia.org/wiki/Inverted_spectrum)
|
||||
|
||||
I don't know the answer to this empirical question.
|
||||
|
||||
* Is the "redness" representation hardcoded, or is it randomly assigned from the wide available pool of qualia devoted to colour? (We could perhaps prove it to be hardcoded if we were able to identify specific parts of the genome which result in specific nerves carrying the red cones' signals to specific structures within the visual processing centre, and using techniques from mechanistic interpretability to identify that the presence of this structure causes redness to manifest the same way in all humans. Or perhaps it's not hardcoded after all!)
|
||||
* Are the reasoning algorithms so perfectly isomorphic between humans that it's even meaningful to say that my quale *is the same as* your quale? (Again partly an empirical question; we could probably show this to be *false* if we could trace the execution of two brains finely enough and their representations turned out to be wildly divergent!) Perhaps two humans can simply have architectures which so fundamentally differ in how they model the world that it's *not* meaningful to say that they are "experiencing the same thing" when exposed to the same input. (Is the `ADD` instruction "the same" in [aarch64](https://en.wikipedia.org/wiki/AArch64) vs [x86-64](https://en.wikipedia.org/wiki/X86-64): do the two processors experience "the same operation", or does the wildly differing architecture make that a meaningless or false statement? Does it even matter, since they have the same result?)
|
28
hugo/content/posts/2024-11-28-net9-aot.md
Normal file
28
hugo/content/posts/2024-11-28-net9-aot.md
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
lastmod: "2024-11-28T20:10:00.0000000+00:00"
|
||||
author: patrick
|
||||
categories:
|
||||
- philosophy
|
||||
date: "2024-11-28T20:10:00.0000000+00:00"
|
||||
title: NativeAOT in .NET 9 and Nixpkgs/darwin
|
||||
summary: "How to get a NativeAOT build using nixpkgs"
|
||||
---
|
||||
|
||||
When nixpkgs was at commit [af51545ec9a44eadf3fe3547610a5cdd882bc34e](https://github.com/NixOS/nixpkgs/tree/af51545ec9a44eadf3fe3547610a5cdd882bc34e), the following sufficed for `dotnet publish --self-contained --configuration Release` to Just Work to build a `<PublishAot>true</PublishAot>` executable on aarch64-darwin:
|
||||
|
||||
```nix
|
||||
{
|
||||
outputs = { nixpkgs, ... }:
|
||||
let pkgs = nixpkgs.legacyPackages.aarch64-darwin; in
|
||||
{
|
||||
devShell = pkgs.mkShell {
|
||||
buildInputs = [ pkgs.dotnetCorePackages.sdk_9_0 ];
|
||||
packages = [
|
||||
pkgs.clang
|
||||
pkgs.darwin.ICU
|
||||
pkgs.darwin.binutils
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
77
hugo/content/posts/2025-03-08-consciousness.md
Normal file
77
hugo/content/posts/2025-03-08-consciousness.md
Normal file
@@ -0,0 +1,77 @@
|
||||
---
|
||||
lastmod: "2025-03-08T13:30:00.0000000+00:00"
|
||||
author: patrick
|
||||
categories:
|
||||
- philosophy
|
||||
date: "2025-03-08T13:30:00.0000000+00:00"
|
||||
title: A Bitcoin analogy for Multiple Drafts theory of consciousness
|
||||
summary: "I've never actually seen anyone write down precisely the way I think about consciousness, so here it is: it's (gasp!) like a blockchain."
|
||||
---
|
||||
|
||||
*This is basically Dennett's Multiple Drafts theory of consciousness as laid out in _Consciousness Explained_, Metzinger's self-model theory that the perception of a "self" is just another part of a model of the world, and Andy Clark's predictive processing theory; but with an additional trendy analogy to indicate a real-world proof-of-concept that Multiple Drafts systems can exist. Epistemic status: it's all vibes, bro. I think Claude thinks this post is bad.*
|
||||
|
||||
## Headline
|
||||
|
||||
There's no inherent single thread of consciousness; instead, it emerges as a best-effort attempt to record after-the-fact a coherent thread out of a much more confused jumble.
|
||||
This coherent thread actually models *what you were* pretty well in a behavioural sense, though, so as a simplifying assumption it's reasonable to say that it's functionally "real", and we call it your "consciousness".
|
||||
It's not a precise record of what you were experiencing, because it's only formed after the fact by discarding a great deal of information, but it's close enough that it's intuitive and useful to keep around in your memory.
|
||||
|
||||
## Background: Multiple Drafts, self-models, and predictive processing
|
||||
|
||||
The brain is a powerful prediction engine, with a single job: to model the world faithfully, [subject to certain constraints](https://en.wikipedia.org/wiki/Free_energy_principle) hard-wired by natural selection.
|
||||
For example, the prediction that "my body is experiencing pain" is hard-wired to have low probability, with the result that the prediction engine's connections to the body cause the body's machinery to take actions that reduce the pain.
|
||||
([One person's modus ponens is another person's modus tollens](https://gwern.net/modus): a strong prediction that the body is in a different place can cause the body to move to a different place, as the machinery which provides the evidence of location adjusts itself to validate the strong prediction coming in from the brain.)
|
||||
This is Clark's predictive processing explanation for how a "mere" prediction engine can take actions in the world.
|
||||
|
||||
One of the things that's present in the world, and therefore within the purview of the brain, is the brain itself, and the body that it's located in.
|
||||
Very early in development, or possibly in a move hard-coded by natural selection, the brain discovers that a pretty parsimonious explanation for what this brain and body tend to do is "this is an agent with desires", so the brain adopts that explanation pending strong evidence to the contrary.
|
||||
(I have no opinion on where this "agents exist" modelling simplification/assumption comes from; I think it would be aesthetically neater for the new brain to learn from scratch that agents are a good model of the world, but when has natural selection ever chosen the neat answer? Claude says "Research by Meltzoff and others suggests that infants begin with innate mechanisms for social cognition rather than discovering agency". Anyway, this point is not central to my argument; I'm sure
|
||||
the field of developmental psychology has an actual answer.)
|
||||
This is basically part of Metzinger's self-model theory, that the existence of a "self" is something that is natural to derive simply by looking at the world and asking how to explain the data you receive from the world.
|
||||
|
||||
To model accurately an agent with desires, it's necessary to model that agent's desires and reasoning processes.
|
||||
Any attempt to model *anything*, though, is subject to revision in the light of new incoming evidence, and in particular the brain's model of its own reasoning is constantly in flux.
|
||||
Some of its models will prove to be pretty accurate, and some will not; the ones which are not are discarded, and the ones which are accurate get enshrined in memory.
|
||||
These models are the "multiple drafts" of Dennett.
|
||||
|
||||
Importantly, the brain has no single one-true-model of itself at the time that it's making predictions; there are *only* the many models arising within the prediction engine, competing as all explanations do to explain the data.
|
||||
Most of the models agree in many ways, because the brain is pretty good at its job, and those things get committed to memory quickly and confidently.
|
||||
There are also many fringe parts of the predictions where the models disagree (because there's less evidence that would prove or refute noncentral parts of the model), and the memory system doesn't commit those quickly or at all.
|
||||
|
||||
The intuition of a single thread of personhood arises from the "intersection of all the models" being committed to memory: those features of the competing models of oneself which agree and explain the behaviour of this fictional "agent that exists in the world" that is you.
|
||||
But this intersection is itself just the memory subsystem's best attempt to record a consistent model; there are many other possible such records, in principle, and it's down to simple accident which one gets "written down".
|
||||
Moreover, memory is mutable, so even the one which got written down is constantly changing (usually only in little ways, but sometimes in huge ways).
|
||||
|
||||
## Speculative aside
|
||||
|
||||
*Epistemic status: Claude believes this section is false, because "research by Tore Nielsen and others on micro-awakenings and thought formation during sleep transitions (Nielsen, 2000, in Behavioral and Brain Sciences) suggests that the phenomenology of losing thoughts during sleep onset relates to reduced activity in the prefrontal cortex and default mode network, not to failures of memory commitment per se". This appears to be referencing
|
||||
[A review of mentation in REM and NREM sleep: “Covert” REM sleep as a possible reconciliation of two opposing models](https://www.dreamscience.ca/en/documents/publications/_2000_Nielsen_BBS_23_851-866_c-rem.pdf). Perplexity believes that the paper does not support Claude's objection. The paper is pretty lengthy and dense, and I wanted to get this post out.*
|
||||
|
||||
You can sometimes actually feel the negative space when you *fail* to commit a memory, when you're falling asleep.
|
||||
If you've had a train of thought which you simply lose because you're falling asleep, that's what it feels like when the intersection of some of these drafts fails to be committed.
|
||||
You feel that there *was* a coherent self (the memory subsystem would normally have committed a record of what the simulated agent that is "you" was doing, and if it had done so, it would have become the basis of the coherent future "you"), but you have completely lost access to what that self was (the memory subsystem did not in fact commit anything).
|
||||
This is probably a good thing, because pre-sleep thoughts can get pretty weird (i.e. contradictory with the usual self), and you probably don't want them to become foundational parts of yourself!
|
||||
|
||||
## The blockchain analogy
|
||||
|
||||
There's actually a Multiple Drafts system operating in the wild!
|
||||
Perhaps by musing on what it might feel like to "be the blockchain", we can intuitively feel Multiple Drafts in action.
|
||||
|
||||
There is no single necessary consciousness, just as there is no single necessary history of the Bitcoin blockchain.
|
||||
In the case of Bitcoin, a coherent history arises from the many validator nodes collectively agreeing on that history; but on short time horizons as the transactions are taking place, there is *no* coherent history.
|
||||
Instead, there are leaves of the Merkle tree constantly springing into being (one for every validator node) and being discarded (when the node becomes convinced that it has lost the race to commit its suggestion of what the history should be).
|
||||
These ephemeral leaves are equally "valid" as branches of history, but most of them are simply forgotten due to quirks of the distributed consensus algorithm: the nodes decide that *other* nodes are likely going to reject their attempts at history, so they abandon them quickly.
|
||||
|
||||
Similarly, in the brain there are many models of the world being postulated to explain current sense data, and in particular there are many models of the engine that is doing the prediction; and some of these models successfully continue predicting the world over short horizons, while some do not (and are discarded).
|
||||
The memory subsystem tries to collect a coherent intersection of the successful models, and records this history, because it's valuable evidence about what the prediction engine (the self) is going to do in the future.
|
||||
But there's no specific time when this happens; some detail gets cemented into history when the memory subsystem is confident in it, but this can be mutated years later, when you replay the memory and reconstruct what you think you must have been feeling at the time.
|
||||
The models which the memory subsystem believes aren't correctly cohering with the "self" get discarded, just as the failed leaves of the Merkle tree are forgotten.
|
||||
|
||||
The brain is probably not as neat as the blockchain: we don't end up with (say) a thousand clearly-delineated models which are then filtered based on how well they predict incoming evidence, and explicitly chosen or rejected.
|
||||
But I find this a compelling proof-of-concept that a coherent "history of the self" can arise from a wild cacophony of competing attempts to commit predictions of the self.
|
||||
|
||||
Is that history "real" despite being "merely emergent"?
|
||||
Sure, if you like, although it's certainly very mutable.
|
||||
For a start, there's the possibility of a "hard fork" (e.g. if you suddenly achieve religion and reinterpret your entire self).
|
||||
But more commonly, because your memory isn't perfect, you have to rerun your model of yourself to some extent when replaying a memory, to fill in the gaps; and your model of yourself *now* is a bit different to your model of yourself *then*, so the replay isn't quite faithful (this is the "false memory" phenomenon studied by Elizabeth Loftus, where rehearsing history rewrites history).
|
||||
That's not something that happens with the blockchain, of course, so in some sense the blockchain is "more real" as a persistent object than my consciousness is: the blockchain won't mutate its history as I try and study it.
|
52
hugo/content/posts/2025-06-16-llms-redux.md
Normal file
52
hugo/content/posts/2025-06-16-llms-redux.md
Normal file
@@ -0,0 +1,52 @@
|
||||
---
|
||||
lastmod: "2025-06-16T09:28:00.0000000+01:00"
|
||||
author: patrick
|
||||
categories:
|
||||
- programming
|
||||
date: "2025-06-16T09:28:00.0000000+01:00"
|
||||
title: LLM effect on my programming (2025 edition)
|
||||
summary: "Since my last post about this in 2024-03, LLMs have become a distinctly positive addition to my ability."
|
||||
---
|
||||
|
||||
I wrote in a [previous post] that ChatGPT 4 was not clearly having a positive effect on my ability to code.
|
||||
|
||||
We're over a year later now, and we have larger models and reasoning models, and those *are* definitely an improvement over not having them.
|
||||
|
||||
# As documentation-knower
|
||||
|
||||
[Opus 4](https://claude.ai) has memorised how .NET works to a terrifying level of detail.
|
||||
In general, I can ask it minutely specific questions about the .NET runtime and it will simply answer them correctly.
|
||||
|
||||
I found Gemini 2.5 Pro to be fairly solid as an engine for searching the .NET spec (which I uploaded to its context), although still quite prone to making things up.
|
||||
|
||||
# As bug-finder
|
||||
|
||||
Opus 4 is also a powerful debugging engine, the first one that I actually trust to tell me the cause of a bug without handholding.
|
||||
|
||||
My workflow is:
|
||||
|
||||
* Put a whole load of tracing into my code
|
||||
* Run the code to obtain the tracing
|
||||
* Dump the trace into Opus 4 (using the ordinary chat interface) along with the code (usually from working in a Project, but sometimes also supplying the `git diff` against `main` if I believe that the diff introduced the bug), and ask it what is wrong.
|
||||
|
||||
This Just Works alarmingly frequently.
|
||||
|
||||
# As sanity-checker
|
||||
|
||||
At work, I feed many (non-sensitive) diffs automatically on `git push` through o3-mini-high with a prompt asking for a sanity check, obvious mistakes, etc.
|
||||
This catches a bunch of really dumb stuff like typos, and is particularly valuable for the cursed dynamic languages like Groovy where you can't know whether anything is wrong without running it.
|
||||
|
||||
I've found o3-mini-high less valuable for "proper" code reviews (the sort that you'd have an engineer do to identify design problems, for example).
|
||||
|
||||
# As LeetCode solver
|
||||
|
||||
o3 is better than I am at solving well-defined tightly-scoped LeetCode-style problems.
|
||||
(Fortunately for me, I basically never have to do this in real life.)
|
||||
|
||||
# Wrapup
|
||||
|
||||
Many of my points in the previous post are still correct: I still don't trust any of the models to write code for me, and for the same reasons.
|
||||
But now the utility of the models in other areas is much higher - I now have what I described in the "What I actually want from such a system" section of the previous post, for example - and I would absolutely recommend a Claude Pro subscription.
|
||||
(I'm even considering Claude Max; Opus consumes a *lot* of quota.)
|
||||
|
||||
[previous post]: {{< ref "2024-03-27-chatgpt-and-programming" >}}
|
19
hugo/content/posts/2025-06-17-woofware-expect.md
Normal file
19
hugo/content/posts/2025-06-17-woofware-expect.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
lastmod: "2025-06-17T00:00:00.0000000+01:00"
|
||||
author: patrick
|
||||
categories:
|
||||
- programming
|
||||
date: "2025-06-17T00:00:00.0000000+01:00"
|
||||
title: Announcing WoofWare.Expect
|
||||
summary: "A basic but functional expect-testing framework for F#."
|
||||
---
|
||||
|
||||
This is a linkpost for [WoofWare.Expect](https://github.com/Smaug123/WoofWare.Expect), which implements [expect testing](https://blog.janestreet.com/the-joy-of-expect-tests/) in an F# [computation expression](https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/computation-expressions).
|
||||
Go and read [the README on GitHub](https://github.com/Smaug123/WoofWare.Expect/blob/main/README.md) if you're interested.
|
||||
|
||||
As of this writing, the following are implemented:
|
||||
|
||||
* Comparison with existing inline snapshot
|
||||
* Custom formatting of the snapshot (fully general `'T -> string` to override the default `.ToString()`)
|
||||
* Specific support for JSON snapshotting using [FSharp.SystemTextJson](https://github.com/Tarmil/FSharp.SystemTextJson), including overriding the default ser/de settings
|
||||
* "Bulk update" mode for mass regenerating snapshots in a test fixture (which is only slightly unwieldy).
|
52
hugo/content/posts/2025-06-20-dotnet-runtime-learnings.md
Normal file
52
hugo/content/posts/2025-06-20-dotnet-runtime-learnings.md
Normal file
@@ -0,0 +1,52 @@
|
||||
---
|
||||
lastmod: "2025-06-20T00:00:00.0000000+01:00"
|
||||
author: patrick
|
||||
categories:
|
||||
- programming
|
||||
date: "2025-06-20T00:00:00.0000000+01:00"
|
||||
title: Things I've learned about the .NET runtime
|
||||
summary: "While writing an MSIL interpreter, I discovered a bunch of unexpected things about the .NET runtime."
|
||||
---
|
||||
|
||||
# The JIT is actually required
|
||||
|
||||
(Or, in NativeAOT, other mechanisms that aren't just what's in System.Private.CoreLib.)
|
||||
|
||||
Some methods are JIT intrinsics, but I had previously thought the JIT was just an optimisation.
|
||||
This is false!
|
||||
For example, [Type.TypeHandle throws](https://github.com/dotnet/runtime/blob/ec11903827fc28847d775ba17e0cd1ff56cfbc2e/src/libraries/System.Private.CoreLib/src/System/Type.cs#L467-L471) and *must* be swapped out by the JIT.
|
||||
I don't know how this works on NativeAOT.
|
||||
|
||||
# `Console.WriteLine` is *incredibly* complicated
|
||||
|
||||
`Console.WriteLine` exercises at least the following:
|
||||
|
||||
* [Locking](https://github.com/dotnet/runtime/blob/4314ca34f3c620c180ef8f7fc28973af7ff47ad4/src/libraries/System.Private.CoreLib/src/System/SR.cs#L52)
|
||||
* [`Ldtoken` and type lookup](https://github.com/dotnet/runtime/blob/4314ca34f3c620c180ef8f7fc28973af7ff47ad4/src/libraries/System.Private.CoreLib/src/System/SR.cs#L84)
|
||||
* [Exception handling](https://github.com/dotnet/runtime/blob/4314ca34f3c620c180ef8f7fc28973af7ff47ad4/src/libraries/System.Private.CoreLib/src/System/SR.cs#L50)
|
||||
* [Byrefs](https://github.com/dotnet/runtime/blob/4314ca34f3c620c180ef8f7fc28973af7ff47ad4/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs#L174)
|
||||
* [Delegates](https://github.com/dotnet/runtime/blob/4314ca34f3c620c180ef8f7fc28973af7ff47ad4/src/libraries/System.Private.CoreLib/src/System/Type.cs#L737)
|
||||
|
||||
# Top-level no-exception-handler behaviour change in net9
|
||||
|
||||
In earlier versions of .NET, `finally` blocks and `Dispose` methods were liable not to run when an unhandled exception terminates program execution.
|
||||
This was documented as implementation-defined behaviour [in the C# language spec](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/exceptions#214-how-exceptions-are-handled), though it doesn't appear to be documented elsewhere.
|
||||
|
||||
That implementation-defined behaviour means my programs basically all contain this boilerplate:
|
||||
|
||||
```fsharp
|
||||
let reallyMain argv =
|
||||
0
|
||||
|
||||
let main argv =
|
||||
try
|
||||
reallyMain argv
|
||||
with
|
||||
| _ -> reraise ()
|
||||
```
|
||||
|
||||
However, in .NET 9 (I think) this behaviour appears to have been changed, and now the .NET runtime does the obvious thing - `Dispose` methods run and `finally` blocks execute even when an exception causes shutdown!
|
||||
|
||||
# The .NET runtime doesn't actually model uint32
|
||||
|
||||
Neither [on the eval stack](https://github.com/Smaug123/WoofWare.PawPrint/blob/c747d6eb3a2d138debce9c6cca763287bb21a7a9/WoofWare.PawPrint/EvalStack.fs#L60) nor [as a CLI intrinsic type](https://github.com/Smaug123/WoofWare.PawPrint/blob/c747d6eb3a2d138debce9c6cca763287bb21a7a9/WoofWare.PawPrint/BasicCliType.fs#L39) are `uint32` or `uint64` modelled; they're stored as `int32` and `int64` with two's complement.
|
71
hugo/content/posts/2025-06-21-python-pitfalls.md
Normal file
71
hugo/content/posts/2025-06-21-python-pitfalls.md
Normal file
@@ -0,0 +1,71 @@
|
||||
---
|
||||
lastmod: "2025-06-21T00:00:00.0000000+01:00"
|
||||
author: patrick
|
||||
categories:
|
||||
- programming
|
||||
date: "2025-06-21T00:00:00.0000000+01:00"
|
||||
title: Some Python surprises
|
||||
summary: "I am forever astonished that people describe Python as a simple language. Here are some of the things I found very surprising about it."
|
||||
---
|
||||
|
||||
# An assertion that can pass
|
||||
|
||||
The following code can succeed without throwing, although it's structurally very unintuitive why:
|
||||
|
||||
```python
|
||||
try:
|
||||
with Foo():
|
||||
result = blah
|
||||
except ValueError:
|
||||
result.baz()
|
||||
else:
|
||||
assert False
|
||||
```
|
||||
|
||||
This is an entry in the "you need to know how everything is implemented before you can understand it" registry: desugaring this makes it clear how it could pass (if the `__exit__` method on the context manager `Foo` throws `ValueError`), but the syntax is practically purpose-built to make it hard to see that it can.
|
||||
|
||||
# You can't monkey-patch `__add__` on an instance
|
||||
|
||||
Special methods like `__add__` are looked up on the *class*, not the instance.
|
||||
(See [Special method lookup](https://docs.python.org/3/reference/datamodel.html#special-lookup).)
|
||||
|
||||
Again, `a + b` *looks* simple, but is in fact weirdly complex and its semantics are highly unintuitive.
|
||||
|
||||
# Integers are sometimes ref-equal and sometimes not
|
||||
|
||||
```python
|
||||
a = 10000 # big enough to escape the small integer cache
|
||||
b = 10000
|
||||
a is b # False
|
||||
10000 is 10000 # True
|
||||
```
|
||||
|
||||
We're seeing a cpython optimisation in the `10000 is 10000` check: instances of literals in the same statement may be reused within that statement.
|
||||
|
||||
Personally I expected some amount of referential transparency around the `is` statement, but it turns out not!
|
||||
|
||||
# Dataclasses are implemented with strings and `eval`
|
||||
|
||||
I was astonished - it's literally [just weaving some strings together](https://github.com/python/cpython/blob/4eab9da960d6944546baa76e3eed56b809ea8ec0/Lib/dataclasses.py#L496) and [calling `exec`](https://github.com/python/cpython/blob/4eab9da960d6944546baa76e3eed56b809ea8ec0/Lib/dataclasses.py#L498)!
|
||||
I don't know it to be *incorrect*, but the sheer bluntness of the instrument amazed me.
|
||||
|
||||
# The six builtins
|
||||
|
||||
There are [six builtins in Python](https://docs.python.org/3/library/constants.html).
|
||||
`True`, `False`, and `None` are unsurprising; `__debug__` is a bit odd to be one of the six privileged constants, but fine, I guess.
|
||||
|
||||
`NotImplemented` is bizarre and suggests whole areas that you should ignore to maintain your sanity.
|
||||
|
||||
Then there's `Ellipsis`, which is the object for which `...` is sugar.
|
||||
It can, for some reason, be reassigned (when `True` etc can't)?
|
||||
(This reassignment doesn't actually have an effect, because the syntax `...` somehow manages to evaluate to `Ellipsis` even when the name `Ellipsis` itself is being used for a global. I still don't really understand what's happening here.)
|
||||
|
||||
# Multiprocessing
|
||||
|
||||
Oh *lord* the number of problems I've seen with the passing of objects across `multiprocessing` boundaries.
|
||||
|
||||
# Annoying wart: violation of Liskov substitution principle with keyword args
|
||||
|
||||
When overriding a method on a class, you can't rename the arguments - even to underscores - because argument names are part of a method's usable API surface.
|
||||
(Pyright warns about this.)
|
||||
The safe way to mark a variable as unused in an overridden method is to have the first line of the method be a useless assignment, e.g. `_ = arg_name`.
|
98
hugo/content/posts/2025-08-29-boolean-blindness.md
Normal file
98
hugo/content/posts/2025-08-29-boolean-blindness.md
Normal file
@@ -0,0 +1,98 @@
|
||||
---
|
||||
lastmod: "2025-08-29T10:23:00.0000000+01:00"
|
||||
author: patrick
|
||||
categories:
|
||||
- programming
|
||||
date: "2025-08-29T10:23:00.0000000+01:00"
|
||||
title: Boolean blindness
|
||||
summary: "Why booleans are an advanced technique that should be used with care."
|
||||
---
|
||||
|
||||
*Written off the back of [That Boolean Should Probably Be Something Else](https://ntietz.com/blog/that-boolean-should-probably-be-something-else/).*
|
||||
|
||||
Booleans often throw away information.
|
||||
Consider *not* throwing away that information unless you have some good reason to do so.
|
||||
|
||||
I know of two main use cases for booleans: indicating that some condition was met, or indicating that some state is desired.
|
||||
Here's what it means to "throw away information" in those two cases.
|
||||
|
||||
# Boolean to indicate that some condition was met
|
||||
|
||||
A boolean means "the condition was met" or "the condition was not met".
|
||||
But why are you justified in making a judgement either way on the statement "the condition was met"?
|
||||
It's usually because you ran some check that gave you evidence that the condition was met (that is, `true`), or that you have no evidence that the condition was met, or even counter-evidence (that is, `false`).
|
||||
|
||||
So why are you telling me that you ran a check and it gave you evidence?
|
||||
Just give me the evidence instead!
|
||||
|
||||
## Timestamps
|
||||
|
||||
The article linked at the top uses the example of storing timestamps in a database, instead of simply a `true` value, indicating "this event happened".
|
||||
That's an optimised case of this pattern.
|
||||
To go purely into the "give me the evidence" mode, you would actually store not a timestamp but a complete representation of the event - who did it, when, and why, for example.
|
||||
But in reality, that's just quite a lot of information, and some of it might be sensitive; so we truncate it.
|
||||
|
||||
In the boolean world, we truncate it all the way, throwing away *all* the information beyond the bare fact that the event happened.
|
||||
|
||||
But in the timestamps world, we truncate it down to just the timestamp component.
|
||||
Now, when someone asks us whether the event happened, we can give them (a small amount of) evidence that it did happen, not just a yes/no answer.
|
||||
|
||||
## Enums
|
||||
|
||||
The article then discusses the question "is this user an admin?".
|
||||
In the booleans world, again we can only say "yes" or "no".
|
||||
But if we start replying with evidence instead of brute fact, we can give the type of the user: we can say "this user is a guest" and allow the caller to deduce that the user is not an admin.
|
||||
|
||||
That is, we can answer not with a boolean but with an enum.
|
||||
|
||||
## Thresholds
|
||||
|
||||
Claude commented on an earlier draft of this essay, suggesting the case of `x > 5` as a boolean result that doesn't have rich intermediate state worth capturing.
|
||||
For such a simple check, though, I'd at least *consider* not passing the boolean around, but instead simply passing `x` and allowing the callee to perform the check explicitly.
|
||||
Perhaps you don't need to anticipate what the callee needs from you, but instead give them *everything* and let them choose.
|
||||
|
||||
# Boolean to indicate that some state is desired
|
||||
|
||||
Config objects are often just big bags of ints and booleans and things.
|
||||
This can be a decent representation, but be aware that it is often artificially restrictive: booleans are often the shadow of more general features that you might be able to offer with minimal extra effort.
|
||||
The boolean causes the user to throw away information about their intent, in conforming to your API.
|
||||
|
||||
For example, `enableLogging = false` is OK, but `logThreshold = LogLevel.None` both expresses the same intent and allows more use cases.
|
||||
|
||||
Or a boolean `putSpacesAtEnd : bool` could instead be `suffix : string`: the boolean API is a constraint on what the user can supply, when you might instead prefer to offer the more general feature.
|
||||
|
||||
Whether a more general representation is *desirable* in any particular case is another matter - API design is hard - but be aware that it's an available option, that makes the meaning much more explicit!
|
||||
|
||||
# Philosophical point
|
||||
|
||||
The type `bool` is logically equivalent to `Option<unit>`.
|
||||
If your usage of `bool` is one for which `Option<unit>` is a natural model, then it's fairly obvious that you've thrown stuff away: `unit` is a very unusual type because it's almost useless.
|
||||
In this light, it's more clearly a candidate for an optimisation that has been *prematurely* applied.
|
||||
|
||||
Here are two equivalent type signatures, one making it clear that information has been thrown away:
|
||||
|
||||
```fsharp
|
||||
let hasPermission (userId : int) : bool = ...
|
||||
```
|
||||
|
||||
```fsharp
|
||||
let hasPermission (userId : int) : Option<unit> = ...
|
||||
```
|
||||
|
||||
And here is where we *don't* throw away that information:
|
||||
|
||||
```fsharp
|
||||
let permission (userId : int) : Option<UserPermissions> = ...
|
||||
```
|
||||
|
||||
The "boolean-equivalent" example has effectively just shoved the result of `permission` through `Option.map ignore`; and `ignore` is a function that should always provoke a *little* unease.
|
||||
|
||||
# Good reasons to use booleans
|
||||
|
||||
Throwing stuff away is a standard performance technique, and indeed booleans can be good for performance: for example, you might perform some computation over the evidence, rendering the result as a boolean, and then repeatedly refer to the result of that computation.
|
||||
Like any optimisation, it's often easier to understand if it's constrained in its scope: creating a boolean internally to a function, that doesn't escape, is almost always completely fine and natural.
|
||||
|
||||
Sometimes you might want to throw away information for other reasons: perhaps you specifically need not to store that user's identifying information.
|
||||
|
||||
Booleans also give you a chance to name some condition explicitly, if that would help: instead of `if fooBar x then ...`, it might be more readable to have `let isFrobnicated = fooBar x; if isFrobnicated then ...`.
|
||||
There may be other ways to do this that don't throw away as much information, but they're often much more heavyweight.
|
@@ -1,5 +1,5 @@
|
||||
---
|
||||
lastmod: "2024-04-17T10:31:58.0000000+01:00"
|
||||
lastmod: "2024-09-27T19:31:58.0000000+01:00"
|
||||
title: My reading list
|
||||
author: patrick
|
||||
layout: page
|
||||
@@ -42,7 +42,7 @@ This page holds a list of the books I am reading, and a list of books I have rea
|
||||
|
||||
# Currently reading
|
||||
|
||||
* Accelerando, by Charles Stross
|
||||
* High Output Management, by Andy Grove
|
||||
|
||||
# Bought and ready to read
|
||||
|
||||
@@ -59,7 +59,6 @@ This page holds a list of the books I am reading, and a list of books I have rea
|
||||
* Linear Algebra Done Right, by Sheldon Axler (non-fiction, apparently the definitive textbook on linear algebra)
|
||||
* Reinventing Discovery, by Michael Nielsen (non-fiction: how modern-day collaboration could remake science)
|
||||
* The Strategy of Conflict, by Tom Schelling (book about game theory by a professional game theorist)
|
||||
* Slaughterhouse Five, by Kurt Vonnegut (depressing fiction)
|
||||
* The Quincunx, by Charles Palliser (Wilkie Collins-esque Dickensian fiction)
|
||||
* Genesis, by Bernard Beckett (future ?dystopian fiction)
|
||||
* Small Gods, by Terry Pratchett (fiction)
|
||||
@@ -75,12 +74,18 @@ This page holds a list of the books I am reading, and a list of books I have rea
|
||||
|
||||
# Have read
|
||||
|
||||
* The Diamond Age (A Young Lady's Illustrated Primer), by Neal Stephenson. After so long having the Primer in my vocabulary without having read the source of the meme, I finally did it when encountering Andy Matuschak's [Exorcising Us of the Primer](https://andymatuschak.org/primer/) and decided that actually reading the book was a prerequisite. Good book, maybe 7/10. Loved the presentation of how globalised societies can factor into tribes; loved the central idea of a device for rapidly teaching a child to be a fully rounded adult, and the periodic demonstrations that Nell is learning real skills in the real world thanks to her study. Slightly perturbed by the strange sex cult that appears to be obligatory in this kind of book. I'm excited to receive my [Daylight Computer](https://daylightcomputer.com/) because I hope it (plus [Claude](https://claude.ai)) can be some shadow of the Primer, although I've actually had some trouble finding a prompt that has Claude come close to enacting the Primer.
|
||||
* We Could Be So Good, by Cat Sebastian. Heartwarming and cute! I've never actually read anything that explored this period of gay history, and it was very gripping.
|
||||
* A Fire Upon The Deep, by Vernor Vinge. Really enjoyed this. Lots of little throwaway bits that just stayed with me ("of course our culture has spent vast amounts of leisure time working out the shortest route to bootstrapping Civilisation on a new planet", the Tines' physical construction, the idea that some cultures are impossible in some regimes of physics).
|
||||
* In Praise of Shadows, by Jun'ichirō Tanizaki. Obviously heavily romanticised, but I enjoyed this a lot. (In fact I have recently been using an audiobook of this, narrated by David Rintoul, to fall asleep to; his voice and the content are both great for that.) Some of this is actually rather sad: an old man, seeing a Western future overtake the culture of which he is a part. The aesthetic pictures his words paint are often beautiful.
|
||||
* Slaughterhouse Five, by Kurt Vonnegut. Indeed pretty depressing! I actually found this quite gripping, like you were really getting to know the protagonist, which I wasn't expecting. Felt like it did a good job of portraying a broken numbed soldier.
|
||||
* Accelerando, by Charles Stross. Weird book, which I guess is the point. I had to struggle through the first few decades, because I found the style very offputting. (Even later, the gratuitous use of jargon like "ackles": I know what an [ACL](https://en.wikipedia.org/wiki/Access-control_list) is, and perhaps such words will indeed be common in the future, but it really felt like the author was "just showing off" some basic computing knowledge.) The general idea was pretty cool, though!
|
||||
* Red Side Story, by Jasper Fforde, the second in the Shades of Grey series. I'm afraid I didn't enjoy this as much as the first book. There's a bunch of gripping worldbuilding here, but the first book was full of endearing naïvité from all characters, and this one was more "serious characters who happen to be in a whimsical setting".
|
||||
* Now It Can Be Told, by General Groves. I wasn't as taken with this book as I was with _The Making of the Atomic Bomb_; this book contained a bunch more individual callouts and "this particular person did a brilliant job" than are really necessary fifty years later. Still a bunch of excellent quotes, e.g. around how the US government paid him $35mm personally to get around procurement rules; _that's_ how you really try to win when you have trust in your employees!
|
||||
* Red Side Story, by Jasper Fforde (sequel to Shades of Grey). Solidly as I expected it to be; fairly enjoyable. Plot was largely predictable.
|
||||
* [Planecrash](https://www.projectlawful.com/). It turns out that self-insert sex fiction is not actually much better if you are self-aware about it. There's some excellent readable story in here, but you have to wade through hours and hours of sex and sex-politics to find it. Absolutely not worth reading from start to finish; just find someone to link the "dath ilan society description and basic coordination classes" highlights. These authors *really* need an editor; the work is literally at least 10x too long.
|
||||
* Tao Te Ching, by Lao Tzu, interpreted by Ursula Le Guin. Her poetry is *beautiful*. Not an easy read: I felt I was rushing at two hours for thirty-odd chapters to get the bare minimum of comprehension, but it's deep enough that each chapter would reward an hour of study. I'm currently going to improv classes, and this feels like it is secretly a book about improv!
|
||||
* Piranesi, by Susanna Clarke. Wonderful. Ethereal (but in a sort of grounded way), beautiful.
|
||||
* Impro, by Keith Johnstone. The first half of this book is very interesting, easy reading, and I suspect rather useful; I believe it's been helpful in my introductory improv lessons. (I don't know how useful it will be without practice of some sort, but I also suspect it's possible to practise without going full improv-classes.) The second half is an exploration of mask work, Commedia dell'arte, trance states, and possession, and I found that much less worth reading.
|
||||
* Impro, by Keith Johnstone. The first half of this book is very interesting, easy reading, and I suspect rather useful; I believe it's been helpful in my introductory improv lessons. (I don't know how useful it will be without practice of some sort, but I also suspect it's possible to practise without going full improv-classes.) The second half is an exploration of mask work, Commedia dell'arte, trance states, and possession, and I found that much less interesting; the first half captured me, and the second half did not.
|
||||
* Diary of a Provincial Lady, by E. M. Delafield. Hilarious. I was laughing out loud every few pages. Strong recommend. This was so like real life.
|
||||
* [Folding Beijing](https://www.uncannymagazine.com/article/folding-beijing-2/), by Hao Jingfang. Interesting short story, although really I think it could have been half the length without losing much; the premise is not exactly complicated, and the story is really just a brief exploration of the premise.
|
||||
* Permutation City, by Greg Egan. Cool book! It's interesting to think about why I find the core premise implausible, but it certainly seemed novel to me. Pretty gripping. It seems to pair quite nicely with Robin Hanson's _The Age of Em_, which would be a nonfiction accompaniment.
|
||||
@@ -88,7 +93,7 @@ This page holds a list of the books I am reading, and a list of books I have rea
|
||||
* A Handful of Dust, by Evelyn Waugh. Good Lord this is bleak. The kind of book which would definitely reward rereading; I feel like I got about a quarter of what was going on, there was so much subtext. Oddly a fun read, though!
|
||||
* The Remains of the Day, by Kazuo Ishiguro. Short, sweet, and tragic. Simple throwaway lines become retrospectively rich in meaning as you read on. Spoiler in rot13: gur haeryvnoyr aneengbe tvirf guvf fgenatr frafr bs grafvba guebhtubhg.
|
||||
* A Pocketful of Rye, by Agatha Christie. One of the Marples. Christie is generally excellent light reading, perhaps partly because her writing is all so familiar. This particular book I first read as an early teenager, but recently reread as part of a marathon in which we watched two adaptations and listened to a radio version; the exercise was actually quite interesting in seeing what the various adapters (and actors) chose to pull out.
|
||||
* The Hornblower series, by CS Forester. I read some of these over and over as a child, and they bear rereading as an adult. The later books become less interesting to me, though, as Hornblower is promoted and gets further from the action.
|
||||
* The Hornblower series, by CS Forester. I read some of these over and over as a child, and they bear rereading as an adult for some naval action from the point of view of a competent man in generally miserable circumstances. The later books become less interesting to me, though, as Hornblower is promoted and gets further from the action.
|
||||
* Station Eleven, by Emily St. John Mandel.
|
||||
* Sea of Tranquility, by Emily St. John Mandel. Short and enjoyable mystery book set across pretty large tracts of space and time. I agree with a GoodReads reviewer, though, that Cloud Atlas does a very similar thing but much better.
|
||||
* Cloud Atlas, by David Mitchell. Beautiful book. Each story is gripping in its own way. Imaginative.
|
||||
@@ -99,7 +104,7 @@ This page holds a list of the books I am reading, and a list of books I have rea
|
||||
* The SRE handbook, by the Google Site Reliability Engineering team. Super interesting. A bunch of this stuff is slowly seeping into how I think about software, with the main obvious effect on my work being that I am now much more strongly inclined to notice when I'm doing a task that could in principle be automated. However, if you're not Google, some of this stuff is probably not aimed at you; they have unique problems. I think this is worth reading for any software engineer.
|
||||
* Leadership Is Language, by David Marquet (sequel to Turn The Ship Around, discussed above). Writing this review some time after reading the book, I don't actually retain anything specific from it, but I have certainly cargo-culted some of what I know was in it - e.g. "the way you phrase things can have a strong effect on the responses you get, so think about what you're implicitly telling people when you choose to phrase something a particular way". I suspect this was worth reading.
|
||||
* The Elephant In The Brain, by Robin Hanson. This is one of those books that colours everything you think about afterwards. The premise is that all aspects of humans can be explained, and more specifically that disparate things like art and modern medicine are in large part about social signalling. Very mind-expanding, very cynical-economist. Recommended.
|
||||
* The Making Of The Atomic Bomb, by Richard Rhodes (non-fiction, about what it says on the tin). Absolutely brilliant book. Strong layman's introduction to the nuclear physics relevant to building the bomb, and plenty of humanising stories. I was not expecting to read so many pages of _Mein Kampf_ quoted in this book (I think most readers probably accept the "Hitler evil" premise). There was a chapter devoted to eyewitness accounts of the destruction of Hiroshima, which was literally sickening to read. Highly recommended.
|
||||
* The Making Of The Atomic Bomb, by Richard Rhodes (non-fiction, about what it says on the tin). Absolutely brilliant book. Strong layman's introduction to the nuclear physics relevant to building the bomb, and plenty of humanising stories. I was not expecting to read so many pages of _Mein Kampf_ quoted in this book (I think most readers probably already accept the "Hitler evil" premise without pages of explanation). There was a chapter devoted to eyewitness accounts of the destruction of Hiroshima, which was literally sickening to read. Highly recommended.
|
||||
* If on a winter's night a traveller, by Italo Calvino. I couldn't really put this down, but I also wouldn't describe it as "gripping". There are some lovely vignettes in here, and many of the stories I'd love to read more of. Recommended.
|
||||
* Infinite Jest, by David Foster Wallace. This was an infuriating book. It's so, so long, and it's so nearly excellent throughout, but honestly I got to the end and thought it wasn't worth the time I'd put into it. Some lovely bits of wordplay, a fairly good plot, excellent characterisation; if it were half the length this would be a snap recommendation.
|
||||
* To Be Taught If Fortunate, by Becky Chambers. Basically four vignettes about extrasolar worlds, each very different. Its core premise is rather different from any sci-fi I have ever read before, and the whole book is gentle.
|
||||
|
15
hugo/content/wordpress/index.html
Normal file
15
hugo/content/wordpress/index.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Redirecting…</title>
|
||||
<link rel="canonical" href="/index.html">
|
||||
<script>location="/index.html"</script>
|
||||
<meta http-equiv="refresh" content="0; url=/index.html">
|
||||
<meta name="robots" content="noindex">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Redirecting…</h1>
|
||||
<a href="/index.html">Click here if you are not redirected.</a>
|
||||
</body>
|
||||
</html>
|
@@ -19,6 +19,14 @@
|
||||
</a>
|
||||
</td>
|
||||
{{ end }}
|
||||
<td>
|
||||
<!-- RSS -->
|
||||
{{ with .OutputFormats.Get "rss" -}}
|
||||
<a href="{{ printf .Permalink }}" aria-label="RSS feed" rel="me">
|
||||
<span class="fas fa-rss fa-2x" aria-hidden="true"> </span>
|
||||
</a>
|
||||
{{ end -}}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="footer">
|
||||
|
Reference in New Issue
Block a user