<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Unformed Delta - recommended</title>
    <description>A place to collect the things I learn, figure out, or find interesting.
</description>
    <link>https://unformeddelta.wiki/</link>
    <atom:link href="https://unformeddelta.wiki/feed/recommended.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Sat, 09 May 2026 14:44:19 +0000</pubDate>
    <lastBuildDate>Sat, 09 May 2026 14:44:19 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
    <item>
      <title>For even a bad pause</title>
      <description>&lt;p&gt;Even a global treaty pausing all new training of frontier AI models, would leave a lot of room for existing models to continue to disrupt.&lt;/p&gt;

&lt;p&gt;Our existing workflows weren’t designed with AI agents in mind and there’s abundant low hanging fruit for optimization. Every time I use Codex or Claude Code, I learn something new, and there’s plenty of things I just don’t have time to try.&lt;/p&gt;

&lt;p&gt;Beyond code there’s plenty of other domains. Claude Cowork, the 10 folders of markdown files that caused the SaaSpocalypse, Claude Design, and more aren’t new models, they’re just harnesses for making it easier to work with existing ones.&lt;/p&gt;

&lt;p&gt;What will be the impact on the economy once even our existing systems are widely adopted?&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;There’s a bunch of good things that we get for free by pausing AI progress.&lt;/p&gt;

&lt;p&gt;The technology as it exists today would diffuse. The public lags behind what those of us interested in AI see.&lt;/p&gt;

&lt;p&gt;More election cycles gives more opportunity for more informed and reasonable lawmakers to be elected. It also gives us room to negotiate and dream up better AI policies.&lt;/p&gt;

&lt;p&gt;Nothing about pausing means AI safety research needs to stop. Who knows what novel problems or breakthroughs we might find in the next years?&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Bernie Sanders and Alexandria Ocasio-Cortez’ &lt;a href=&quot;https://www.congress.gov/bill/119th-congress/senate-bill/4214/text&quot;&gt;AI Data Center Moratorium Act&lt;/a&gt; is just 1853 words — well worth reading all of.&lt;/p&gt;

&lt;p&gt;Half of the bill is a sizzle reel of quotes from experts and industry leaders. The functional section of the bill is tiny:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;154 words&lt;/strong&gt; define “Artificial Intelligence Data Center”&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;287 words&lt;/strong&gt; set the terms of the moratorium: no new AI data centers until AI is safe and built to be mutually beneficial for all Americans&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;275 words&lt;/strong&gt; requisition various reports, and give the Secretary of Energy the power to verify that the moratorium is being followed&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;161 words&lt;/strong&gt; ban the export of chips to countries not implementing similar measures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s a far cry from a global treaty. But it takes action now buying time and leverage to get a more comprehensive treaty implemented.&lt;/p&gt;

&lt;p&gt;The bill cedes our largest advantage to China. Chinese models are only 3-9 months behind the US frontier, slowing down puts us at risk of losing the frontier.&lt;/p&gt;

&lt;p&gt;This is costly, but perhaps might also serve as a signal. How can we better demonstrate our commitment to AI safety?&lt;/p&gt;

&lt;p&gt;AI labs have frequently say that they want AI regulation. I also look at this bill as an invitation to the labs: help us figure out how to make AI mutually beneficial for society, and then you can go on building the data centers you want.&lt;/p&gt;

&lt;p&gt;My largest quibble is with some of the most concrete details. To me one of the benefits of a sloppy pause are that it gives us time to contemplate what better legislation might look like. Enforcing that AI data center development be done with union labor while nice, seems far from necessary and I’d prefer a bill with less provisions about what is necessary to end the moratorium.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;I’m confident that &lt;a href=&quot;https://ifanyonebuildsit.com&quot;&gt;If Anyone Builds It, Everyone Dies&lt;/a&gt;. Will we be able to stop, or are the rewards from training better and better AI models too tempting? How long would it take us to stop even if policy makers unanimously agreed that we should?&lt;/p&gt;

&lt;p&gt;Perhaps we should slow down as much as we can now.&lt;/p&gt;
</description>
      <pubDate>Wed, 29 Apr 2026 06:51:00 +0000</pubDate>
      <link>https://unformeddelta.wiki/LOtEGaimIxO2/for-even-a-bad-pause</link>
      <guid isPermaLink="true">https://unformeddelta.wiki/LOtEGaimIxO2/for-even-a-bad-pause</guid>
      
      <category>inkhaven</category>
      
      <category>recommended</category>
      
      <category>ai</category>
      
      <category>ai-safety</category>
      
      <category>pause</category>
      
    </item>
    
    <item>
      <title>I don&apos;t want your skills</title>
      <description>&lt;p&gt;I often notice people advertising their custom skills as a solution to your agentic programming problems. They’ll provide you some genuinely useful advice, then cap it off by offering you skills that operationalizes their advice.&lt;/p&gt;

&lt;p&gt;I found the failure modes and tips identified in &lt;a href=&quot;https://www.youtube.com/watch?v=v4F1gFy-hqg&quot;&gt;Software Fundamentals Matter More Than Ever&lt;/a&gt; insightful. I never thought about having a glossary of shared vocabulary to make communication with AI agents more effective. AI agents outrunning their headlights by doing way too much autonomously provides metaphor for my common experience of having AI agents do underspecified work. Focusing on building deeper modules with a lot of functionality hiding behind a small interface, is a pattern I’ve been thinking around, but haven’t yet been able to put words to.&lt;/p&gt;

&lt;p&gt;But following the insight with skills that will “solve” the problem for you, is the equivalent to giving a tutorial on how to implement &lt;a href=&quot;https://github.com/karpathy/nanogpt&quot;&gt;nanoGPT&lt;/a&gt; and then capping it off by saying: but you can just use &lt;a href=&quot;https://chatgpt.com&quot;&gt;https://chatgpt.com&lt;/a&gt;&lt;sup id=&quot;fnref:disclaimer&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:disclaimer&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Yes, it does seem helpful to have my AI agent &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/grill-me&lt;/code&gt; — asking detailed questions instead of providing corrections to plans reflecting a fundamental misunderstanding of the problem over and over again. Of course, I’d love to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/improve-codebase-architecture&lt;/code&gt;  modularizing my codebase. But running a skill won’t help you understand how it works.&lt;/p&gt;

&lt;p&gt;These skills probably work in simpler codebases. But simpler codebases are also the best environment to understand the principles behind the skills and learn how to build them yourself. And without understanding the principles, you won’t necessarily understand that or how the skill failed in a more complex codebase.&lt;/p&gt;

&lt;p&gt;I’ve noticed this pattern before in discussions with other engineers. I explained to another engineer: just giving Claude Sonnet 4.5 our feature flag documentation plus a list of files that needed to modify was enough for it to make the changes fully autonomously. They responded by asking if I could package that up into an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/add-feature-flag&lt;/code&gt; skill.&lt;/p&gt;

&lt;p&gt;I didn’t see the point. The skill would just be 1-2 sentences of text and a list of files that needed to be modified in order to make changes to the feature flags. The skill would encapsulate nothing but the fact that this task was now easy to automate.&lt;/p&gt;

&lt;p&gt;My recommendation is to engage with content that offers you skills, but try to learn the principles behind the skills instead of using the skills themselves. Try to prompt your AI agent to solve the problem yourself.&lt;/p&gt;

&lt;p&gt;Doing this, I’ve found that after a while, I want to abstract my prompt into my own skill.&lt;/p&gt;

&lt;p&gt;I remember reading an article about adding comments to plan documents inline, instead addressing them one by one in Claude Code’s prompt. I liked this technique and after trying it, ended up building produced &lt;a href=&quot;https://github.com/lehmacdj/.dotfiles/blob/main/llm/address-comments.symskill/SKILL.md&quot;&gt;this skill&lt;/a&gt;. Though I’ve provided a link, I recommend not clicking it.&lt;/p&gt;

&lt;p&gt;Downloading skills won’t make you a good AI engineer. Understanding why they work and operationalizing the principles behind them will.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:disclaimer&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Andrey Karpathy does not do this. &lt;a href=&quot;#fnref:disclaimer&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
      <pubDate>Sat, 25 Apr 2026 04:03:00 +0000</pubDate>
      <link>https://unformeddelta.wiki/aFKl86BhaWNX/i-dont-want-your-skills</link>
      <guid isPermaLink="true">https://unformeddelta.wiki/aFKl86BhaWNX/i-dont-want-your-skills</guid>
      
      <category>recommended</category>
      
      <category>agentic-programming</category>
      
      <category>inkhaven</category>
      
    </item>
    
    <item>
      <title>programming language features (and optimizations)</title>
      <description>&lt;p&gt;My dream programming language would be able to express the syntax and semantics of every other programming language idiomatically. In this framing a good programming language would have few builtins&lt;sup id=&quot;fnref:builtins&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:builtins&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; but would still be able to manifest many more specific features as library definitions.&lt;/p&gt;

&lt;p&gt;I take a very general view of features. Optimizations are included in this list because in order practically exploit the fact that one programming can express the semantics of another, it must be able to match its performance&lt;sup id=&quot;fnref:why-match-performance&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:why-match-performance&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. Thus optimizations are more or less “features” for a programming language; they help determine what the programming language can practically be used for.&lt;/p&gt;

&lt;p&gt;Maximizing which features are expressible as part of the standard library, maximizes what users are able to rewrite. If users don’t like the features the language provides in its standard library they can write their own. Such a language is maximally flexible for users.&lt;/p&gt;

&lt;p&gt;Of course, actually using custom built features comes at the expense of interoperability with the broader ecosystem. But I think it is better to give users the choice of what they need to interoperate with, rather than artificially restricting it to guarantee good interoperability&lt;sup id=&quot;fnref:go-lang&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:go-lang&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;With a sufficient floor of metaprogramming capabilities, any feature could be implemented as a builtin or as part of the standard library. I collect this list so that I can sort/consider which features are more primitive and which are the most useful to be able to reprogram. Each programming language features thus becomes both a test and an axiom for programming language expressivity.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Meta note: I went through and made a bunch of these notes public. There’s still a lot of links that aren’t public. A lot of the pages themselves are stubs and have highly varying levels of research/detail/revision put into them.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;meta-programming&quot;&gt;&lt;a href=&quot;/ncxpONlAUxwN/meta-programming&quot;&gt;meta programming&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Features enabling and enabled by metaprogramming. In some sense these are the most important because they’re what enables implementing features in terms of each other. I’m also interested in evaluating which of these features are the most irreducible.&lt;/p&gt;

&lt;p&gt;Features providing metaprogramming ability:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/NBcoqhpqPI7Q/homoiconicity&quot;&gt;homoiconicity&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/QKeZY0XKOiI6/get-runtime-string-of-compile-time-identifier&quot;&gt;get runtime string of compile-time identifier&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/xWpiR33ashZN/storing-morphological-data-with-identifiers&quot;&gt;storing morphological data with identifiers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/8BHXL4aXonrC/compile-time-execution-of-code-assertion-baking-code&quot;&gt;compile time execution of code assertion / baking code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Features implementable by metaprogramming:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;embedded query languages, e.g. &lt;a href=&quot;/JJkIIMTFCOS2/linq&quot;&gt;LINQ&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;EDSLs in general get better as metaprogramming is better supported by a programming language&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Features kind of like metaprogramming in terms of the expressiveness they provide:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/Z1PKno9u7n88/overloadable-literals&quot;&gt;overloadable literals&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/xHw0NhTYpNsv/first-class-patterns&quot;&gt;first class patterns&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/iJCO4lkr7tNY/first-class-constructor-names&quot;&gt;first class constructor names&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/zgEZe8EylXt3/first-class-modules&quot;&gt;first class modules&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/6lzBYvOGzs77/self-types&quot;&gt;self types&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2glFqLPSCCmX/lambda-with-receiver&quot;&gt;Lambda with receiver&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/gSlE0WOhgelG/contextual-keywords&quot;&gt;contextual keywords&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/CPg3TGdClzgM/raw-identifiers&quot;&gt;raw identifiers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/6lFX3b2wE4N9/functional-tactics-languages-for-proof-assistants&quot;&gt;functional tactics languages for proof assistants&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;working-with-generally-monadic-effects&quot;&gt;working with (generally monadic) effects&lt;/h2&gt;
&lt;p&gt;This category encapsulates language features that make working with effects easier:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;do notation&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/AfQULF8hGowN/monad-extraction&quot;&gt;monad extraction&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/aZQHyB6nrpSg/idiom-brackets&quot;&gt;idiom brackets&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;lifted versions of boolean operators&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/vwO1Erpqe9jg/dedicated-syntax-for-specific-effects&quot;&gt;dedicated syntax for specific effects&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/9prPQE3hGLjS/pattern-match-failures-are-an-effect-parsers-via-pattern-matching&quot;&gt;pattern match failures are an effect / parsers via pattern matching&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/NqZArcVKG3dy/the-runtime-system-should-be-deeply-tied-to-effect-system&quot;&gt;the runtime system should be deeply tied to effect system&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/kX1jiVaBymWv/implicit-conversions-between-effects&quot;&gt;Implicit Conversions Between Effects&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;See also: &lt;a href=&quot;/t1WnMS8gb0uo/effects&quot;&gt;Effects&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;working-with-coeffects&quot;&gt;working with coeffects&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/zOnT5C3LH1V2/method-with-notation&quot;&gt;method (/with) notation&lt;/a&gt;: relatively undeveloped, but interesting&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/0yMXYaW73qbq/coeffects-can-act-as-interpreters-for-effects&quot;&gt;coeffects can act as interpreters for effects&lt;/a&gt;: vague but interesting, method notation has some extra ideas for this&lt;/li&gt;
  &lt;li&gt;See also: &lt;a href=&quot;/mxPjuprza4i8/coeffects-consumer-effects&quot;&gt;coeffects / consumer effects&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;concurrency--distributed-programming&quot;&gt;concurrency / distributed programming&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/Nxtt5aJb3FnJ/structured-concurrency-nurseries&quot;&gt;structured concurrency / nurseries&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/lNKqn420Niw4/async-await&quot;&gt;async/await&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/yKIqGyLcKXQc/controlling-placement-of-logic-onto-specific-machines&quot;&gt;controlling placement of logic onto specific machines&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/dgmN2nnuWwRr/surfacing-semantic-information-about-distributed-behavior&quot;&gt;surfacing semantic information about distributed behavior&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/65rqGUe3XiKm/decomposing-transactional-systems&quot;&gt;decomposing transactional systems&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;working-with-data&quot;&gt;Working with data&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;/GQrJD6Vydss6/pattern-matching&quot;&gt;pattern matching&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/xHw0NhTYpNsv/first-class-patterns&quot;&gt;first class patterns&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/uDadVZnfjFD5/easily-checking-which-sum-case-is-used&quot;&gt;easily checking which sum case is used&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/iJCO4lkr7tNY/first-class-constructor-names&quot;&gt;first class constructor names&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Higher Kinded Data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Accessors / key paths / lenses:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;generic/uniform syntax for arbitrary n-functors/lenses&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;optimizations&quot;&gt;optimizations&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.ashermancinelli.com/csblog/2025-7-20-Ideal-Array-Language.html#why-does-this-matter&quot;&gt;someone’s ideal array programming language: ideas about non-uniform compute + SIMD + etc.&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/5JBEx6WCIHoE/stream-fusion&quot;&gt;stream fusion&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/mUFaDSi2Kni8/super-compilation&quot;&gt;super compilation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/zncYgtgbNa9x/equality-saturation-e-graphs&quot;&gt;equality saturation (e-graphs)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;evaluation-order&quot;&gt;evaluation order&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/2B407TlcHBup/lazy-evaluation-order-call-by-name&quot;&gt;lazy evaluation order / call by name&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/svrWWFkcUvTd/call-by-push-value&quot;&gt;call by push value&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;types&quot;&gt;types&lt;/h2&gt;
&lt;p&gt;Primitive types:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;basic types: &lt;a href=&quot;/48FOjJ7COOaX/closed-vs-open-types&quot;&gt;closed vs open types&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;/3dDEa8tnSN83/structs-record-types&quot;&gt;structs/record types&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;row types (i.e. extensible records)&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;/EdP0HQuZhLDD/coproducts-variants-enums&quot;&gt;coproducts / variants / enums&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;/XuvkOLlAiCEm/polymorphic-variants&quot;&gt;polymorphic variants&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;/EJjBX51KQ1Yy/recursive-µ-types&quot;&gt;recursive (µ) types&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;/qQ783yMXPPbQ/nominative-ν-types&quot;&gt;nominative (ν) types&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;/UeA8tt6iF5bq/algebraic-data-types&quot;&gt;algebraic data types&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;dependent types:
    &lt;ul&gt;
      &lt;li&gt;dependent product&lt;/li&gt;
      &lt;li&gt;dependent sum&lt;/li&gt;
      &lt;li&gt;interval / cubic type theory / univalence&lt;/li&gt;
      &lt;li&gt;cumulative universes&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;linear types&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Broader concepts:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/ZS3QCNHImVwZ/type-inference-list-of-methods-elaboration&quot;&gt;type inference (+ list of methods) / elaboration&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/6QbUR4dyX9Wd/completeness-checking&quot;&gt;completeness checking&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/E6doTkK2Znp0/subtypes-subtyping&quot;&gt;subtypes / subtyping&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/o8Dyaxi0ZKPK/structural-types&quot;&gt;structural types&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;gradual typing / migratory typing&lt;/li&gt;
  &lt;li&gt;pure functions, mutability
    &lt;ul&gt;
      &lt;li&gt;ST monad&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Weird/highly non-standard stuff:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/nrO5W22ORJzs/dual-type-operator&quot;&gt;dual type operator&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/6gtykpBojvhd/co-completeness-checking&quot;&gt;co-completeness checking&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/6lzBYvOGzs77/self-types&quot;&gt;self types&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2glFqLPSCCmX/lambda-with-receiver&quot;&gt;Lambda with receiver&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;probably not practical or interesting: &lt;a href=&quot;/Crx6jhw9TK7r/representing-types-as-just-namespaces&quot;&gt;representing types as just namespaces&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;typeclasses--traits&quot;&gt;&lt;a href=&quot;/iKz45KVyICwj/typeclasses-traits&quot;&gt;typeclasses / traits&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Typeclass features:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/MO8UYVyYLUgb/inserting-new-typeclasses-in-between-existing-ones&quot;&gt;inserting new typeclasses in-between existing ones&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/9cmxkzhW9IDE/override-typeclasses-or-implicits&quot;&gt;override typeclasses or implicits&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/3nJYq6q6JOEA/confluent-instance-resolution&quot;&gt;confluent instance resolution&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/TChq81fMCv9p/scoped-typeclasses-or-implicits&quot;&gt;scoped typeclasses or implicits&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/UnwAZzzngQLR/orphan-instances&quot;&gt;orphan instances&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/A2tVR0i9YcsB/givens-scala-3&quot;&gt;givens (Scala 3)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/ddgDTcVHs968/multiparameter-type-classes&quot;&gt;multiparameter type classes&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/I3MsqrihWOL9/auto-derived-type-classes&quot;&gt;auto derived type classes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;standard-library&quot;&gt;standard library&lt;/h2&gt;
&lt;p&gt;The main purpose of a standard library is to define the shared vocabulary that all programs can coordinate around. Because more primitive features are implemented as part of the “standard library”, it places an even larger burden on the design of its standard library.&lt;/p&gt;

&lt;p&gt;Properties the standard library should have:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;layers of primitiveness: that allow giving up progressive amounts of interoperability for the ability to redefine larger parts of the language&lt;/li&gt;
  &lt;li&gt;facilitate migrations between standard library types to make the decision to include/not-include various things as unimpactful as possible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Must haves:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/9q45qzJgPaIz/type-safe-dates-times-durations&quot;&gt;type safe dates/times/durations&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;OSString type&lt;/li&gt;
  &lt;li&gt;theorem proving:
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;/ZMtfpDsFf117/explicitly-unordered-containers&quot;&gt;explicitly unordered containers&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Things to consider adding to a type class hierarchy beyond what Haskell has:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/RoZrSQ0VADCE/partial-equality-ordering&quot;&gt;Partial Equality / Ordering&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/qy3O2KrKgJYU/selective&quot;&gt;Selective&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/nlCzhqXrt5fN/discriminators-contravariant-functor-hierarchy-on-sorting&quot;&gt;Discriminators (contravariant functor hierarchy, O(n) sorting!)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;modules--scoping&quot;&gt;modules / scoping&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/zgEZe8EylXt3/first-class-modules&quot;&gt;first class modules&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/xWpiR33ashZN/storing-morphological-data-with-identifiers&quot;&gt;storing morphological data with identifiers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/x7PUneHXkXAH/flexible-scope-resolution-with-article-like-functions-keywords&quot;&gt;flexible scope resolution with article like functions/keywords&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;limited / more local scopes:
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;/F4TTPLipKTSS/local-type-declarations&quot;&gt;local type declarations&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;/TChq81fMCv9p/scoped-typeclasses-or-implicits&quot;&gt;scoped typeclasses or implicits&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;/mpYtVwtsssAa/defining-functions-global-variables-over-a-limited-scope&quot;&gt;defining functions/global variables over a limited scope&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;lifetimes--scoping&quot;&gt;lifetimes / scoping&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/dRm9QXhhosuz/raii&quot;&gt;RAII&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/dn7y1F0E7gIR/defer-statement&quot;&gt;defer statement&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/0FSraZkV6OJ7/deconstructors-deinitializers&quot;&gt;deconstructors / deinitializers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;lifetime annotations ala rust&lt;/li&gt;
  &lt;li&gt;borrow checker&lt;/li&gt;
  &lt;li&gt;move semantics (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;consume&lt;/code&gt; in Swift)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;control-flow&quot;&gt;control flow&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/KI7CnXtB4sYS/implementing-control-flow-as-library-functions&quot;&gt;implementing control flow as library functions&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;loops:
    &lt;ul&gt;
      &lt;li&gt;for loops&lt;/li&gt;
      &lt;li&gt;foreach loops&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;/sSiTDOesjtyI/while-loop&quot;&gt;while loop&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;/n4l4TUphkC42/until-loop&quot;&gt;until loop&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;do while loop&lt;/li&gt;
      &lt;li&gt;unconditional forever loop&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;/4hDfrbOYfERt/do-while-with-block-loop&quot;&gt;do while with block loop&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/JwjtjzAsEbm9/if-statements&quot;&gt;if statements&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/Wdj1LjlC97rO/switch-case-analysis-statements&quot;&gt;switch / case analysis statements&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/T2LKKGgNsdGW/allowing-statements-to-be-used-as-expressions&quot;&gt;allowing statements to be used as expressions&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/dn7y1F0E7gIR/defer-statement&quot;&gt;defer statement&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;try { … } catch { … }&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dis-preferred:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/KAvQgJqAafP2/with-using-blocks&quot;&gt;with/using blocks&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/VeqfqfVzppXi/try-finally&quot;&gt;try { … } finally { … }&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;code-location--relocating-code&quot;&gt;code location / relocating code&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;removing indentation from nested code structures&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/DB3xJAOpe0Bf/unit-tests-can-be-co-located-with-code&quot;&gt;unit tests can be co-located with code&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;get calling function location&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/dn7y1F0E7gIR/defer-statement&quot;&gt;defer statement&lt;/a&gt; is useful for putting de-initialization next to initialization logic&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;testing&quot;&gt;testing&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/DB3xJAOpe0Bf/unit-tests-can-be-co-located-with-code&quot;&gt;unit tests can be co-located with code&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;inspection testing&lt;/li&gt;
  &lt;li&gt;unit tests can be discovered at compile time / in the IDE without necessarily running arbitrary code&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;see-also&quot;&gt;See also&lt;/h1&gt;
&lt;ul&gt;
  &lt;li&gt;programming language benchmarks for ways of testing what features are useful for programming tasks&lt;/li&gt;
  &lt;li&gt;my programming language for features that are core enough to warrant consideration as primitives for my programming language design project&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:builtins&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Features implemented with special support in the compiler. Also sometimes called intrinsics (e.g. by the rust compiler) &lt;a href=&quot;#fnref:builtins&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:why-match-performance&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Even though the lambda calculus is Turing complete and can technically implement arbitrary floating point arithmetic, no one is seriously trying to train neural networks using it. &lt;a href=&quot;#fnref:why-match-performance&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:go-lang&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;This is my largest problem with the philosophy behind the design of go-lang. While true that a simpler language leads to more uniform programming styles, it also makes it harder to build shared abstractions. &lt;a href=&quot;#fnref:go-lang&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
      <pubDate>Fri, 24 Apr 2026 00:12:00 +0000</pubDate>
      <link>https://unformeddelta.wiki/dCtl1IFIC8VF/programming-language-features-and-optimizations</link>
      <guid isPermaLink="true">https://unformeddelta.wiki/dCtl1IFIC8VF/programming-language-features-and-optimizations</guid>
      
      <category>inkhaven</category>
      
      <category>recommended</category>
      
      <category>programming-languages</category>
      
    </item>
    
    <item>
      <title>My Neovim configuration</title>
      <description>&lt;p&gt;I use Neovim for 95%+ of my writing, both prose and code. I originally picked Vim over Emacs because I liked its modal text editing. Over the following years I’ve honed it to my preferences, building up over ~4000 lines of configuration. I’ve flirted with switching to Emacs with evil-mode for a better plugin ecosystem, but Vim is too deeply engraved in my muscle memory to move away from.&lt;/p&gt;

&lt;h2 id=&quot;lua-vs-vimscript&quot;&gt;Lua vs Vimscript&lt;/h2&gt;
&lt;p&gt;I don’t have a strong preference for Lua/Vimscript. Historically, Vimscript was the only language for configuring Vim&lt;sup id=&quot;fnref:which-are-bad&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:which-are-bad&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; . I generally assume that I will always use Neovim nowadays. Neovim makes Lua a first class language for configuring Vim. In fact, in addition to bridging all of Vim’s APIs to Lua, new APIs (such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.lsp&lt;/code&gt;) are often only offered through Lua.&lt;/p&gt;

&lt;p&gt;Rewriting all of my configuration in Lua just to lose support for Vim completely seems like a waste of time, so I still keep a lot of my configuration in Vimscript. I tend to prefer Vimscript’s syntax for &lt;a href=&quot;https://github.com/lehmacdj/.dotfiles/blob/623ba890da5afff964d72010ab28214edf53e4b7/nvim.symconfig/init.vim#L241-L242&quot;&gt;mappings&lt;/a&gt; and &lt;a href=&quot;https://github.com/lehmacdj/.dotfiles/blob/623ba890da5afff964d72010ab28214edf53e4b7/nvim.symconfig/init.vim#L214-L218&quot;&gt;autocommands&lt;/a&gt; to &lt;a href=&quot;https://github.com/lehmacdj/.dotfiles/blob/af7972a429a12a86649b5671c66a4ecf267b09de/nvim.symconfig/plugin/lsp.lua#L46-L48&quot;&gt;Lua’s&lt;/a&gt; anyways. Lua’s feels a little bit too verbose, and is harder to understand quickly in my opinion.&lt;/p&gt;

&lt;p&gt;Neovim makes it very easy to mix Lua and Vimscript, which makes it possible to maintain interoperability even while maintaining configuration in both.&lt;/p&gt;

&lt;h2 id=&quot;escape-key&quot;&gt;Escape key&lt;/h2&gt;
&lt;p&gt;Because the escape key is far in the top left corner of modern keyboards, mapping &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jj&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jk&lt;/code&gt; to escape in insert mode is fairly common. I used to do this. At some point I learned that Vim and most Vim plugins for other text editors treat &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;C-[&amp;gt;&lt;/code&gt; as escape. Rebinding caps lock to control system wide, made it possible to press &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;C-[&amp;gt;&lt;/code&gt; with my two pinkies simultaneously. An escape key mapping was previously the only configuration I truly couldn’t do without so this has the added benefit of letting me use Vim-mode plugins in other editors (or Vim itself through SSH) well enough without needing to configure them.&lt;/p&gt;

&lt;h2 id=&quot;modularization&quot;&gt;Modularization&lt;/h2&gt;
&lt;p&gt;Because my config has grown quite large, I need to keep it modularized for it to stay maintainable.&lt;/p&gt;

&lt;p&gt;Mostly I rely on the runtime directory structure which allows loading a lot of files flexibly:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init.vim&lt;/code&gt; has logic that needs to run before other configuration, plus a bunch of stuff that I’ve been too lazy to move elsewhere&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plugins.vim&lt;/code&gt; is sourced from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init.vim&lt;/code&gt; and loads plugins. I have this separated out because I use a lot of plugins&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ftsyntax&lt;/code&gt; directories for autocommands improving file type detection, or adding new&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ftplugin/after&lt;/code&gt; directories house language specific configuration to prevent needing to define autocommands for them&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autoload&lt;/code&gt; directories store “library” functions that I use from other pieces of my configuration&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lua/my&lt;/code&gt; modules serve the same purpose, but for Lua code&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;plugin&lt;/code&gt; directories for configuration insensitive to loading order&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;plugins&quot;&gt;Plugins&lt;/h2&gt;
&lt;p&gt;I still use vim-plug to manage my plugins because it works well enough, and well written plugins lazy load by design, thus not requiring anything fancier.&lt;/p&gt;

&lt;p&gt;I’m a heavy plugin user so I’ll only go through my favorite plugins. The most notable category is plugins that add generic cross language features to the editor without conflicting with default keybindings:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tpope/vim-repeat&lt;/code&gt; makes it possible to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.&lt;/code&gt; with custom actions provided by other plugins. This should really just be a built in Vim feature.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tpope/vim-sleuth&lt;/code&gt; makes indentation behave sanely by default.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tpope/vim-surround&lt;/code&gt; adds a truly essential &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ys&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cs&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ds&lt;/code&gt; text editing verbs for adding/changing/deleting surrounding text&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tommcdo/vim-exchange&lt;/code&gt; provides a very useful &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cx&lt;/code&gt; text editing verb for swapping text&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wellle/targets.vim&lt;/code&gt; adds extra text objects (e.g. for function arguments) and makes existing text objects more flexible (e.g. selecting the next instance of a text object if you aren’t already inside of it)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;overcache/NeoSolarized&lt;/code&gt; for my color scheme because it’s the most modern true color Solarized color scheme that I could find. I use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim-lualine/lualine&lt;/code&gt; + &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nvim-tree/nvim-web-devicons&lt;/code&gt; to make the UI a bit prettier.&lt;/p&gt;

&lt;p&gt;For more IDE like features, I mostly rely on language servers, but some extra support is provided by plugins.&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hrsh7th/nvim-cmp&lt;/code&gt; for autocomplete though I’m considering switching off this because it is now unmaintained&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LuaSnip&lt;/code&gt; for snippets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Other than that, there’s pretty much just a bunch of syntax plugins.&lt;/p&gt;

&lt;p&gt;I’ve also factored bits of my config as plugins (e.g. &lt;a href=&quot;/Rna31XL7OHqU/vim-magic-link-paste&quot;&gt;vim-magic-link-paste&lt;/a&gt;) plus a syntax plugin for moss-lang. A way to keep it easy to edit these even though they are no longer in my dotfiles repo is to branch on whether the repository exists on my computer:&lt;/p&gt;
&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;isdirectory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;$HOME&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;/src/vim-magic-link-paste&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  Plug $HOME&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;/src/vim-magic-link-paste&apos;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
  Plug &lt;span class=&quot;s1&quot;&gt;&apos;lehmacdj/vim-magic-link-paste&apos;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This way, vim-plug won’t clone them, and I can edit the source and have it stay up to date automatically.&lt;/p&gt;

&lt;h2 id=&quot;making-changes-to-configuration&quot;&gt;Making changes to configuration&lt;/h2&gt;
&lt;p&gt;I find being able to quickly navigate to a specific bit of configuration that I want to tweak important so that I’m able to fix problems / add new configuration without breaking my flow.&lt;/p&gt;

&lt;p&gt;I use mappings that open up a configuration file in a split:&lt;/p&gt;
&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;&quot; Edit vimrc&lt;/span&gt;
nnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;Leader&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;ev &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;Cmd&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;split&lt;/span&gt; $MYVIMRC&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;CR&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;&quot; Edit plugins&lt;/span&gt;
nnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;Leader&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ep&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;Cmd&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;split&lt;/span&gt; $VIMHOME/plugins&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;vim&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;CR&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;My favorite is my one for editing language specific tweaks, it directly opens up the appropriate file for the current file type:&lt;/p&gt;
&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;&quot; Edit filetype file&lt;/span&gt;
nnoremap &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;expr&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;Leader&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ef&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&amp;lt;Cmd&amp;gt;split &apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;$VIMHOME&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;/after/ftplugin/&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&amp;amp;&lt;span class=&quot;k&quot;&gt;filetype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;.vim&amp;lt;CR&amp;gt;&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;language-specific-tweaks&quot;&gt;Language specific tweaks&lt;/h2&gt;
&lt;p&gt;I most frequently edit my language specific configuration when I’m learning a language, or using a language I haven’t edited in a while. Most commonly, language specific configuration is overrides for my global vim config like &lt;a href=&quot;https://github.com/lehmacdj/.dotfiles/blob/d360d71f7811664994519ca10f18254743364c2e/nvim.symconfig/after/ftplugin/make.vim#L1-L3&quot;&gt;not converting tabs into spaces for Makefile&lt;/a&gt; or &lt;a href=&quot;https://github.com/lehmacdj/.dotfiles/blob/9b6a637f5c17bb9f9895f8fe03d96d4be480a8b4/nvim.symconfig/after/ftplugin/markdown.vim#L39&quot;&gt;setting up soft wrapping for Markdown&lt;/a&gt;. I also include custom keybindings that are only relevant for particular file types, like &lt;a href=&quot;https://github.com/lehmacdj/.dotfiles/blob/9b6a637f5c17bb9f9895f8fe03d96d4be480a8b4/nvim.symconfig/after/ftplugin/markdown.vim#L67-L68&quot;&gt;publishing a note from my wiki&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;wiki-specific-stuff&quot;&gt;Wiki specific stuff&lt;/h2&gt;
&lt;p&gt;For my notes specifically I have a &lt;a href=&quot;https://github.com/lehmacdj/wiki-language-server&quot;&gt;custom language server&lt;/a&gt; that I use providing autocomplete + title transclusion from random ids + go to definition for navigating between notes. I rely heavily on conceal to keep markdown syntax hidden while reading notes in Neovim.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:which-are-bad&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;There also were remote plugins. But they require installing language runtimes, and have a more limited API than exposed through Vimscript. &lt;a href=&quot;#fnref:which-are-bad&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
      <pubDate>Thu, 23 Apr 2026 06:02:00 +0000</pubDate>
      <link>https://unformeddelta.wiki/LylN8Ju8BGfr/my-neovim-configuration</link>
      <guid isPermaLink="true">https://unformeddelta.wiki/LylN8Ju8BGfr/my-neovim-configuration</guid>
      
      <category>vim</category>
      
      <category>recommended</category>
      
      <category>inkhaven</category>
      
      <category>wiki</category>
      
    </item>
    
    <item>
      <title>Metadata patterns not accounted for by music apps</title>
      <description>&lt;p&gt;I hesitated a lot when first getting into anime idol music. I was definitely a little self-conscious that the album art can get fairly suggestive.&lt;/p&gt;
&lt;style&gt;
.img-blur-reveal { position: relative; flex: 1; overflow: hidden; }
.img-blur-reveal img { width: 100%; height: auto; display: block; filter: blur(20px); transition: filter 0.3s; }
.img-blur-reveal:hover img { filter: none; }
.img-blur-reveal .overlay { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; text-align: center; padding: 0.5em; pointer-events: none; transition: opacity 0.3s; }
.img-blur-reveal:hover .overlay { opacity: 0; }
&lt;/style&gt;

&lt;div style=&quot;display: flex; gap: 1em; width: 100%; align-items: flex-start;&quot;&gt;
  &lt;div style=&quot;flex: 1;&quot;&gt;
    &lt;img src=&quot;/images/ihe0bEPXK5ip-Pasted%20image%2020260421234132.png&quot; alt=&quot;Album art from THE IDOLM@STER SHINY COLORS &amp;quot;CANVAS&amp;quot; 06&quot; style=&quot;width: 100%; height: auto; display: block;&quot; /&gt;
  &lt;/div&gt;
  &lt;div class=&quot;img-blur-reveal&quot;&gt;
    &lt;img src=&quot;/images/ihe0bEPXK5ip-Pasted%20image%2020260421234152.png&quot; alt=&quot;Abum art from Duo &amp;amp; Trio Collection CD Vol. 1 Summer Vacation&quot; /&gt;
    &lt;div class=&quot;overlay&quot;&gt;13+ album art with characters wearing swimsuits&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;But more importantly I feared its complexity would render my music cluttered and unnavigable. I mostly engaged with my music &lt;em&gt;navigationally&lt;/em&gt; as opposed to &lt;em&gt;searching&lt;/em&gt;. I liked to select a genre, an artist within that genre, and then pick out an album within that genre to listen to. Instead of staring at an empty search field, wanting music for focusing, I could pick Soundtrack, evaluating that Joe Hisaishi (i.e. Ghibli Soundtracks) was chiller than John Williams (Star Wars), then Spirited Away, deciding Princess Mononoke was too gloomy and I needed a little more whimsy.&lt;/p&gt;

&lt;p&gt;Idol music would seriously upset this balance. Many tracks were only available as singles, and — GASP — would need to learn to organize my music into playlists. But as listening to nightcore music on YouTube transitioned into watching Love Live! Sunshine’s Aqours’ lyrics videos, eventually I decided that the sanctity of my navigable music library would need to be broken, and started adding μ’s and Aqours music to my music library.&lt;/p&gt;

&lt;p&gt;When I got tired of manually importing metadata I discovered &lt;a href=&quot;https://github.com/beetbox/beets&quot;&gt;beets&lt;/a&gt;, a command line tool that automatically tags music with MusicBrainz metadata. This kept my music organized, but once I was listening to a huge number of artists and franchises&lt;sup id=&quot;fnref:which-franchises&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:which-franchises&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, navigability in my music player started to break down, none the less.&lt;/p&gt;

&lt;p&gt;None of these matter when listening to an algorithm generated playlist on Spotify or YouTube Music. But regardless, I still have a strong desire to navigate — I think it helps me feel more intentional about my music listening.&lt;/p&gt;

&lt;p&gt;Classical music once had a lot of similar problems, e.g. the same piece but separate recordings different orchestras/conductors. Eventually, Apple implemented better navigability through specialized services like &lt;a href=&quot;https://classical.music.apple.com/us/browse/catalog&quot;&gt;Apple Music Classical&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;These are the metadata patterns I want custom support for when Claude is able to build me a custom music app.&lt;/p&gt;

&lt;h2 id=&quot;character-vs-voice-actor&quot;&gt;Character vs Voice actor&lt;/h2&gt;
&lt;p&gt;Each character is portrayed by a voice actor. Voice actors often also publish music as themselves, and sometimes the same voice actor portrays multiple characters&lt;sup id=&quot;fnref:example-seiyu-overlap&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:example-seiyu-overlap&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. If I want to listen to music by a particular singer because I like their voice, I’d love to be able to jump to all of the music by the voice actor. YouTube Music/Spotify usually doesn’t even show the voice actor (it depends on the franchise).&lt;/p&gt;

&lt;h2 id=&quot;deep-hierarchies&quot;&gt;Deep hierarchies&lt;/h2&gt;
&lt;p&gt;Because idol anime franchises are primarily a vehicle for selling merchandise for a huge number of characters, they end up with tons of characters sorted into different units (groups of characters that perform together). Idolm@ster is a particularly illustrative franchise&lt;sup id=&quot;fnref:see-more&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:see-more&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;: it contains at least 8 sub-franchises, of which Idolm@ster Shiny Colors contains 8 units, of which Noctchill contains 4 members.&lt;/p&gt;

&lt;h2 id=&quot;overlapping-hierarchies&quot;&gt;Overlapping hierarchies&lt;/h2&gt;
&lt;p&gt;Groups aren’t even static a lot of the time. In Idolm@ster Million Live, pretty much every new single features a never-seen-before unit. Fortunately, when credited as artist these units usually include list of their members, which makes it possible to find songs containing a particular character through search.&lt;/p&gt;

&lt;p&gt;So fans are confident their favorite character will get a new song eventually, albums/singles are often sorted into series&lt;sup id=&quot;fnref:series&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:series&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;. I often wish I could navigate between albums in the series while listening to music.&lt;/p&gt;

&lt;h2 id=&quot;tracks-you-typically-dont-want-to-listen-to&quot;&gt;Tracks you typically don’t want to listen to&lt;/h2&gt;
&lt;p&gt;Albums often bundle tracks that don’t make to listen to typically. Most albums include karaoke tracks without vocals, plus there’s often also drama tracks with character story. These are sometimes interesting to listen to, but I don’t typically want my music listening to be interrupted by a podcast.&lt;/p&gt;

&lt;p&gt;Beyond that there’s often variants of the same song: solo versions, short versions (i.e. ~1:30 versions used in rhythm games), and live recordings. MusicBrainz’s data model actually works fairly well for variants, &lt;a href=&quot;https://musicbrainz.org/work/b9b4e98c-36ad-40be-8461-10784a71e235&quot;&gt;linking recordings to a single song&lt;/a&gt;, but I haven’t found a music app that allows navigating these relationships.&lt;/p&gt;

&lt;p&gt;Music apps aren’t able to filter these out for general listening, but still expose them when desired.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:which-franchises&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;nayuta, Idolm@ster, Love Live!, Project SEKAI (especially More More Jump! and Nightcord at 25:00) are my favorites. I’ve even gone to a couple of live shows in Japan. &lt;a href=&quot;#fnref:which-franchises&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:example-seiyu-overlap&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Ruby Kurosawa and Airi Momoi’s voice actor are both Ai Furihata. &lt;a href=&quot;#fnref:example-seiyu-overlap&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:see-more&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://project-imas.wiki&quot;&gt;https://project-imas.wiki&lt;/a&gt; is organizes all this complexity neatly. &lt;a href=&quot;#fnref:see-more&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:series&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;For example there are 7 albums in THE IDOLM@STER SHINY COLORS “CANVAS” series (just numbered 01 through 07). &lt;a href=&quot;#fnref:series&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
      <pubDate>Wed, 22 Apr 2026 06:34:00 +0000</pubDate>
      <link>https://unformeddelta.wiki/ihe0bEPXK5ip/metadata-patterns-not-accounted-for-by-music-apps</link>
      <guid isPermaLink="true">https://unformeddelta.wiki/ihe0bEPXK5ip/metadata-patterns-not-accounted-for-by-music-apps</guid>
      
      <category>navigability</category>
      
      <category>idolm@ster</category>
      
      <category>idol</category>
      
      <category>music</category>
      
      <category>recommended</category>
      
      <category>inkhaven</category>
      
    </item>
    
    <item>
      <title>5 unexpectedly mindful activities</title>
      <description>&lt;p&gt;I’ve been increasingly interested in mindfulness over the past year, starting to meditate about ~2 months ago. Overall, it has been fairly transformative in terms of my qualitative stress and overall sense of well being. These are activities that didn’t seem mindful, but I ended up finding meditation like benefits in.&lt;/p&gt;

&lt;h2 id=&quot;playing-riichi-mahjong&quot;&gt;Playing Riichi Mahjong&lt;/h2&gt;
&lt;p&gt;I originally learned Riichi Mahjong at work. When Mahjong Soul added my favorite character from Idolm@ster Shiny Colors in a collab, I started to play online. At first, 5 seconds a turn felt like a tiny amount of time to identify patterns in a 14 tile hand and decide what tile to discard. But, as I got better, simpler hands became easy to play mechanically, and the extra time between turns made it easy for my mind to drift to other things.&lt;/p&gt;

&lt;p&gt;But the game has a surprising amount of depth. Even if optimal tile efficiency becomes trivial, there’s room to improve by paying more attention to what your opponents are discarding, expected value calculations, and so on.&lt;/p&gt;

&lt;p&gt;Ultimately Riichi Mahjong is still a heavily luck based game, and it’s unfortunately common to play perfectly, and still end up in last place. This creates a good opportunity for equanimity practice, by remaining composed while losing, you maximize your chances of making an extremely satisfying comeback.&lt;/p&gt;

&lt;h2 id=&quot;walking-without-listening-to-anything&quot;&gt;Walking without listening to anything&lt;/h2&gt;
&lt;p&gt;When I first was getting interested in being more mindful, I was listening to something on my &lt;a href=&quot;/VPDDYgykGJvl/airpods&quot;&gt;AirPods&lt;/a&gt; almost all of the time. I started to make an effort to only listen to podcasts or audiobooks intentionally. I started by designating transitions, such as entering a building AirPods free. At first, I frequently felt unproductive unproductive because I wasn’t ingesting information at every possible moment, and it was easy to slip into putting my AirPods and listening to something anyways. Eventually, I started to enjoy mindfully putting my shoes, and riding down the elevator before heading out for a walk. I now often notice I’m not actually enjoying what I’m listening to, and stop it, enjoying the rest of a walk in silence.&lt;/p&gt;

&lt;h2 id=&quot;brushing-my-hair&quot;&gt;Brushing my hair&lt;/h2&gt;
&lt;p&gt;Almost any mundane activity can be done mindfully. Even boring chores like brushing my hair, washing dishes, or cleaning my apartment. If anything, the more boring the activity, the more space it provides for mindful reflection. Nowadays I mostly do these activities while listening to a podcast or music if I’m having trouble motivating myself to start doing them.&lt;/p&gt;

&lt;h2 id=&quot;just-listening-to-a-podcast-or-music&quot;&gt;Just listening to a podcast or music&lt;/h2&gt;
&lt;p&gt;As I listened to less podcasts, audiobooks, and music while doing other things, I found there was still audio that I wanted to make time to listen to. Mindfully listening has helped me be more discerning of what I like best. For shorter pieces like songs, &lt;a href=&quot;/Qi6Vn8lPWDEX/4-step-attention-procedure-for-listening-or-more-generally-observing&quot;&gt;this 4 step attention procedure for listening&lt;/a&gt; is a good way to engage more deeply when desired.&lt;/p&gt;

&lt;h2 id=&quot;watching-yuru-camp&quot;&gt;Watching Yuru Camp&lt;/h2&gt;
&lt;p&gt;Laid back-camp (ゆるキャン), is a slice of life anime, focusing on high school girls going camping in and around Yamanashi prefecture (right around Mt. Fuji). Because it’s primarily slice of life, there isn’t much plot. Sometimes it features seconds of nature scenery montages and panoramas at the expense of character interaction. While watching season 1, I thought this made the show ideal for solving Jig-Saw Puzzles while watching the show. But mindfully watching the show gave me an even better experience. Watching one episode each night before bedtime gave me space to process my day and feel ready to go to sleep. After finishing the latest season, I still haven’t found anything that I like quite as much as a replacement.&lt;/p&gt;

&lt;h2 id=&quot;anything-can-be-mindful&quot;&gt;Anything can be mindful&lt;/h2&gt;
&lt;p&gt;Anything can be done mindfully as long as it isn’t too stimulating or addictive. Find activities you don’t reach for compulsively but want to do anyways. Activities that you multitask while doing or do while multitasking can be good candidates. They leave your mind free enough to pursue them with more intention. Focusing on doing such activities often makes the activity feel more meaningful.&lt;/p&gt;
</description>
      <pubDate>Sun, 19 Apr 2026 19:48:00 +0000</pubDate>
      <link>https://unformeddelta.wiki/shWm4speAqvp/5-unexpectedly-mindful-activities</link>
      <guid isPermaLink="true">https://unformeddelta.wiki/shWm4speAqvp/5-unexpectedly-mindful-activities</guid>
      
      <category>mindfulness</category>
      
      <category>inkhaven</category>
      
      <category>recommended</category>
      
    </item>
    
    <item>
      <title>Dominion is the ultimate strategic deck-builder</title>
      <description>&lt;p&gt;In Hearthstone, Yu-Gi-Oh, Magic the Gathering, or really any TCG the winner of a match is sometimes predetermined before either player has taken their first turn. Control decks are hyperspecialized to clear the tiny minions produced by an aggro deck, then grind them out with more valuable cards. Aggro decks will usually swarm the board and beat down a combo deck player before they manage to set up their combo. Combo decks tend to beat control decks, setting up a rock paper scissors like meta-game.&lt;/p&gt;

&lt;p&gt;This meta-game has immense strategic depth. Players consider the available pool of cards, and try to craft a deck with the best possible win rate. But another player could have a better win-rate by countering the straightforwardly best looking deck. Thus players must imagine the complete distribution of decks and balance using the most powerful cards, being resistant to being countered, and trying to counter their competition. This strategic depth of the meta-game has always been my favorite part of TCGs.&lt;/p&gt;

&lt;p&gt;Dominion is a deck-building game that distills this meta-game into the game itself. Players start out with a deck with just 7 coppers and 3 estates, but throughout the game purchase cards, adding them to their deck. Unlike a TCG where the available cards only changes every few months when a new set of cards is released, in Dominion each game has a different set of 10 available kingdom cards. Randomly selecting from over 500 available cards, means that there are well over \(10^{25}\) possible kingdoms&lt;sup id=&quot;fnref:extra-selection-criteria&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:extra-selection-criteria&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, each with their own strategic considerations.&lt;/p&gt;

&lt;p&gt;Much like TCGs, strategies can be sorted into different deck archetypes&lt;sup id=&quot;fnref:more-on-fundamental-archetypes&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:more-on-fundamental-archetypes&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;big money&lt;/strong&gt; decks aim to buy a province each turn, by improving the money the average 5 card hand generates&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;engines&lt;/strong&gt; optimize to draw the entire deck each turn, often buying multiple provinces in a turn&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;combos&lt;/strong&gt; utilize unique card combinations usually culminating in a single big turn in which they end the game&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;slogs&lt;/strong&gt; aim to slow down the game, while acquiring cards that give them a bigger advantage the longer the game lasts&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;rushes&lt;/strong&gt; use cards that gain more cards to end the game as quickly as possible, scoring just enough points to win&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dominion’s strategic deck building decisions dominate the game from the very start. Each turn you have a 5 card hand, only shuffling new cards into your deck after having used up your entire deck. Starting from a 10 card deck, on your first turn, you already know your second hand. Because all 10 kingdom cards are visible at the start of the game with 10 copies of each, players can plan ahead to their final deck before buying a single card.&lt;/p&gt;

&lt;p&gt;Different deck archetypes need very different cards, and often want to make very different early purchases. Hedging and buying a card that is good for multiple different plans is only useful if you actually might need to pivot based on what your opponent does. The opportunity cost of doing so is often too high to pay.&lt;/p&gt;

&lt;p&gt;Other deck-builders fail to have this strategic depth. For example, in Slay the Spire, you only see 3 cards at a time and pick one. You don’t know what cards you’ll be able to acquire later in a run. This makes committing to a longer term strategic plan foolish, because it significantly cuts your optionality&lt;sup id=&quot;fnref:lol-i-dont-care&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:lol-i-dont-care&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. Instead of replicating the, any card goes, deck building of constructed TCG formats, it replicates drafting.&lt;/p&gt;

&lt;p&gt;After creating your game plan, Dominion’s tactical gameplay is mostly mechanical. You track your deck and concretize your plan by reacting to your particular shuffle luck plus your opponents behavior. In a close game, the endgame features Dominion’s heaviest tactics, as players vie to ensure that they will be able to end the game on their turn in the lead. If you missed a good strategy, and your opponent catching you off guard, it’s usually already too late to pivot.&lt;/p&gt;

&lt;p&gt;Because winning or losing hinges on strategic deck building choices, Dominion players love to analyze kingdoms, debating at length the subtleties of different plans without even playing the game. Freed from the burden of shuffling, online Dominion games last just 10-15 minutes. Usually the first 3-5 minutes is spent figuring out what deck best suits the given kingdom.&lt;/p&gt;

&lt;p&gt;In Dominion more than any other game&lt;sup id=&quot;fnref:other-games&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:other-games&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;, strategy dominates over tactics. It doesn’t just give you the ability to, but requires playing with a bird’s eye view, thinking about the deck you plan to build, right from the start.&lt;/p&gt;

&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:extra-selection-criteria&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;There’s a bunch of extra selection factors: Landscape cards like Events, Landmarks, Projects, etc. plus cards that require extra cards like Young Witch which requires the selection of a bane, that make calculating the exact number fairly tedious. &lt;a href=&quot;#fnref:extra-selection-criteria&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:more-on-fundamental-archetypes&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;My terminology here is borrowed from Wandering Winder’s &lt;a href=&quot;https://dominionstrategy.com/2013/01/21/the-five-fundamental-deck-types-introduction/&quot;&gt;The Five Fundamental Deck Types&lt;/a&gt;. Sometimes thinking in terms of these archetypes is overly restrictive, but it’s a good starting point for understanding the different strategies one might pursue in a Dominion game. &lt;a href=&quot;#fnref:more-on-fundamental-archetypes&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:lol-i-dont-care&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;Because engines/combos appeal to me (and often are the strongest strategies in Dominion), I usually go for silly infinite combo decks with the Silent, resetting if I don’t get the cards I need. But this is more playing a slot machine, rather than finding strategic depth in Slay the Spire. &lt;a href=&quot;#fnref:lol-i-dont-care&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:other-games&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;I’ve mostly framed this as being about deck-builders, because it’s a lot easier to compare apples with apples. That said, I think Dominion has a particularly high density of strategy to tactics for any game. &lt;br /&gt; Consider chess. Though opening theory is arguably fairly strategic, it’s extremely memorization heavy. Beyond that, tactics tend to dominate. The game tree is too chaotic to make concrete plans about end-game strategy in the mid-game. &lt;br /&gt; In my opinion the strongest contender for strategically most dense game is &lt;a href=&quot;https://en.wikipedia.org/wiki/Prismata&quot;&gt;Prismata&lt;/a&gt;, which takes Dominion’s open market and removes luck completely. Unfortunately it never took off, thus has a small player base and hasn’t added as many distinct “units” (the equivalent of kingdom cards). &lt;a href=&quot;#fnref:other-games&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
      <pubDate>Sun, 19 Apr 2026 03:19:00 +0000</pubDate>
      <link>https://unformeddelta.wiki/CzZXOuq2reuv/dominion-is-the-ultimate-strategic-deck-builder</link>
      <guid isPermaLink="true">https://unformeddelta.wiki/CzZXOuq2reuv/dominion-is-the-ultimate-strategic-deck-builder</guid>
      
      <category>board-games</category>
      
      <category>strategy</category>
      
      <category>recommended</category>
      
      <category>inkhaven</category>
      
    </item>
    
    <item>
      <title>Against foolproof software</title>
      <description>&lt;p&gt;&lt;em&gt;If you’re familiar with spaced repetition systems, this should work as a standalone post. This is the last post of a 3 post series. The first two posts explain &lt;a href=&quot;/v8mH7WGj5fNz/what-makes-a-good-spaced-repetition-system-wanikani&quot;&gt;WaniKani&lt;/a&gt; and &lt;a href=&quot;/0THf60NuwInF/what-makes-a-good-spaced-repetition-system-jpdbio&quot;&gt;jpdb.io&lt;/a&gt; in more detail.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;WaniKani tries very hard to make learning Japanese foolproof. They don’t let you grade yourself or undo mistakes &lt;a href=&quot;https://knowledge.wanikani.com/wanikani/undo-button/&quot;&gt;they want to protect you&lt;/a&gt; from “the illusion of knowing”. &lt;a href=&quot;https://knowledge.wanikani.com/wanikani/skip-content/&quot;&gt;They don’t offer&lt;/a&gt; the ability to blacklist or permanently mark cards as known.&lt;/p&gt;

&lt;p&gt;These design decisions probably make WaniKani more effective for the user profiles they think about the most. WaniKani’s testimonials highlight two kinds of users:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Japanese residents&lt;/strong&gt;, who likely either need Japanese for work, e.g. “My job requires me to work with a number of Japanese companies.”, or strong intrinsic motivation, e.g. “I’ve lived in Japan for eight years”. For this kind of person, it’s easy to dedicate 1-2 hours every day to learning Japanese.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;self-learners&lt;/strong&gt;, with a lot of time to dedicate to learning Kanji. My friends who made it through much more of WaniKani than me, all fit into this category. Even for me, WaniKani worked well at first, before betraying my expectations in a couple of important ways.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First, WaniKani ended up growing into a much larger time commitment than I assumed from my first few weeks using it. WaniKani doesn’t claim how many hours per day it will take to learn Japanese in just over a year. But, because early on WaniKani’s mechanics for unlocking lessons prevented me from investing the ~30 minutes per day I wanted to, I assumed that the workload would continue to be manageable. Then, when reviewing flashcards from the past 4 months, the workload became overwhelming. jpdb.io’s better spaced repetition algorithm lets you build it into your schedule more consistently from the start, while also adapting better if you’re willing to commit less time in the future.&lt;/p&gt;

&lt;p&gt;Second, WaniKani promised to teach me “2,000 kanji, hand-picked and cleverly ordered” plus “6,000 Japanese words, all carefully validated by a human to be common or useful”. Of course, I didn’t have a good sense of what vocabulary I wanted to learn, so this was part of what appealed to me when I chose WaniKani. If I’d been willing to commit the time to mine songs and texts for vocabulary I cared about, I probably would have started with Anki. But over time, the rigidity of the curriculum started to frustrate me. I longed to be able to exclude words, even considering a Firefox extension for WaniKani that would autofill the correct answer for words that I didn’t want to review.&lt;/p&gt;

&lt;p&gt;Both of these problems were mostly a misalignment between my goals and knowledge, and the needs WaniKani’s developers assume their users have. But WaniKani is designed to be foolproof, without options or configuration that would make it less effective for certain kinds of users.&lt;/p&gt;

&lt;p&gt;Aiming for foolproof makes a lot of sense when designing a product. Less options, configuration, and variables to consider makes the product simpler. This has huge dividends for scalability. A simpler product is easier to explain, optimize, market, and sell without needing to consider the needs of individual users.&lt;/p&gt;

&lt;p&gt;But I wasn’t interested in WaniKani as a mindless consumer, I was interested in a tool to help me learn Japanese. Instead of aiming to be foolproof, jpdb.io trusts its users to accomplish their goals. This unlocks the possibility for it to be better tailored to any individual user’s specific goals.&lt;/p&gt;

&lt;p&gt;Not everyone will carefully tweak all the configuration options to figure out what works the best for them. Good defaults will make sure that the average user still has a good experience. But almost everyone has specific complaints about the products they use or things they would want tweaked. It’s worth building a configuration option for at least the most common ones.&lt;/p&gt;

&lt;p&gt;Even if users want something that you think would make the product worse, they’re probably trying to act in their own best interest. Sometimes, as the designer, you really do know better. But, at other times you don’t understand the user’s complaint well enough. If enough people request a setting you find confusing, perhaps it’s worth exercising some intellectual humility and adding it anyways, along with an explanation for why you think they shouldn’t use it&lt;sup id=&quot;fnref:jpdb-io-does-this&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:jpdb-io-does-this&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. If you trust that your users are acting in their own best interest, they’re probably motivated enough to try to understand your reasoning.&lt;/p&gt;

&lt;p&gt;Most users don’t need to be protected from themselves. Instead of making your software foolproof for your assumed user, design it to adapt to the needs of your specific users.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:jpdb-io-does-this&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;jpdb.io’s settings page actually does this several times. I haven’t changed any of the settings it recommends against. &lt;a href=&quot;#fnref:jpdb-io-does-this&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
      <pubDate>Fri, 17 Apr 2026 06:37:00 +0000</pubDate>
      <link>https://unformeddelta.wiki/YLwRkdcbZJyA/against-foolproof-software</link>
      <guid isPermaLink="true">https://unformeddelta.wiki/YLwRkdcbZJyA/against-foolproof-software</guid>
      
      <category>language-learning</category>
      
      <category>recommended</category>
      
      <category>spaced-repetition</category>
      
      <category>inkhaven</category>
      
      <category>product-design</category>
      
    </item>
    
    <item>
      <title>What makes a good spaced repetition system? (jpdb.io)</title>
      <description>&lt;p&gt;&lt;em&gt;I recommend &lt;a href=&quot;/v8mH7WGj5fNz/what-makes-a-good-spaced-repetition-system-wanikani&quot;&gt;reading yesterday’s post&lt;/a&gt; discussing my follies with WaniKani the first time I tried learning Kanji.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Over a year and a trip to Japan passed before I made a serious effort at studying Japanese again. WaniKani had failed me in several ways, and I was reluctant to try a spaced repetition system that wouldn’t solve them.&lt;/p&gt;

&lt;p&gt;I wanted something that would adapt to my existing Japanese knowledge, letting me avoid redundant flashcards. More importantly, I needed something that would respond more gracefully to getting overwhelmed or returning after a break.&lt;/p&gt;

&lt;p&gt;jpdb.io checked both of these boxes. Instead of a fixed curriculum, jpdb.io allowed you to choose exactly which vocabulary you wanted to learn. Even better, it offered a wide variety of pre-built decks with vocabulary from anime, visual novels, and books. It also claimed to handle lapses and irregular time periods between flashcard reviews better by implementing an ML based spaced repetition algorithm.&lt;/p&gt;

&lt;p&gt;jpdb.io’s flashcard system/lessons are simpler than WaniKani’s. There are only two kinds: kanji flashcards (which includes radicals) and vocabulary flashcards. Kanji flashcards come with mnemonics&lt;sup id=&quot;fnref:mnemonics&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:mnemonics&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; ask you to visualize or draw the kanji or radical based on its name while vocabulary flashcards ask you to guess the pronunciation/meaning of the word in the context of an example sentence.&lt;/p&gt;

&lt;p&gt;I was enjoying the Summer Pockets anime at the time and eager for more content, wanted to try reading the source visual novel as Japanese practice. jpdb.io configured to feed me the most common vocabulary in Summer Pockets, I raced through 30 minutes of flashcards per day, mostly marking that I would never forget vocabulary that I already knew.&lt;/p&gt;

&lt;p&gt;Unlike WaniKani, flashcards are self graded — you choose whether remembering the kanji/vocabulary was hard/medium/easy or whether you forgot the flashcard nothing/something.&lt;/p&gt;

&lt;p&gt;Anki allows using FSRS as its spaced repetition scheduler providing pretty much the same benefits as jpdb.io’s scheduler.&lt;/p&gt;

&lt;p&gt;I was aware that without strongly committing to an answer, there was a risk that I would assume that I would assume my answer was correct, even when I hadn’t really known before seeing the solution. To guard against this I took the time to trace the kanji in the air and subvocalize the vocabulary’s meaning and pronunciation before clicking through to see the solution. Deciding how to grade myself was tricky at first. Sometimes when tracing out a kanji, I would draw the right strokes but in the wrong order. Because I was only tracing into the air, it was hard to judge how accurately I’d drawn the shape, so I opted to grade myself more conservatively.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://jpdb.io/faq#SpacedRepetitionAlgorithm&quot;&gt;jpdb.io’s spaced repetition algorithm&lt;/a&gt; also lived up to its promises. I’ve noticed two main benefits in practice. First, flashcards are pretty much always the right difficulty. My accuracy on jpdb.io ended up being fairly consistent with my accuracy on WaniKani at ~90%. Despite this, I rarely get a flashcard that I want to mark as easy; usually I have to think at least a second or two, before remembering the correct answer. Second, unlike WaniKani I don’t get flashcards wrong, only to weeks later on my next review still have no idea what the right answer is. Instead, jpdb.io usually shows me the flashcard again much sooner (i.e. the next day) when I get a flashcard wrong.&lt;/p&gt;

&lt;p&gt;All of this remained true even when abandoning jpdb.io for longer periods of time, be it several weeks for a trip, or even once for several months. Just continuing to review my flashcards at whatever pace I manage when I got back, slowly reintroduces me to the flashcards I forgot, while giving me credit for remembering a longer period of time, for the flashcards I got wrong. It’s also been really nice to be able to tailor the vocabulary I’m learning to whatever Japanese media I’m consuming over the past year.&lt;/p&gt;

&lt;p&gt;I haven’t practiced Japanese quite as consistently since switching to jpdb.io. But, I’ve been using it for at least a year, whereas WaniKani burnt me out after just ~5 months. It effortlessly slots into my life when I want it to, adapting to whatever is going on in my life at the moment, making it as painless as possible to pick it back up again.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Continued in &lt;a href=&quot;/YLwRkdcbZJyA/against-foolproof-software&quot;&gt;Against foolproof software&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:mnemonics&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;At least the most common ~1000 radicals/kanji have mnemonics. I found that learning the most common words in Summer Pockets, I fairly quickly started running into some kanji missing mnemonics. But jpdb.io lets you to define custom mnemonics, which has the added benefit of making it easier to remember your mnemonic (assuming you try reasonably hard to make one). &lt;a href=&quot;#fnref:mnemonics&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
      <pubDate>Thu, 16 Apr 2026 05:01:00 +0000</pubDate>
      <link>https://unformeddelta.wiki/0THf60NuwInF/what-makes-a-good-spaced-repetition-system-jpdbio</link>
      <guid isPermaLink="true">https://unformeddelta.wiki/0THf60NuwInF/what-makes-a-good-spaced-repetition-system-jpdbio</guid>
      
      <category>japanese</category>
      
      <category>language-learning</category>
      
      <category>recommended</category>
      
      <category>spaced-repetition</category>
      
      <category>inkhaven</category>
      
    </item>
    
    <item>
      <title>What makes a good spaced repetition system? (WaniKani)</title>
      <description>&lt;p&gt;&lt;em&gt;This is part 1 of a ~3 part post. This part explains how WaniKani works through my first experience and follies using a spaced repetition system.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Japanese is one of the world’s most difficult writing systems. Compared with English, Hiragana and Katagana are simple phonetic alphabets. Their pronunciation is always consistent, and across both alphabets there’s just ~92 distinct characters plus a handful of consistent diacritics and multi-character compounds. Much easier than English where “ghoti” could arguably be pronounced “fish”&lt;sup id=&quot;fnref:ghoti-explanation&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:ghoti-explanation&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;But to read Japanese, you also need to be able to interpret at least 2000 Kanji characters. Most Kanji characters can be pronounced at least two different ways depending on context: a native Japanese pronunciation (kun’yomi) in addition to the pronunciation derived from Chinese (on’yomi). For common characters there’s usually at least one or two more. In the worst cases, for example 生, an extremely common character that Japanese children learn in first grade, a single character can have as many as 6 different kun’yomi and 2 different on’yomi.&lt;/p&gt;

&lt;p&gt;I knew all of this when I set out to learn the 2000 most common Kanji. I’d just returned from my first trip to Japan, and was more motivated to learn than ever.&lt;/p&gt;

&lt;h2 id=&quot;wanikani&quot;&gt;WaniKani&lt;/h2&gt;
&lt;p&gt;WaniKani made getting started frictionless. Kanji can be broken down into radicals, bits of characters with a consistent meaning/shape. Each WaniKani level, starts off with lessons teaching you the names of the radicals. Each radical is taught with a mnemonic and often comes with a cute picture too:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Since there are no circles in Japanese characters, sometimes rectangles or squares have to make do. In this case, this big rectangle is the &lt;strong&gt;sun&lt;/strong&gt;. The middle line is a cloud, moving across the sun. Picture it, but don’t actually look at the sun and burn your eyes!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/images/v8mH7WGj5fNz-Screenshot 2026-04-13 at 17.30.01.png&quot; alt=&quot;A shining sun with a thin cloud passing across its middle, outlined by the 日 radical.&quot; style=&quot;display: block; margin: 0 auto;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;After a couple hours, you prove that you remember the names of each of the radicals by typing them out, and then you’re done for a few hours. You review the radicals again, then again after a day, and finally if you’ve gotten the item right 4 times in a row, you’ve proven that you’ve committed the radical to your “medium-term” memory. The radical upgrades from the “Apprentice” to the “Guru” memory stage, unlocking Kanji that depend on that radical. For Kanji there’s two separate things you learn and are tested on: meaning and pronunciation. When a Kanji advances to “Guru” you unlock dependent vocabulary, again with separate meaning and pronunciation lessons. Once all but 3 Kanji in a level are “Guru”, you advance to the next level, unlocking the next set of radicals.&lt;/p&gt;

&lt;p&gt;At first, it only took 5-10 minutes a day to do all of my reviews plus new lessons. I returned to WaniKani for my reviews after the exact review time intervals, to make sure that do my reviews as soon as possible. Because I was also maintaining a high accuracy, I was able to advance a level every ~8 days. Projecting forward, it wasn’t difficult to imagine getting to the last level, level 60 in a year and a half as advertised. I was starting to notice the vocabulary I was learning in the music I listened to, excited that so as long as I could match my current pace, I would have mastered Japanese in just over a year. How naive I had been.&lt;/p&gt;

&lt;p&gt;The thing about spaced repetition systems, is that you’re trying to commit the Kanji and vocabulary to your long-term memory, remembering them indefinitely. So you keep reviewing again after 1 week, after 2 weeks, after 1 month, and finally, in WaniKani, after 4 months the item is considered “Burned” and you never see it again in reviews. Beyond that, ambient exposure through reading is probably enough to avoid forgetting it.&lt;/p&gt;

&lt;p&gt;These longer-term reviews didn’t get in the way of my high accuracy rate, but the additional workload made my review sessions start to take longer and longer. By the time I was hitting my first batch of 4 month reviews, I was spending at least an hour a day on my 200ish of my lessons and reviews. To be confident that this was as hard as hard as it would get I calculated that &lt;a href=&quot;/1zuNpog5p4DD/theres-150-vocab-radicals-kanji-per-wanikani-level&quot;&gt;about ~150 total vocab/radicals/kanji per WaniKani level&lt;/a&gt;. Some vocabulary were also starting to get fairly obscure. I’m still not exactly sure what outpatient means in English, but 外来 was one of the words I was learning in Japanese. An hour a day was a large enough time commitment that I was starting to question whether it was worth continuing.&lt;/p&gt;

&lt;p&gt;When getting an item wrong, spaced repetition systems adjust their model of how well you know that item. WaniKani uses discrete memory stages: “Apprentice” 1-4, “Guru” 1 &amp;amp; 2, “Master”, “Enlightened”, and “Burned”. WaniKani places a lot of weight on how often you get an item wrong before you get it right. Getting an item wrong only once, then right on the next try because you carefully reviewed and committed the mnemonic to your short term memory, only moves an item back 2 memory stages &lt;sup id=&quot;fnref:wanikani-wrong-details&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:wanikani-wrong-details&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. This means you can get an item wrong after not having seen it in over 4 months, and then next see it again over two 2 weeks later. Just getting the item right on the first re-try isn’t enough to prove that you still know the item well enough to remember it in two weeks. This can make reviews feel extra frustrating because you’re being asked to review cards that you don’t actually have a good chance of getting right.&lt;/p&gt;

&lt;p&gt;I started to dedicate less time to WaniKani, just 30-60 minutes per day instead of just over an hour. Some days I wouldn’t even finish all of my reviews, much less all of my new lessons. Consequently, I started to level up more slowly, and my accuracy started to drop. My lower accuracy further increased my workload, and I found that my accuracy on cards that I’d gotten wrong two weeks earlier stayed fairly low. Eventually I was rarely finishing all of my reviews. After traveling for two weeks, the mountain of reviews I returned to made continuing feel impossible.&lt;/p&gt;

&lt;p&gt;After a couple of months futilely trying catch back up, my accuracy rate quickly falling, I let go completely, giving up not only on finishing WaniKani, but also achieving Japanese reading and writing proficiency.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Check out &lt;a href=&quot;/0THf60NuwInF/what-makes-a-good-spaced-repetition-system-jpdbio&quot;&gt;part 2&lt;/a&gt; where I try again more intelligently.&lt;/em&gt;&lt;/p&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:ghoti-explanation&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;“gh” as in cough, “o” as in “women”, and “ti” as in “nation”. &lt;a href=&quot;#fnref:ghoti-explanation&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:wanikani-wrong-details&quot; role=&quot;doc-endnote&quot;&gt;
      &lt;p&gt;The exact formula is documented in &lt;a href=&quot;https://knowledge.wanikani.com/wanikani/srs-stages/&quot;&gt;WaniKani’s knowledge base&lt;/a&gt;. &lt;a href=&quot;#fnref:wanikani-wrong-details&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
      <pubDate>Wed, 15 Apr 2026 05:17:00 +0000</pubDate>
      <link>https://unformeddelta.wiki/v8mH7WGj5fNz/what-makes-a-good-spaced-repetition-system-wanikani</link>
      <guid isPermaLink="true">https://unformeddelta.wiki/v8mH7WGj5fNz/what-makes-a-good-spaced-repetition-system-wanikani</guid>
      
      <category>japanese</category>
      
      <category>language-learning</category>
      
      <category>recommended</category>
      
      <category>spaced-repetition</category>
      
      <category>inkhaven</category>
      
    </item>
    
  </channel>
</rss>
