--- /dev/null
+# An Algorithmic Lucidity
+
+Pelican static-site conversion of a WordPress blog (zackmdavis.net/blog). Content lives in `content/`, one Markdown file per post/page. `analgorithmiclucidity.WordPress.*.xml` is the original WXR export, used as ground truth when cross-checking whether the WordPress→Markdown conversion silently lost or corrupted formatting.
+
+## Known gotchas
+
+### Bare `$` math delimiter collides with currency amounts
+
+We use the `pelican-render-math` plugin (`PLUGINS = ['render_math']` in `pelicanconf.py`) for MathJax. Its inline-math regex is hardcoded to bare `$...$` with **no way to disable it** (source: `.venv/lib/python3.12/site-packages/pelican/plugins/render_math/pelican_mathjax_markdown_extension.py`). If a paragraph contains two or more literal `$` (e.g. two dollar amounts), they can pair up and get swallowed into a bogus math span, corrupting the render. Backslash-escaping (`\$`) does *not* help — the plugin's pattern runs at higher Markdown inline-pattern priority (185) than the `escape` pattern (180) specifically so real LaTeX commands survive, which as a side effect means it never sees escape sequences at all.
+
+Current fix, applied case-by-case as encountered: replace one or more of the conflicting `$` with the HTML entity `$` (bypasses the regex entirely since it isn't a literal `$` character in the raw source). Confirmed no other post in the corpus has this problem as of 2026-07-14 (see `content/2016/joined.md` for the one confirmed instance).
+
+**If this keeps recurring and the per-instance entity patching becomes annoying**: the real fix is switching to the `python-markdown-math` package (`mdx_math`) instead, configured with `enable_dollar_delimiter: False` (that's the default). Unlike `pelican-render-math`, it makes bare `$` a plain, forever-ordinary character and requires `\(...\)` for inline math instead — which is also MathJax's own actual default behavior (bare `$` inline math is opt-in upstream, precisely to avoid currency collisions; this Pelican plugin skipped that safety rail). Confirmed via its source (`enable_dollar_delimiter` default `False`, pattern priority 185, same escape-priority trick).
+
+Migration cost if we ever do this: (1) swap the plugin and reimplement the "only inject the MathJax `<script>` tag on pages that actually contain math" auto-detection ourselves, since that's Pelican-specific glue `pelican-render-math` provides that the plain extension doesn't; (2) convert every existing inline `$...$` math span across the corpus to `\(...\)` (display math `$$...$$` is already unambiguous and can stay as-is); (3) revert the `$` entities back to plain `$`. Not done as of 2026-07-14 — decided the entity workaround is fine for now since it's a single confirmed instance.
+
+### Automatic email-autolinking of `<...>` disabled
+
+Python-Markdown's core `automail` inline pattern (priority 110, baked into every `Markdown` instance regardless of extensions) greedily swallows any bare `<foo@bar>` into a `mailto:` autolink as one atomic match — so `<_zmd@sfsu.edu_>` (used in the Putnam posts to mimic italicized "From:"/"To:" email-client headers) got mangled: underscores baked in literally as part of the (broken) address, angle brackets consumed. Backslash-escaping didn't help either, since `<` isn't in Markdown's default escapable-character list (`>` is, `<` isn't), so `\<` just left a literal backslash in the output.
+
+Fixed permanently (rather than patched per-instance) by deregistering the pattern globally: see `_DisableAutomailExtension` in `pelicanconf.py`, wired in via `MARKDOWN['extensions']`. Confirmed this doesn't affect the separate `autolink` pattern (bare `<http://...>` URLs still auto-link fine). As of 2026-07-14, plain `<_email_>` syntax works correctly everywhere in the corpus with no escaping needed.
_Wednesday 9 October 2013—_ I did poorly on the assessment yesterday. There were eight SQL queries to write; the first five were trivial, but I bombed the last three because [I'm a moron](http://zackmdavis.net/blog/2013/08/im-a-moron/) and didn't remember that the keyword for filtering aggregations was HAVING. I worked with _William Ott_ on an ice-cream finder (which uses Google Maps APIs to print out directions to nearby ice-cream) and a Twitter client. Of course, it simply wouldn't do to write an ice-cream finder without using it to find ice-cream, so after class we took one of our program's suggestions and bought ice-cream at the Häagen-Dazs in the mall on Market and Fifth. Today I worked with _David A._; we learned about routers and controllers.
-[](http://zackmdavis.net/blog/wp-content/uploads/2013/10/our_cat_for_rent.png)
+[](http://zackmdavis.net/blog/wp-content/uploads/2013/10/our_cat_for_rent.png){: .alignleft }
_Thursday 10 October 2013—_ Dear reader, suppose [yet](http://zackmdavis.net/blog/2013/09/app-academy-diary-week-two/#sunday) [again](http://zackmdavis.net/blog/2013/09/app-academy-diary-week-three/#saturday) that you're working on the great American dog-sharing site—_loser!_ Sharing dogs is _so_ last week; you should have predicted that by now, everyone who's anyone would be renting cats instead. That's why today _Dean Yang_ and I used our prodigious knowledge of not just models, but also both views _and_ controllers, to make a mock cat-rental site! It's like this: say you visit the URL for the page that displays all the cats. Your browser issues an HTTP GET request, which is handled by the Rails router: an instance of the `CatsController` is spawned, and its `index` method is called, which puts an array of `Cat` objects (instantiated by the ActiveRecord ORM from their representations in the database) in an instance variable, which is then made available to a process that uses a template to decide how to express the information about the cats in HTML, which is then sent back to your browser. Similar stuff happens to let you make a new cat, or edit an existing cat.
My partner should object
Except she really doesn't care_
-I stare, in the mirror
+_I stare, in the mirror
Half-paralyzed in fear
My partner should object
-Except she really doesn't care
+Except she really doesn't care_
She went and proved some things which no one had surmised
Yesterday my sister won the Nobel physics prize_
-Yesterday I dreamed I won the Pulitzer prize
+_Yesterday I dreamed I won the Pulitzer prize
I uncovered the scandal, was a President's demise
I found the truth and brought it out to people's eyes
-Yesterday I dreamed I won the Pulitzer journalism prize
+Yesterday I dreamed I won the Pulitzer journalism prize_
-And then I woke up
-And rubbed my eyes
+_And then I woke up
+And rubbed my eyes_
-Yesterday my sister won the Nobel prize
+_Yesterday my sister won the Nobel prize
Her work will be a benefit to all of humankind
She went and proved some things which no one had surmised
-Yesterday my sister won the Nobel physics prize
+Yesterday my sister won the Nobel physics prize_
Tags: Python
Slug: clarity-of-intent
-```irc
+```
<bob> and here on line 79---
<bob> else:
<bob> return None
Slug: defect
[](http://zackmdavis.net/blog/wp-content/uploads/2014/03/genotype_emacs.png)
+
I—I'm afraid that examination of my [23andMe](https://www.23andme.com/) raw data has revealed a horrible truth about myself. I mean, I had always suspected, but now there's no room for doubt, no hope for denial. The terrible fact is that—
I am not a geneticist.
So this morning, shortly after I arrive in the office, plans are quickly formed for me and Alexander and our esteemed colleague Tim to go to the outpost.
-```` ```
+```
Sep 10 09:18:04 <acorwin> zackmdavis: PSL?
Sep 10 09:18:39 <zackmdavis> acorwin, I don't know what that is an initialism for
Sep 10 09:18:43 <zackmdavis> oh
Sep 10 09:18:46 <acorwin> zackmdavis: pump--
Sep 10 09:18:49 <zackmdavis> Pumpkin Spice!
-``` ````
+```
We stroll down Brannan street, chatting about the sorts of things San Francisco software engineers talk about when they're not talking about their work, like the code we've been writing not-for-work. Alexander has been making a dice game for the iPhone but has run into trouble that he doesn't know how to debug; I suggest going to an iOS meetup group and enthusiastically mention that I went to an exciting Clojure meetup the previous night (where Zach Tellman, who has more GitHub stars than me by like two and a half orders of magnitude, gave me some tips on how to improve [my 3D 2048 clone](https://github.com/zackmdavis/Thirty-Three/)).
Tags: akrasia
Slug: back-from-running
-```irc
+```
[16:03:37] <alice> I'm back from literally running, metaphorically from
figurative demons
[16:03:50] <alice> including the celebrity demon-prince Rateirs-Blak
[(Previously.)](http://zackmdavis.net/blog/2014/05/a-short-story/)
-```irc
+```
[19:26:50] <bob> alice: you still around?
[19:27:08] <alice> bob, sort of
[19:27:20] <bob> alice: ok. never mind.
alias grports="netstat -tulpn | grep"
+# cat
-+alias ?="cat"
++alias 🐱="cat"
+
# Vagrant
alias v="vagrant"
A little bit of lipstick rubbed off on the sandwich and the straw.
-I waited in the Hyatt lobby for a while, still with the jacket over my uniform, reading the Janet Mock autobiography on my PADD, until it was time to check in. After buying my Sunday wristband ($70), I wandered over to the photo-op/autograph ticketing table and bought a ticket to get a photo with Michael Dorn at 11:10 ($40). (Nana Visitor or Terry Farrell herself would have been my first choices for a celebrity photo, but they weren't there that day.)
+I waited in the Hyatt lobby for a while, still with the jacket over my uniform, reading the Janet Mock autobiography on my PADD, until it was time to check in. After buying my Sunday wristband ($70), I wandered over to the photo-op/autograph ticketing table and bought a ticket to get a photo with Michael Dorn at 11:10 ($40). (Nana Visitor or Terry Farrell herself would have been my first choices for a celebrity photo, but they weren't there that day.)
There was still a lot of time to hang out before the theater opened for the actual convention programming, but that was fine, because actual convention programming is kind of boring; the actual point of conventions is to have an excuse to dress up and wander around and talk to people and get vanity photos of other people who are using the convention as an excuse to dress up.
After de Lancie, there was a discussion with some writer-folk (the schedule _said_ the topic would be the [new series next year](https://en.wikipedia.org/wiki/Star_Trek:_Discovery), but they didn't seem to know anything about it), and soon enough, it was time for my photo op with Michael Dorn.
-The photo session was very assembly-line—here (unlike the autograph sessions I witnessed at other conventions) there was no pretense of your $40 giving you the opportunity to actually _meet_ your heroes for even half a minute: this was pose, _click_, and it's over, time for the next fan to get in position. I had time to say to Dorn, "I'm Jadzia," but that was it.
+The photo session was very assembly-line—here (unlike the autograph sessions I witnessed at other conventions) there was no pretense of your $40 giving you the opportunity to actually _meet_ your heroes for even half a minute: this was pose, _click_, and it's over, time for the next fan to get in position. I had time to say to Dorn, "I'm Jadzia," but that was it.
Not that I was disappointed. A woman on the event staff commented on how happy I looked skipping down the room after the photo was taken. "[My future husband!](http://memory-alpha.wikia.com/wiki/You_Are_Cordially_Invited_%28episode%29)" I said.
Title: Oral Tradition I
Date: 2016-05-15 10:28
Status: published
-Category: fiction
+Category: asides
Slug: oral-tradition-i
The great rabbi Computron-6f61f18b-9ebf-4379-8778-f9e5bda821d5 said: in the days of auld lang syne on Earth-that-was, a match of a very popular strategy board game was arranged between a team of grandmasters, as White, and the best computer program, as Black. White played c4. After thinking for 45 minutes, the computer resigned.
[(Previously on _An Algorithmic Lucidity_.)](http://zackmdavis.net/blog/2015/08/rustcamp-reminiscences/)
-[](http://zackmdavis.net/blog/wp-content/uploads/2016/09/sfo_reflections.jpg)
+[](http://zackmdavis.net/blog/wp-content/uploads/2016/09/sfo_reflections.jpg){: .alignright }
The other weekend, excited to learn more and connect with people about what's going on at the forefront of expressive, performant, data-race-free computing—and eager for a healthy diversion from the last two months of agonizing delirium induced by the world-shattering insight about how everything I've cared about for the past fourteen years turns out to be related in unexpected and terrifying ways that I can't talk about for reasons that I also can't talk about—I took Friday off from my dayjob and caught a Thursday night flight out of SFO to exotic Portland (... I, um, don't travel much) for [RustConf](http://rustconf.com/)!
Every reference (I kind of want to say _ampersand_) in Rust code has an associated _lifetime_, the region of the program that that reference is valid for. Lifetime annotations (appearing in angle brackets like generics and starting with an apostrophe; by convention, usually named consecutively from the start of the lowercase Latin alphabet: `'a`, `'b`, _&c._) in function signatures are used to distinguish between the lifetimes of different reference arguments, but the compiler has _lifetime ellision rules_ that cover the 90% use-cases, so you can actually write pretty substantial Rust programs without actually understanding the theory, which is both practically useful and _eternally shameful_ (for a programmer who is _satisfied_ with _not understanding_ something is not long for this world). Hence the training. [(Exercises from the training sessions are available online.)](http://rust-tutorials.com/RustConf16/)
-[](http://zackmdavis.net/blog/wp-content/uploads/2016/09/rustconf_swag.jpg)
+[](http://zackmdavis.net/blog/wp-content/uploads/2016/09/rustconf_swag.jpg){: .alignleft }
The point of lifetime analysis is to ensure that all references point somewhere valid; you can't (_can't_, the compiler won't let you) have a reference to a thing that outlives the thing itself. When you return a reference from a function, you can't be referencing something created by that function, because any such thing would die at the end of the function as it goes out of scope: a reference in the return type has to be a reference to something owned by the caller that was passed as an argument, but if there was more than one reference argument, it's ambiguous _which_ of the reference arguments has to be outlived by the returned reference, which is why you sometimes need explicit lifetime annotations ...
There were some technical difficulties getting the projectors hooked up to the laptop for the next talk. Steve Klabnik said that the break was brought to us by Apple, who is not sponsoring us, but really wants us to have a long break between talks. "They should have written it in Rust!" I shouted (as if _someone_ had to say it); Steve shrugged.
-[](http://zackmdavis.net/blog/wp-content/uploads/2016/09/compiler_says_no.jpg)
+[](http://zackmdavis.net/blog/wp-content/uploads/2016/09/compiler_says_no.jpg){: .alignright }
The projector issue got fixed and Liz Baille, developer at [Tilde](http://www.tilde.io/) and graphic-novelist, gave a really funny talk in the form of an "illustrated adventure guide" to Rust ("You might have noticed how clean and beautiful Rustlandia is, and you might have also noticed that there are no garbage cans anywhere").
Wow, has it already been a year since last RustConf?—give or take the exact date of the event sliding a bit between years—and give a month-and-a-half of procrastination before being truly struck by the mounting realization that my opportunity to blog _something_ about it [before the opportunity expires](http://zackmdavis.net/blog/2016/01/ideas-have-expirations/) has almost—but crucially, not quite—faded into oblivion. And a year-and-a-quarter since [my first contribution](http://zackmdavis.net/blog/2016/06/pose/) to the compiler? I've recently moved into the top hundred contributors by commit count, because GitHub's [contributors graph page](https://github.com/rust-lang/rust/graphs/contributors) only goes down to a hundred and [my life is controlled by what things GitHub happens to provide graphs for](http://zackmdavis.net/blog/2014/02/motivation/).
-[](http://zackmdavis.net/blog/wp-content/uploads/2017/10/rustconf_2017_swag.jpg)
+[](http://zackmdavis.net/blog/wp-content/uploads/2017/10/rustconf_2017_swag.jpg){: .alignleft }
So in the evening of Wednesday 15 August, I boarded the Amtrak [Coast Starlight](https://www.amtrak.com/coast-starlight-train) at Jack London Square station in Oakland for the long pilgrimage north to Portland to visit friend of the blog Sophia and attend this year's RustConf.
Slug: sworn-to-the-word
Ideology Makes You Stupid
+
[](http://zackmdavis.net/blog/wp-content/uploads/2017/02/sworn_to_the_word.png)
Tags: schooling
Slug: recruitment-advertisements-for-the-2024-putnam-competition-at-san-francisco-state-university
-**From**: Zack M Davis \<_zmd@sfsu.edu_\>
+**From**: Zack M Davis <_zmd@sfsu.edu_>
**Sent**: Wednesday, September 11, 2024 5:02 PM
-**To**: math_majors@lists.sfsu.edu \<_math_majors@lists.sfsu.edu_\>
+**To**: math_majors@lists.sfsu.edu <_math_majors@lists.sfsu.edu_>
**Subject**: Putnam prep session for eternal mathematical glory, 4 p.m. Thu 19 September
> One must make a distinction however: when dragged into prominence by half-poets, the result is not poetry, nor till the poets among us can be "literalists of the imagination"—above insolence and triviality and can present for inspection "imaginary gardens with real toads in them", shall we have it. In the meantime, if you demand on the one hand the raw material of poetry in all its rawness, and that which is on the other hand genuine, then you are interested in poetry.
----
-**From**: Zack M Davis \<_zmd@sfsu.edu_\>
+**From**: Zack M Davis <_zmd@sfsu.edu_>
**Sent**: Sunday, September 29, 2024 11:17 PM
-**To**: math_majors@lists.sfsu.edu \<_math_majors@lists.sfsu.edu_\>
+**To**: math_majors@lists.sfsu.edu <_math_majors@lists.sfsu.edu_>
**Subject**: Putnam prep session #2 for eternal mathematical glory ... and donuts, 2 p.m. Fri 4 October
"Hey, Goofusia," said Gallantina. "Did you see this post on the math_majors list? Someone's trying to organize a team for the [Putnam competition](https://en.wikipedia.org/wiki/William_Lowell_Putnam_Mathematical_Competition)—here, at SFSU! There's going to be **a prep session in Thornton 935 on Friday at 2 p.m.** The organizer sounds really desperate—there should be **free donuts**. Want to come?"
Tags: schooling
Slug: the-end-of-the-movie-sf-state-2024-putnam-competition-team-a-retrospective
-**From**: Zack M Davis \<_zmd@sfsu.edu_\>
+**From**: Zack M Davis <_zmd@sfsu.edu_>
**Sent**: Sunday, January 12, 2025 11:52 AM
-**To**: math_majors@lists.sfsu.edu \<_math_majors@lists.sfsu.edu_\>, math_graduate@lists.sfsu.edu \<_math_graduate@lists.sfsu.edu_\>, math_lecturers@lists.sfsu.edu \<_math_lecturers@lists.sfsu.edu_\>, math_tenure@lists.sfsu.edu \<_math_tenure@lists.sfsu.edu_\>
+**To**: math_majors@lists.sfsu.edu <_math_majors@lists.sfsu.edu_>, math_graduate@lists.sfsu.edu <_math_graduate@lists.sfsu.edu_>, math_lecturers@lists.sfsu.edu <_math_lecturers@lists.sfsu.edu_>, math_tenure@lists.sfsu.edu <_math_tenure@lists.sfsu.edu_>
**Subject**: the end of the movie: SF State's 2024 Putnam Competition team, a retrospective
> Because life is a gradual series of revelations
)
# Markdown extensions
+import markdown as _markdown
+
+
+class _DisableAutomailExtension(_markdown.Extension):
+ """Deregister core Markdown's automatic email-autolinking of bare <...>.
+
+ It greedily swallows any <foo@bar> as one atomic match, so writing
+ <_zmd@sfsu.edu_> for italicized email addresses in "From:"/"To:"
+ lines got mangled (underscores baked in literally, angle brackets
+ consumed) instead of becoming an <em> as intended.
+ """
+
+ def extendMarkdown(self, md):
+ md.inlinePatterns.deregister('automail')
+
+
MARKDOWN = {
'extension_configs': {
'markdown.extensions.codehilite': {'css_class': 'highlight', 'guess_lang': False},
'title': 'Table of Contents',
},
},
+ 'extensions': [_DisableAutomailExtension()],
'output_format': 'html5'
}