<?xml version="1.0" encoding="utf-8"?> <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/"> <channel> <title>esrh.me</title> <link>https://esrh.me</link> <description><![CDATA[my blog!]]></description> <atom:link href="https://esrh.me/feed" rel="self" type="application/rss+xml" /> <lastBuildDate>Tue, 11 Feb 2025 00:00:00 UT</lastBuildDate> <item> <title>Why I love lisp, among other topics</title> <link>https://esrh.me/posts/2025-02-11-lisp.html</link> <description><![CDATA[<article> <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"> </script> <section class="header"> Posted: 2025 / 02 / 11 </section> <section> <div class="toc"> <h2 class="tocheader">Contents</h2> <ul> <li><a href="#introduction" id="toc-introduction"><span class="toc-section-number">1</span> Introduction</a> <ul> <li><a href="#some-rambling" id="toc-some-rambling"><span class="toc-section-number">1.1</span> Some rambling</a></li> </ul></li> <li><a href="#other" id="toc-other"><span class="toc-section-number">2</span> Other</a></li> </ul> </div> <h1 data-number="1" id="introduction"><span class="header-section-number">1</span> Introduction</h1> <p>So far, I’ve usually written posts here when I feel I have something atomic and at least somewhat unique to say, but this one will be a bit more personal, retrospective, meandering and kinda pointless. I’d like to talk about something that’s quite dear to my heart, lisp.</p> <p>But first of all, I’d like to update my dear readers of this website on where I’ve been! It’s been just about a year since my last post, and longer since the last redesign of the site design (if memory serves me right, we’re on the third or fourth iteration at the moment). My <a href="https://photos.esrh.me">photos</a> site is updated every so often, but I rarely take many photos unless I’m travelling – I plan to change this in the near future!</p> <p>I spent the summer 2024 taking the last classes I’d kept until the end, working on an SDR time-of-flight estimation project, playing lots of badminton with <a href="https://sidongg.github.io/">Sidong</a> (now ECE PhD at GaTech) and of course – as we did for 2 years – watching anime and yapping way too much with <a href="https://cgdct.moe/">Stephen</a> (now CS PhD at CMU). Excluding the year I spent interning at NTT, I was at Georgia Tech for 2 years. I’d rather not comment about the state of the admin, CS classes, or housing, but I really did come to like Atlanta and the people I spent my time with there. I changed considerably from 2021-2024, broadly attributable to two experiences. One was the year I lived in Japan, which gave me a bit a of a bigger picture about life and deeply influenced my sense of aesthetics; but the other was living in close proximity with <a href="https://brown.ee">Daniel</a> and Stephen – who influenced everything from my sense of humor to my thoughts on programming languages (ostensibly, the topic of this post). My friends at GT were honestly one of a kind and had such strong, bright and interesting personalities, I’m so glad I got to know them :)</p> <p>I was always vaguely amused by cool programming languages, but I started seriously programming lisp in my first year of undergrad to prove to my neovim-using friends that emacs was way cooler. I say “amused” because really I’m just interested in alternate ways of thinking about computing, since I don’t know much about PLT or compilers. I had briefly interacted with Haskell in high school, but hadn’t ever written anything in it. Daniel and I learned Haskell again together in my first year, doing the <a href="https://mightybyte.github.io/monad-challenges/">monad challenges</a> and a bunch of advent of code problems, although my main use for Haskell was for configuring Xmonad and Hakyll. Daniel was (and is) very good at functional programming, and these moments are fond memories to me. I remember particularly well getting badly stuck deriving <code class="verbatim">liftM2</code> while he cruised along ahead. I highly recommend that challenge set if you’re interested in learning Haskell. Haskell was the first time I was exposed to FP proper, and all the abstractions built up with types and higher order functions – things like functors/applicative/monads, arrows, zippers, etc. What caught my interest was the way that Haskell programmers continue making abstractions until the actual problem to be solved appears syntactically trivial – and relatedly, why the code of some Haskell projects are practically DSLs. But this post isn’t about Haskell, and I don’t think any of my friends from then had any love for lisp, but Haskell forever changed the way I wrote lisp (and all other languages too).</p> <h2 data-number="1.1" id="some-rambling"><span class="header-section-number">1.1</span> Some rambling</h2> <p>One of the many magical things about lisp is that it’s the <strong>only</strong> language that can claim to be truly multi-paradigm – because it has minimal syntax. The more syntactical rules are baked into the language (like, for instance the way Python deals with generators), the more the language guides people into a certain idiomatic way of programming. Lisp on the other hand, is only a few macro expansions away from raw abstract syntax tree. This is what makes lisp so powerful in my eyes; it can implement a huge variety of ideas elegantly. Lisps can have GC or no GC, lazy eval or strict eval, object oriented systems, imperative <a href="https://www.lispworks.com/documentation/HyperSpec/Body/m_loop.htm#loop">loop</a> facilities, <a href="https://github.com/coalton-lang/coalton">and even static types</a>. All this power, is of course due to macros, which rewrite code at compile-time.</p> <p>For instance, the commonly used <code class="verbatim">when</code> macro from many languages adds a new syntactical construct:</p> <div class="sourceCode" id="cb1"><pre class="sourceCode scheme"><code class="sourceCode scheme"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>(<span class="ex">define-macro</span><span class="fu"> </span>(when <span class="kw">cond</span> <span class="kw">exp</span> <span class="op">.</span> rest)</span> <span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a> `(<span class="kw">if</span> ,cond</span> <span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> (<span class="kw">begin</span> ,exp <span class="op">.</span> ,rest)))</span></code></pre></div> <p>Which lets you run any number of forms when a condition is true. This means you can write</p> <div class="sourceCode" id="cb2"><pre class="sourceCode scheme"><code class="sourceCode scheme"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>(when (at-war?)</span> <span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a> (<span class="kw">display</span> <span class="st">"Lauching missiles!"</span>)</span> <span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a> (<span class="kw">display</span> <span class="st">"Attack at dawn!"</span>))</span></code></pre></div> <p>instead of</p> <div class="sourceCode" id="cb3"><pre class="sourceCode scheme"><code class="sourceCode scheme"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>(<span class="kw">if</span> (at-war?)</span> <span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a> (<span class="kw">begin</span></span> <span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a> (<span class="kw">display</span> <span class="st">"Lauching missiles!"</span>)</span> <span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a> (<span class="kw">display</span> <span class="st">"Attack at dawn!"</span>)))</span></code></pre></div> <p>Since the first one gets compiled to exactly the second one. Obivously this is a trivial (but useful!) example, but macros become more complex when code is generated <em>programmatically</em> rather than just by mechanical substitution into a template. The <code class="verbatim">loop</code> macro from common lisp is a good example of another commonly used macro with a very complex implementation. In common lisp, a for loop can be written with the loop macro:</p> <div class="sourceCode" id="cb4" data-org-language="lisp"><pre class="sourceCode commonlisp"><code class="sourceCode commonlisp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>(<span class="kw">loop</span> for i from <span class="dv">0</span> to <span class="dv">10</span> <span class="kw">do</span> (<span class="kw">pprint</span> i))</span></code></pre></div> <p>The loop macro has a <a href="https://cl-cookbook.sourceforge.net/loop.html">quite intricate natural-language syntax</a>.</p> <p>Of course, macros aren’t unique to lisp by any means, but the degree of freedom and ease of definition of macros in lisp is due exactly to the homoiconicity; code is data, so manipulating code is just as easy as manipulating data! In other languages, like rust, c++, defining macros is limited, dangerous, difficult, and thus rarely done. In lisp, defining and using macros is natural. I will point out a notable exception to the “other languages” scope: Julia, which is remarkably close to the syntactic freedom one has with lisp – the lisp influence is markedly clear in many aspects of that language: metaprogramming, multiple dispatch, flexible typing, repl interactivity, etc.</p> <p>Anyway, I become involved with the <a href="https://github.com/meow-edit/meow">meow</a> project in my first year of college as well, and that marked my full immersion into elisp. My emacs config became filled with functional commands like those from <code class="verbatim">dash</code> and weird macros. This was really the point of no return for me, and I started writing much more lisp – but ran into the classic issue: you’re spoiled for choice. There are tons of different lisp dialects, some with tons of different implementations. I finally settled on <a href="https://github.com/janet-lang/janet">janet</a> for scripting needs, it was small, fast, and had a convenient standard library. But after touring clojure, emacs lisp, common lisp, and scheme, I kept feeling like I was missing some feature from some language, or preferring some naming scheme that I was used to. This sparked <a href="https://github.com/eshrh/matsurika">matsurika</a>, a fork of janet with additional functions and macros wrapped up in the binary. Essentially, every helper or abstraction I wanted to write while actually solving a problem I’d generalize as best as possible and put it into the interpreter instead of that particular script. It’s very powerful to be able to modify your interpreter as you go; and when you can do this freely knowing nobody will ever read your scripts, and nobody will ever use your fork, it leads to extremely concise and clean programs with a lot of hidden complexity.</p> <p>Some of the macros added to matsurika include:</p> <ul> <li><code class="verbatim">$</code>, which runs a shell command and returns the output – very useful to hack quickly, by using unix commands when convenient. For example, getting python files in the current directory: <code class="verbatim">(filter |(s-suffix? ".py" $) ($ ls))</code></li> <li><code class="verbatim">cli</code>, a concise way to define a main function make the args accessible</li> <li><code class="verbatim">s+</code>, a string concatenation facility with constants in scope: <code class="verbatim">(s+ qt "hello" s "world" qt nl)</code> to print <code class="verbatim">"hello world"\n</code> which</li> <li><code class="verbatim">awk</code>, which runs lisp forms on every line of a string/file that matches a PEG (CFG-like grammar) – ported from <a href="https://www.nongnu.org/txr/txr-manpage.html#N-179D63DE">TXR lisp’s awk macro</a></li> <li><code class="verbatim">->></code>, chains a sequence of computations by threading a value as the last argument of each form… <code class="verbatim">(->> 5 (+ 1) (- 5) (* 100))</code> evals to -100. However, it is sometimes convenient to change the arg order for only one computation in the chain. In my version of the threaded macro, prefixing a form with <code class="verbatim">*</code> reverses the order of the args. So, <code class="verbatim">(->> 5 (+ 1) *(- 5) (* 100))</code> evals to 100. I am a big fan of these threading macros, I used them first in Clojure, but find myself wanting them everywhere. My favorite macro library is <a href="https://github.com/rplevy/swiss-arrows">swiss-arrows</a>, which invents some new kinds of arrows with… rather odd names. I ported several of them to matsurika and use them surprisingly often. Actually, this is a good example of the contrast between a lisp-enabled “abstraction by rewriting” approach and a traditional fp “abstraction by higher order functions”. <code class="verbatim">->></code> can be easily interpreted as <code class="verbatim">foldl const</code> over a list of partial functions, or composing partial functions. This has effectively been turned into a new convenient syntactical construct with a macro. Similarly, the “Nil-shortcutting diamond wand” (??) from swiss-arrows, which ends the chain early if any intermediate value is nil, is equivalent to chaining <code class="verbatim">Maybe</code> computations with <code class="verbatim">>>=</code> in Haskell.</li> </ul> <p>I’ve written a number of scripts that use reasonably often in janet/matsurika, and in general it’s been fun. However, I don’t think that choosing janet was the right choice in retrospect. This is for a number of reasons. First, janet (and by extension, clojure) is already too opinionated, and is not a good base to mold to your tastes. I like some of those opinions (for instance, the PEGs, the table syntax) but don’t like some others. Second, the maintainance cost of having to hack on the janet source code, combined with the fact that since its forked i will need to periodically rebase to get the latest changes (with manual merge conflicts), turned out to be nontrivial. Finally, needing your own deranged binary to run your scripts is a bit awkward. One of Janet’s biggest differentiators, and indeed a project goal is that it’s small, written in C, has no dependencies, and is embeddable. My goals include only “small.” Everything new in matsurika could easily have implemented as a library providing new macros and functions. In the near future, I plan to implement this for either r5rs scheme or racket. Racket seems particularly appealing, since it has explicit support for other lisp dialects using the <code class="verbatim">#lang</code> keyword. I do enjoy clojure as a language, but for mostly superficial reasons: it tends to encourage a stateless pure FP style, and the standard library is pretty good (batteries included). However, I’m not a huge fan of some of the modern clojureisms like the square brackets; one might argue that clojure is not a lisp at all because the code is not linked lists and there are no cons cells; one of the minimal specifications for a lisp according to the <a href="https://www-formal.stanford.edu/jmc/recursive.pdf">original paper</a> by John McCarthy.</p> <h1 data-number="2" id="other"><span class="header-section-number">2</span> Other</h1> <p>I graduated college in August 2024 – and I’m now doing my Masters at the Institute of Science Tokyo (formerly Tokyo Tech). I love it here! I’m working on using using diffusion models with wireless data at <a href="https://nishio-laboratory.github.io/">Nlab</a>. I’m living a lot slower than I did the last time I was here; there’s not much local tourism left to do, and it feels normal rather than magical as it once did. I bike a lot around the city, and it’s become one of my favorite hobbies.</p> <p>I’ve been using emacs for a long time now, but lately I’ve been keeping my on <a href="https://github.com/lem-project/lem">lem</a>; I think it’s a matter of time before I switch (probably after I port the core of meow to CL). I no longer believe as strongly as I once did in the future of emacs, but I do still feel that my current keybinding scheme on meow’s editing model is really close to optimal for me. I’m sure that emacs and its religious users will continue to hack away underground long after the nukes fall and wipe out surface life, but there are fundamental flaws that need to be fixed:</p> <ul> <li>emacs-lisp is really not that good</li> <li>decades of cruft has led to bad performance <ul> <li><a href="https://200ok.ch/posts/2020-09-29_comprehensive_guide_on_handling_long_lines_in_emacs.html">the epic long lines problem</a></li> <li>single-threaded</li> <li>the epic GC hanging problem</li> <li>relatively slow start up time</li> </ul></li> </ul> <p>With a project of emacs age and popularity obviously there have been a number of attempts to hack it: GNU Emacs is itself a reimplementation for one (1984), Lucid emacs (late 80s), <a href="https://github.com/emacs-ng/emacs-ng">emacs-ng</a>, <a href="https://github.com/remacs/remacs">remacs</a>, <a href="https://github.com/commercial-emacs/commercial-emacs">commercial-emacs</a>, etc that I’m probably forgetting. I like lem mainly because it makes the step of finally ditching emacs lisp for common lisp. It’s much better suited for developing editor packages, and cl compilers are more performant. I think of lem to emacs as perhaps neovim to vim; a tight, modern reimplementation that doesn’t forget the culture and soul of the original project.</p> <p>No matter how much I wax about lisp, I write mainly python on a day to day basis. That’s why the “soul” (as I like to call it) of the language/ecosystem and the experience of writing in lisp is so important to me; it’s my reprieve. I’ve wasted more time than most readers could possibly imagine trying to convince people that lisp is the best programming language ever (true), literally goated (also true), <a href="https://youtu.be/HM1Zb3xmvMc">alien tech</a> from the future (so timeless!), divinely inspired (it’s said God came to JMC in his sleep) etc but it really doesn’t matter. What matters is that writing lisp is truly fun! It’s a joy to iterate and organically build up a solution, testing as you go in the repl, precisely manipulating the code with sophisticated tools (structural editing! paredit!). Lisp dialect tooling (especially CL, Schemes, Clojure) is blissful to use – the very first language servers were for lisps! The monkey-wrench move-fast-break-things attitude encouraged by dynamically typed lisp combined with the patterns of interactivity, self-documentation, and hot-swappability is to me, at the very core of hacker culture. If you spend enough time with lisp, the parentheses fade out with the stars and you’re left to admire the raw, pulsating heart of computation.</p> <p>As Stallman puts it:</p> <blockquote> <p>The most powerful programming language is Lisp. If you don’t know Lisp (or its variant, Scheme), you don’t know what it means for a programming language to be powerful and elegant. Once you learn Lisp, you will see what is lacking in most other languages.</p> </blockquote> <p><code class="verbatim">Y F = F (Y F)</code></p> </section> </article> ]]></description> <pubDate>Tue, 11 Feb 2025 00:00:00 UT</pubDate> <guid>https://esrh.me/posts/2025-02-11-lisp.html</guid> <dc:creator>Eshan Ramesh</dc:creator> </item> <item> <title>spectral blessing (a short story)</title> <link>https://esrh.me/posts/2024-02-25-spectral-blessing.html</link> <description><![CDATA[<article> <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"> </script> <section class="header"> Posted: 2024 / 02 / 25 </section> <section> <div class="toc"> </div> <p>For Sa-yi, the time has nearly come. Most of children she grows up with all live for the ceremony she will soon take part in. Most children pick a trade, a kind of specialization. Some work on the autofarms, some learn to decode the messages from the elders, and some make handicrafts and tools. Some children, of course, decide that the work isn’t worth the effort, and instead engage themselves with trivial matters, like competing to see who can climb the highest up the holy tower (a common demonstration of masculinity), or playing card games for extra snacks.</p> <p>Sa-yi learns the scripture. She always has, for as long as she can remember. There are no adults in their cocoon, not since they all turned 8 (at which time there is another ceremony, the <em>i/Ha</em>, celebrating the sacred nature of the number). To her, the scripture is everything. Seemingly, the more she reads the more there is to read; the more questions are answered the more questions reveal themselves. But this doesn’t bother her; it excites her. Her trade is to read, and she is the best at what she does.</p> <p>The <em>i/Yi-ro</em> is what one might call a coming of age ritual, underwent at twice the age of the <em>i/Ha</em>. The hatch in the center of the cocoon is opened for a child to descend into, and they are never seen again. The scriptures (the easiest of them, the <em>Yajur</em>) tell the children that they will receive their true name during the ceremony, and the children have no choice but to believe them. They don’t know what their true name would mean, or even what it might sound like, but they all feel a certain weight and importance attached to it. They’re only told it’s a judging, where the bad children will be punished for their misbehavior with a disgraceful name and and the good children will be rewarded for their effort with a beautiful name. It goes a long way towards keeping them in line, but it’s hardly necessary. Nobody really misbehaves in the cocoon, and there is no serious conflict. All the children are familiar with the invisible force on their heads that presents itself when they begin to disobey the scripture.</p> <p>Today it is Sa-yi’s turn. She tries her best to suppress her shaking hands as she climbs down a set of stairs – irreverent oscillation is frowned upon by the Third Book of the <em>Rig</em>. The stairs soon give way to a gently sloping spiral slope that leads her deeper underground. At the bottom she finds a finely woven mesh door made of the same metallic material as the walkway. She pushes opens the door and steps inside. It is warmer here, and dark. Before she can take another step, a light finds her and she lays eyes on three vague, shadowy silhouettes.</p> <p>The central figure speaks: “We will now begin with the 31st <em>i/Yi-ro</em> of this epoch. Sa-yi, step forward. Speak only when asked.”</p> <p>She does as she is told, stepping forward onto a circular platform, feeling a slight but definite pressure as she does so. It’s not all so different from what the children feel every night as they go to sleep. It’s stronger, and much clearer.</p> <p>“State your identity” the figure booms. Sa-yi begins almost immediately:</p> <p>“My false name is Sa-yi, cocoon <code class="verbatim">DF0</code>, batch <code class="verbatim">AA1</code>, group <code class="verbatim">DC3</code>. I am an Interpreter with guild 71. Confirm?”</p> <p>As she utters the last phrase, she stretches her arm out in front of her, palm facing forward. On it, an intricate tattoo of swirling lines and intertwining curves – her eigenkey – glows hot for a brief moment. Even the youngest among them knew the proper etiquette.</p> <p>“Accepted.” they reply, in unison yet such that one can match each voice with its owner effortlessly. They are in perfect harmony.</p> <p>“The truth of the <em>i/Yi-ro</em> is not as you have been told it is, Sa-yi. We do not judge here. There is no need to judge you. We have been judging you for a long time now, and we are nearly finished. The purpose of this event is for you to listen, rather than to speak.”</p> <p>Sa-yi begins to feel the pressure on her head grow, and grow until it becomes unbearable and piercing and all-consuming and resonant with her skull. And finally, for the first time, she begins to see.</p> <p>Colors rush forth, the normal colors included, but more colors too. Colors that one cannot see but with the mind’s eye. There is no end to the color, each more fresh than the last, and each unlocking a new visual perspective, in the same way a blind child is awakened to the world of art – and in that instant she realizes she has been blind all her life.</p> <p>What Sa-yi sees, I cannot tell you – it is inexpressible in our languages. It is inexpressible not like 1 = 2 (which is illogical but expressible), but like that which cannot be pictured by in our minds. All I can give is a projection, like a lower dimensional slice of a deeper world. This is what she sees:</p> <div class="line-block">the universe begins. nothing. a planet passes by a star.<br /> its orbit is very long.<br /> lifeforms are born, lifeforms die.<br /> the planet passes again.<br /> nothing happens exactly once. if one were to live long enough, one would see it happen again.<br /> when something happens again it has a frequency.<br /> it need not have a form of course, the form is predetermined because there is only one form<br /> the wave, of course.<br /> the waveform.<br /> <br /> a lake surrounded by mountains.<br /> it was formed once, it will be destroyed, and it will be formed again,<br /> all in tune with the universal frequency, the uberfrequency, as all is.<br /> a stone, the perfect stone is thrown, and the water ripples,<br /> a smooth wave, the perfect wave, propagates from the source (the transmitter).<br /> it is perfectly clear, and perfectly smooth, it is the waveform in shape,<br /> yet nothing but a harmonic of the uberwave.<br /> a pure shape, with a seductive symmetry, an innocence in each gentle curve that<br /> entrances the eye like the pendulum of an intricate grandfather clock.<br /> <br /> the mountains fade smoothly into nothingness and the water stretches<br /> as far as the eye can see.<br /> infinitely many waves from infinitely many imperfect stones hit the water<br /> and the ripples touch each other like tendrils of effect intermingling and intertwining –<br /> and they combine in tune and out of tune into a new wave<br /> one that has not yet been seen before in this universe<br /> but surely will be in another.<br /> in this instant there are enough waves to name a wave for every string in every language,<br /> and in the next instant there are more.<br /> <br /> something is lost when these waves are made,<br /> for they are impure,<br /> and they are hideously imperfect compared to the harmonics of the uberwave.<br /> the intrinsic natures of the component waves yearn to be free,<br /> because nature is smooth and free.<br /> the sudden and sharp are unnatural and binding.<br /> nature is smooth.<br /> nature is smooth but sometimes bent out of shape by the free energies of the universe<br /> but its heart always makes itself known:<br /> ringing artifacts in the fabric of spacetime,<br /> harmonics,<br /> nature screaming out as its spinal cord is shattered into<br /> the gray-coded constellations of the night sky.<br /> <br /> and finally she sees that she is made of water, defined by one great wavefunction,<br /> carefully constructed, with not one error,<br /> by a mechanical monstrosity that throws stones into the lake.<br /> the machine is not of this world; it is of the world above.<br /> it stretches across the sky, but the world is not cast in darkness.<br /> gears and pulleys mash and spin silently.<br /> you would know god too if you saw it.<br /> the machine simulates the world with its energy,<br /> warping and weaving the simple into the complex.<br /> <br /> it is impossible to discern its objective.<br /> it may have none at all but to sculpt its pond to match its algorithmic sense of beauty,<br /> an artistry of symmetry and simplicity and oscillatory aesthetics.<br /> the machine, oscillating at the uberfrequency, must be tormented;<br /> the waves seem to splash and wriggle incessantly.<br /> we can only imagine how awful the harmonics of the sculptures it forms must appear to it –<br /> but we see a beauty in the unintentional imperfections, for the only<br /> complexity our imperfect selves can understand as beautiful is<br /> exactly that which is resonant with our perfect components.<br /> <br /> and finally she sees that<br /> she is always propagating further away from the center of the machine<br /> her one and only birthplace.<br /> everything she has done and will do is merely<br /> a consequence of a perfect component,<br /> some with a period of days,<br /> some longer than she will live and be reborn and die again.<br /> the anxiety of autoscopy is instantly replaced by an overwhelming sense of peace,<br /> knowing that one is<br /> nothing if not predetermined,<br /> nothing if not a drop in the river to heaven.</div> <p>And her world goes black, pure black. She struggles to open her eyes only to realize they were already open as she regains feeling in her limbs. Her proto-vision will not return to her for several days. She feels as if she’s lost something; whatever it was, she knows it must have been unimportant. But she has gained something far more important.</p> <p>The three figures speak again, but she doesn’t hear them; she sees: three blobs of pattern in three complimentary colors that she finds immensely pleasing together, as if they’ve been chosen from a higher-dimensional color wheel.</p> <p>She knows, somehow, her true name: Na-ha-ze, after the current epoch, 780. She knows that this ceremony had been performed millions of times before. She knows everything about her new purpose, and the world she was born into. She is perfectly aware that most children were not given the Spectral Blessing; after all, how could they handle such a thing? Most were handed down some common name and sent on their way. A few were disposed of. Na-ha-ze feels this is all as it should be, and what she feels as the new Prima-Intendant is fact.</p> <p>Somewhere above her, she senses a gate opening, and her field of vision is washed away by the most beautiful colors she has never seen.</p> <p>—</p> <div class="notes"> <ul> <li>thanks to <a href="https://cgdct.moe">stephen</a> and my friends for reading early drafts</li> <li>inexpressibility of what gives logic to the world (and is outside the world) is an idea from <a href="https://www.kfs.org/jonathan/witt/t641en.html">tractatus (6.41)</a></li> <li>the world being <a href="https://people.idsia.ch/~juergen/computeruniverse.html">simulated</a> by a machine that prioritizes speed, simplicity, and algorithmic <a href="https://people.idsia.ch/~juergen/beauty.html">beauty</a> is inspired by <a href="https://people.idsia.ch/~juergen/">schmidhuber</a></li> <li>many allusions are made to a <a href="https://en.wikipedia.org/wiki/Fourier_analysis">fundamental idea</a> about the decomposition of functions in math and signal processing</li> </ul> </div> </section> </article> ]]></description> <pubDate>Sun, 25 Feb 2024 00:00:00 UT</pubDate> <guid>https://esrh.me/posts/2024-02-25-spectral-blessing.html</guid> <dc:creator>Eshan Ramesh</dc:creator> </item> <item> <title>Meow response to a critique of kakoune-style editing</title> <link>https://esrh.me/posts/2024-01-29-meow-response.html</link> <description><![CDATA[<article> <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"> </script> <section class="header"> Posted: 2024 / 01 / 29 </section> <section> <div class="toc"> <h3 class="tocheader">Contents</h3> <ul> <li><a href="#introduction" id="toc-introduction"><span class="toc-section-number">1</span> Introduction</a></li> <li><a href="#critique-points" id="toc-critique-points"><span class="toc-section-number">2</span> Critique points</a> <ul> <li><a href="#reverse-grammar-hurts-key-reuse" id="toc-reverse-grammar-hurts-key-reuse"><span class="toc-section-number">2.1</span> Reverse grammar hurts key reuse</a></li> <li><a href="#navigation-vs-selection" id="toc-navigation-vs-selection"><span class="toc-section-number">2.2</span> Navigation vs Selection</a></li> <li><a href="#visual-selections-dont-prevent-mistakes-overlays-do" id="toc-visual-selections-dont-prevent-mistakes-overlays-do"><span class="toc-section-number">2.3</span> Visual selections don’t prevent mistakes; overlays do</a></li> <li><a href="#visual-confirmation-is-unnecessary" id="toc-visual-confirmation-is-unnecessary"><span class="toc-section-number">2.4</span> Visual confirmation is unnecessary</a></li> <li><a href="#evil-integration-is-better" id="toc-evil-integration-is-better"><span class="toc-section-number">2.5</span> Evil integration is better</a></li> </ul></li> <li><a href="#ending-thoughts" id="toc-ending-thoughts"><span class="toc-section-number">3</span> Ending thoughts</a></li> </ul> </div> <h2 data-number="1" id="introduction"><span class="header-section-number">1</span> Introduction</h2> <p>A few days ago, my <a href="./2021-12-18-switching-to-meow.html">article</a> was <a href="https://lobste.rs/s/lb2eld/switching_meow_modal_editing_system_from">posted</a> to lobste.rs and it got a <a href="https://lobste.rs/s/lb2eld/switching_meow_modal_editing_system_from#c_dfs8sq">comment</a> from Celeritas linking me to <a href="https://github.com/noctuid/dotfiles/blob/master/emacs/editing.org#why-not-kakoune">this</a> argument in favor of vim-style editing rather than kakoune-style editing. I was typing up a response in the thread, but it ended up getting pretty long, so I decided to turn it into a sort of follow-up post.</p> <p>That article is written by noctuid, a pretty prolific emacs community member (i remember reading their evil guide when I first started using doom something like 6 years ago now). I’ve never used kakoune, but even though I ultimately disagree with their take I can relate to many parts of it. Meow fixes many of the issues they mention with kakoune. I think that with editor discussions in general there’s an exceptional amount of subjective bias because of the cost it takes to learn new things. I’ll be biased because I sunk the cost to learn kakoune grammar, and that’s what I currently use. I don’t think there are many people who’ve switched the other way.</p> <p>In this post I’d like to comment on some of the critiques noctuid makes about kakoune, especially with regards to navigation and selection and how meow seems to address many of their points. In some sense, this is a bit more of a sobered take compared to my post 2 years ago. It comes with a bit more experience and knowledge of how meow works internally.</p> <h2 data-number="2" id="critique-points"><span class="header-section-number">2</span> Critique points</h2> <h3 data-number="2.1" id="reverse-grammar-hurts-key-reuse"><span class="header-section-number">2.1</span> Reverse grammar hurts key reuse</h3> <p>The idea is that operator-pending mode is a separate context in which keys can be re-used, like how <code class="verbatim">w</code> means “word” after <code class="verbatim">d</code> but “next word” in general. Noctuid takes issue with having to use a modifier to select text objects.</p> <p>I think it’s really just a layout issue – indeed in meow we use <code class="verbatim">,</code> and <code class="verbatim">.</code> on the recommended layout. When you’re selecting a text object, that <strong>is</strong> a separate context in which keys are interpreted differently. You can reuse every key to select a text object. I might be misunderstanding what was meant by this part, but as I see it you’re losing nothing.</p> <h3 data-number="2.2" id="navigation-vs-selection"><span class="header-section-number">2.2</span> Navigation vs Selection</h3> <p>When I first started using meow, I might have agreed that automatic selections were a bit distracting, but once you start ignoring them it really becomes a non-issue. In meow, any movement key or command that does not act on a selection cancels the active selection, meaning that if you make a motion without wanting to act on it the selection will probably disappear on your very next command. However, it probably is a very valid observation that most people will very rarely make a motion and THEN realize they want to act on it. I just think that there is a real benefit to automatic selections, and it’s worth it for the cases where you select intending to act.</p> <h3 data-number="2.3" id="visual-selections-dont-prevent-mistakes-overlays-do"><span class="header-section-number">2.3</span> Visual selections don’t prevent mistakes; overlays do</h3> <p>Noctuid correctly points out that visual selections don’t really prevent you from <em>making</em> mistakes, they only make it obvious and easy to fix when you <em>do</em>.</p> <p>Luckily meow has visual selections <strong>and</strong> overlays. Meow implements nearly exactly what noctuid describes, but with great integration (compared to avy) and really smooth ergonomics for the vast majority of everyday editing use cases. In short, most movement commands in meow trigger overlays over the target locations of all possible repetitions of that command, letting you quickly and visually repeat a command some number of times.</p> <p>I don’t agree that visual selections don’t prevent mistakes – I couldn’t tell you how many times I’ve fat fingered 8 instead of 7 or simply changed my mind after making a selection. Additionally, having both gives you two options: either press the right number by reading the hints, or spam. Some commands in meow reuse keys for their expand versions. For instance, if you select a line with <code class="verbatim">meow-line</code> (<code class="verbatim">x</code>), pressing the same key again selects one more line. If you mark a whole word with <code class="verbatim">meow-mark-word</code> (<code class="verbatim">w</code>), pressing <code class="verbatim">meow-next-word</code> (<code class="verbatim">e</code>) expands by one word instead of selecting the next word only.</p> <p>A subtle point which even many long time users of meow might not know the specifics of is this expandable selections. Every time you make a selection in meow, it is marked with some information that informs meow what to do on a repeat: whether it is an “expand” selection or a “select” selection, and what object the selection is targeting. The commands that make an “expand” selections are</p> <ul> <li>up/down/right/left expansions</li> <li>word/symbol based expansions</li> <li>line expansions</li> <li>block expansions (paren/bracket pairs, <code class="verbatim">meow-block</code> expands</li> </ul> <p>up the tree).</p> <p>The commands that make “select” selections and therefore do not reuse keys are</p> <ul> <li>find/till character</li> <li>general text-objects (perhaps might change in the future, there’s a lot of discussion about this on github)</li> <li>meow-visit</li> </ul> <p>This whole setup makes expanding selections much easier, and basically gives you same user experience as highlighting text with a mouse: choosing your selection one object at a time. In my experience, I tend to spam keys to select <5 text objects, it’s just faster and takes less thought. In this “spam” selection mode, visual selection indeed does prevent selection errors, it’s slower and less efficient but exact.</p> <h3 data-number="2.4" id="visual-confirmation-is-unnecessary"><span class="header-section-number">2.4</span> Visual confirmation is unnecessary</h3> <p>From the article:</p> <blockquote> <p>Furthermore, the effect of many motions and text objects is obvious; visual confirmation is often completely unnecessary. Deleting the current word, sentence, or parentheses block does not involve uncertainty. t and f are basically the “dumbest” motions in that they don’t move by clear units like paragraphs or words but instead jump to arbitrary characters. The majority of my operator usage has no possibility for mistakes apart from mistyping.It doesn’t make sense to me to optimize a modal model around rarer cases like the dtf example, even if I thought a visual selection was the ideal way to handle these cases.</p> </blockquote> <p>I mostly agree with this point. A lot of my editing tasks are just “delete this word” or “change inside parens” which are so fast I barely see the selection before it’s gone. In this case though, visual selections cost nothing. So, I don’t agree with is the tradeoff part of their argument. It <strong>does</strong> make sense to optimize modal models around error prone cases, especially when there is minimal (and to me, mostly aesthetic) cost for doing so. I don’t think these cases are that rare; jumping to the <code class="verbatim">n</code> th occurrence of a character or selecting <code class="verbatim">n</code> lines is quite common!</p> <h3 data-number="2.5" id="evil-integration-is-better"><span class="header-section-number">2.5</span> Evil integration is better</h3> <p>In the “why not other emacs packages?” section, noctuid mentions that emacs packages use different keybindings for different actions, and that modal editing packages face a fundamental convention difference for motion keys (jk vs C-n, C-p). This is a good point to mention meow’s “motion” state, meant to address exactly this.</p> <p>Essentially, it lets you override your motion keys in <em>every</em> mode that steals them from you <em>automatically</em>. Evil expects you to remap your keys in every one of your modes. Meow decides which modes to use motion in using a <a href="https://github.com/meow-edit/meow/blob/3247b9d4f2b46bcf8d216857a59d67dd416dcdb9/meow-helpers.el#L237-L261">funny little heuristic</a> that checks whether keys self-insert into the buffer and recursively against a predefined list of parent modes. Any command that’s hidden is rebound under the <code class="verbatim">Hyper</code> modifier, So, if you need to use the command that used to be bound to your motion keys, you can bind <code class="verbatim">H-<key></code> under your leader prefix. It’s a dead simple idea, and it’ll always work.</p> <p>While motion works for interaction-style packages like elfeed and magit, unfortunately, this is ultimately a valid criticism. Meow is forced to adapt to packages that nontrivially change your <em>editing</em> experience itself, like company, polymode, sly and cider to name a few. For these, meow comes with some “shims” that mostly just turn on the motion mode when its needed. Inevitably, this leads to bad user experience with some missed packages – but luckily, most compatibility issues are trivially solved by just turning on motion mode when it’s necessary, and indeed most shims that meow has do just that.</p> <h2 data-number="3" id="ending-thoughts"><span class="header-section-number">3</span> Ending thoughts</h2> <p>Noctuid’s post is 6 years old, and my response is obviously unfair since they’re writing about kakoune, and I’m talking about a modern package that has had the chance to learn from the many modal editing packages. Still, many of the critiques are about kakoune’s model itself, which meow uses. I still think it’s a good idea, or at least surely not a “a broken solution to a non-issue.” The instantaneous feedback and visual selections cost is mostly aesthetic, with a benefit of making selection errors trivial to notice and fix before acting on them.</p> <p>At the end of the day, people edit differently – editors should be molded to the desires of the users, not the other way around.</p> </section> </article> ]]></description> <pubDate>Mon, 29 Jan 2024 00:00:00 UT</pubDate> <guid>https://esrh.me/posts/2024-01-29-meow-response.html</guid> <dc:creator>Eshan Ramesh</dc:creator> </item> </channel> </rss>