• The last few weeks have been a small education in rejection.

    I sent the manuscript to publishers. The replies came back — polite, professional, no. Then again. Then again.

    My first instinct was to look inward, which felt like the responsible thing to do. If they’re saying no, something must be wrong with the book. So I revised. I tightened chapters, rewrote a derivation I’d never been happy with, went through the figures again. Each pass made the manuscript a little better.

    But somewhere around the third round, I had to admit something: no amount of polishing was going to reverse those decisions. The gap between “good draft” and “yes” wasn’t a gap of quality. It was something else.

    The something else

    Publishing draws a line between two kinds of books: the trade book — something a curious reader picks up in a bookstore — and the textbook, which lives in classrooms and has adoption cycles and a syllabus around it.

    I’d been pitching mine as a trade book. Twelve chapters of derivations, exercises, from-scratch implementations. A book that assumes you’ll work through it rather than read it on a train.

    That’s not a trade book. That was never a trade book. I’d been walking into the wrong department and wondering why nobody wanted what I had.

    It’s a strange kind of relief, discovering that the problem is a category error. The manuscript wasn’t failing. It was in the wrong queue.

    Putting it down

    So I repositioned it as a textbook, made the revisions that framing called for, and then — the harder part — stopped.

    There’s always one more pass available. Another derivation to smooth, another figure to redo. At some point continuing to revise stops being craftsmanship and starts being avoidance, and I think I got close enough to that line to see it. The draft is good. Not perfect; good. I put it down.

    It’s now with publishers who actually work in textbooks, and I’m back to waiting — but this time waiting on the right people.

    What I’ve been doing instead

    Not writing, mostly. Which turns out to be its own kind of progress.

    I’ve started a new research topic — the first genuinely new thing in a while — and drafted a paper around it. And in the way these things go, working on that paper sent me back into texspark’s source: new usage patterns, new small frictions, new fixes. The tool improves when I use it for something I haven’t used it for before.

    The book is where it is. Somebody will read it eventually, or they won’t, and either way it exists now, which was never guaranteed. Meanwhile there’s a paper to write, and an editor to improve, and — as always — one more thing to fix before I can get back to writing.


  • My referrer list is short enough that I read it like a diary. Google, Twitter, a few direct visits. Last week a new entry appeared: chatgpt.com. One visitor.

    Somebody asked ChatGPT something — probably about LaTeX editors on macOS — and ChatGPT mentioned texspark, and that person clicked. I have no idea who they were or what they asked. But I know how they got here, and the path is worth writing down.

    The chain, visible in my logs

    Because this site is small, I can see the whole sequence rather than infer it. Three entries, weeks apart:

    • Early JulyOAI-SearchBot shows up in my download log. OpenAI’s search crawler, indexing the site.
    • Mid JulyGPTBot follows. The one that reads pages so ChatGPT can talk about them.
    • Early August — a human arrives with chatgpt.com as their referrer.

    Crawl, index, recommend, click. The same loop search engines have run for twenty-five years, except the last step now happens inside a conversation instead of on a results page.

    Why this is stranger than it sounds

    Here’s the part that made me stop: texspark ranks terribly on Google. Average position across all my search terms is somewhere around 35 — page four, where nobody goes. I’ve been patiently waiting months for that number to improve, because that’s how this is supposed to work: you write, you rank, eventually you get clicks.

    But ChatGPT doesn’t rank pages. It reads them and decides which one actually answers the question. Domain authority, backlink count, how old your domain is — the machinery that keeps a new site buried on page four — matters much less. What seems to matter is whether your pages state clearly and specifically what your thing is and isn’t.

    Which means the pages I wrote for humans — the honest comparisons, the “here’s what Texmaker does better” sections, the documentation with actual keyboard shortcuts in it — may be doing their most useful work in a channel I wasn’t even aiming at.

    One visitor is not a trend

    Let me be clear about the sample size: it’s one. One person, one click, no evidence they downloaded anything. I’m not about to reorganize my writing around “LLM optimization,” which sounds like a phrase that will age badly and probably already has a conference track.

    But it does suggest something worth noticing. For a small, new site with no backlinks and no authority, AI search may be a faster path to being found than climbing Google’s rankings. Not because you gamed anything — just because a model reading your page has no reason to care that your domain is four months old.

    The advice, if there is any, is unglamorous: write pages that are specific and true. Say what your software does, what it doesn’t, and who it isn’t for. That’s been good advice for humans forever. It now appears to also be good advice for the machines quoting you to humans.

    Anyway — hello, whoever you were. You’re in a chart now.


  • Today I sent the full manuscript of Machine Learning from Scratch — all twelve chapters — to an editor, along with the proposal. First complete draft, out the door.

    It’s a strange feeling. For months the book was entirely mine: my pace, my decisions, my endlessly rearranged outline. I could open any chapter at 2 a.m. and change a derivation on a whim. Now a complete draft sits in someone else’s inbox, and for the first time the next move isn’t mine to make.

    The writing happened faster than I expected once the editor I was building — texspark — got out of my way. Twelve chapters of equations, figures, and derivations, typeset in LaTeX, written in an app that grew up alongside the manuscript. At some point the tool stopped being the project and became just the thing I wrote in, which was always the goal.

    There’s a lot still ahead: an editor’s read, revisions, the whole publishing pipeline that turns a folder of .tex files into something with a spine. But a first complete draft is a real threshold, and it’s crossed.

    For now, the book is out of my hands. Back to refreshing my email.


  • When you tell people you’re writing a machine learning book, they assume a stack: Jupyter notebooks, Markdown, maybe a static-site generator, everything on GitHub, code and prose interleaved. That’s how ML content is made now. It’s a good stack. I’m not using it.

    I’m writing the whole thing in LaTeX — every chapter, every figure, every equation. In 2026, for a machine learning book, this is a slightly eccentric choice, and people ask why. Here’s the honest answer.

    The math has to be beautiful, because the math is the point

    The book is called Machine Learning from Scratch. The entire premise is deriving things — backpropagation by hand, gradients written out term by term, the chain rule crawling across half a page. This is not a book where equations are decoration you could screenshot from a paper. The equations are the content.

    Nothing typesets math like LaTeX. Not “renders it acceptably” — typesets it, with the spacing and alignment and typographic care that makes a three-line derivation readable instead of intimidating. Markdown with a math plugin gets you 80% there and then abandons you exactly where it matters: the aligned multi-line derivation, the numbered equation you reference twelve pages later, the matrix that has to line up. For a book that lives or dies on whether a reader can follow the math, 80% is a failing grade.

    A book is not a website

    Notebooks and Markdown optimize for the web: scrollable, linkable, runnable. Wonderful properties — for a tutorial. But I’m writing a book, and a book is a designed physical object even when it’s a PDF. Page breaks that don’t strand a heading. Figures that sit where the eye expects them. A table of contents, an index, cross-references that know their own page numbers. Consistent typography across three hundred pages.

    LaTeX was built for exactly this — it’s a typesetting system that happens to accept text input, not a text format that happens to produce output. Every serious textbook you learned from was probably set in TeX. There’s a reason the convention held.

    Plain text ages well

    My manuscript is a folder of .tex files. I can grep it, diff it, version it in Git, back it up anywhere, and open it in any editor on any machine for the next forty years. No proprietary format, no cloud account that might sunset, no notebook JSON that turns into a merge-conflict nightmare the moment two edits touch the same cell. When you’re committing to a multi-year project, “will I be able to open this in 2040” is not a paranoid question. LaTeX’s answer is yes, trivially.

    The honest catch

    I won’t pretend it’s free. LaTeX has a real learning curve, the error messages read like threats, and the edit-compile-look loop is slower than a live-rendering Markdown preview. For a quick tutorial or a runnable notebook, the modern stack genuinely wins — I’d use it without hesitation.

    But for a math-dense book meant to last, the tradeoffs run the other way, and the friction is worth paying down rather than avoiding. Which — full disclosure — is the thread that connects the two things I spend my time on: the book pushed me to sharpen the editor I write it in, and the editor is the reason the friction is bearable. The manuscript and the tool grew up together. Neither would exist in its current form without the other.

    So: LaTeX, in 2026, for a machine learning book. Eccentric, maybe. But every time a derivation lands clean on the page — spacing right, alignment perfect, reference resolved — I remember exactly why.


  • You wrote \begin{figure}[h]. You meant it. Here, you said. Put the figure here, where I have placed it, next to the sentence that refers to it, like a reasonable person arranging a reasonable document.

    LaTeX read your [h], considered it, and put the figure on the next page. Alone. Centered in an ocean of white space. Three paragraphs away from the text that mentions it.

    Welcome to floats. Everyone who has written a thesis has stood exactly where you are standing.

    The bargaining begins

    The escalation is always the same, and every LaTeX user has climbed its rungs in order:

    • [h] — “here.” A polite request. Ignored roughly half the time.
    • [h!] — “here, and I mean it.” The ! tells LaTeX to drop its rules about how much of a page a float may occupy. Stronger. Still a suggestion.
    • [ht] — “here, or top, I’m flexible.” You have started negotiating.
    • [htbp] — “here, top, bottom, or a whole page — anywhere, please, I’m begging you.” The full surrender. You are no longer specifying placement; you are listing every place you would accept.
    • \usepackage{float} then [H] — the nuclear option. Capital H means “HERE. Not a float anymore. Nail it to this exact spot and let the consequences fall where they may.”

    By the time you reach [H] you have stopped writing a paper and started fighting a typesetting engine at 1 a.m. And [H] usually “works,” which is exactly why it’s dangerous — it wins the battle and quietly wrecks the layout, leaving half-empty pages behind it like a toddler who insisted on carrying the plates.

    Why LaTeX does this to you

    Here is the part that turns the rage into grudging respect: LaTeX is not being difficult. It’s being principled.

    A float is called a float because it is designed to move. The whole point is that figures and tables should never leave an ugly gap at the bottom of a page, never get split across a page break, never strand two lines of a paragraph alone. When you write [h], you’re asking LaTeX to honor your placement and its typographic conscience at the same time — and when those conflict, it sides with the conscience. It would rather move your figure than let your document look bad by the standards of professional book typesetting.

    Word would have just jammed the image where you dropped it and let the text flow into a mess around it. LaTeX refuses. It’s the difference between a tool that does what you say and a tool that does what you meant — and the gap between those two is where all the swearing lives.

    The actual advice

    After enough theses, you stop fighting and learn the moves that actually help:

    • Use [tbp] as your default and let figures live at the top of a page. Papers look better this way than with figures wedged mid-paragraph, and once you accept it, the fighting stops.
    • Reserve [H] for the rare figure that genuinely must sit at one spot — a step in a sequence, a figure inside a boxed example. Not for every plot.
    • Reach for \clearpage before a section if floats are piling up and drifting into the wrong part of the document.
    • Trust the reference, not the position. That’s what \ref{fig:...} is for — the reader follows “Figure 3” to wherever Figure 3 landed. They do not need it glued to the sentence. Only you do, and only because you can see the source.

    The one thing that actually helps at 1 a.m.

    Most float rage comes from a slow feedback loop: change [h] to [htbp], recompile, hunt through the PDF for where the figure went this time, repeat. The faster you can see the result, the less it feels like a fight and the more it feels like nudging.

    Which is, honestly, half of why I built texspark: hit ⌘B, watch the PDF update beside the source, and forward-search to the figure to see exactly where it settled — without losing your place. Floats will still float. But you can watch them do it, and course-correct in seconds instead of minutes. It doesn’t make LaTeX obey you. Nothing does. It just makes the negotiation faster.

    The figure is on the next page again. It’s fine. Write \ref{} and let it go.


  • Abstract comparisons are easy to write and easy to ignore. So let’s make it concrete.

    The setup: a book project. main.tex at the root, ten chapters under chapters/, each pulled in with \include. You’re deep in chapters/04-optimization.tex when you want to (a) build, (b) find your place in the structure, and (c) move between source and PDF in both directions. Bread-and-butter thesis work.

    I used Texmaker for over ten years — dissertation, papers, lectures — so what follows is not guesswork about a rival. It’s muscle memory, written down.

    Round 1: Building from a sub-file

    Texmaker. Press F1 (Quick Build) while editing 04-optimization.tex and Texmaker builds that file — which promptly fails, because a chapter fragment has no preamble. The fix is the master document mechanism: Options → Define Current Document as ‘Master Document’. Do this once per session opening — it’s a mode you enable, and if you forget, your first build of the day fails first. (There’s also “restore previous session,” which helps, but the master state has a way of needing re-declaration at the worst moments.)

    texspark. Mark main.tex as the build target once — ⌘⇧P, or double-click its tab; it gets a 🔨 icon. From then on, ⌘B from any chapter builds main.tex. The target survives relaunch with the session. And if you open the project through the PDF side (more on that below), the build target sets itself.

    The difference isn’t capability — both editors can build the right file. It’s that one asks you to remember a mode, and the other asks you to make one decision, once.

    Round 2: The outline

    Texmaker. The Structure panel shows the sections of open files, per file. It goes down to subsubsection — a hierarchy depth I know precisely, because I once patched the source to add \paragraph support. To see chapter 7’s structure, chapter 7 must be open; the panel won’t walk the \include chain from main.tex and assemble the book for you.

    texspark. The outline is project-wide by construction: it parses the build target and follows every \input/\include recursively, presenting one tree in document order — chapters you haven’t opened included. It reads live buffers, so unsaved edits appear immediately; commented-out sections don’t. Click any entry and the right file opens at the right line.

    For a 200-page manuscript, this is the difference between “the outline is where I navigate the book” and “the outline is where I navigate the file I already found.”

    Round 3: Jumping between source and PDF — both directions

    Source → PDF (forward search)

    Texmaker. The built-in viewer supports forward search, and it works — from the current file to the corresponding PDF position, provided the master document is set and SyncTeX data exists. From a sub-file, the jump resolves against the master’s PDF, which is the right behavior when the mode is on.

    texspark. ⌘⇧↩ from anywhere — main file or chapter twelve — scrolls the PDF to your cursor’s line and flashes a yellow pulse there for about a second and a half, so your eye lands with your click. The same forward jump also fires when you click an outline entry or an issue row, and if the right panel happens to be showing the AI chat, it flips back to the PDF first. One more detail for long builds: the PDF’s scroll position survives multi-pass rebuilds, so a xelatex → makeindex → xelatex cycle doesn’t fling you back to page one before the jump.

    PDF → source (inverse search)

    Texmaker. Click in the viewer and you land in the source, including into included files, as long as the file is (or gets) open and SyncTeX data is present. Serviceable, occasionally moody about which window gets focus.

    texspark. ⌘-click in the PDF lands on the matching line, opening the sub-file as a tab if needed. Then the detail I’m proudest of: if you jumped into a sub-file, its parent automatically becomes the build target. The app infers the project root from where you came from — so the very next ⌘B does the right thing without you having declared anything at all.

    Round trip, in practice: pulse to the PDF, ⌘-click back into whatever chapter needs fixing, ⌘B, and the right book rebuilds. No mode, no declaration, no “wait, which file am I building.”

    The scorecard

    Honest totals: Texmaker does all three jobs. It did them for me for a decade, through a dissertation and every paper since. But each job carries a small tax — declare the master again, open the file to see its structure, mind the focus. Ten years of small taxes is what texspark was built to refund.

    If your projects are one file long, genuinely: either editor, and Texmaker is free. If your main.tex is a table of \includes — try the 14-day trial at texspark.io and build from a sub-file on day one. That single ⌘B is the whole pitch.


  • Something changed at v0.7.0, and I can describe it precisely: I stopped opening Xcode in the morning.

    For months, the routine was fixed. Coffee, Xcode, texspark’s source, chase whatever broke yesterday. The book — the entire reason texspark exists — got the leftovers: an evening hour here, a guilty weekend session there. The tool was eating the work it was built for.

    Somewhere around v0.7.0, the ratio flipped.

    Once the big architecture settled, my days became writing days. But here’s the part I didn’t expect: the writing became the QA department. Hours of real manuscript work put the editor into situations no test plan would have invented — and out came the bugs. Small ones. Strange ones. The kind you only meet at paragraph three hundred: a fold that misbehaves in one specific nesting, a scroll that drifts by a hair after a particular build sequence, an outline entry that’s right in every way except one. Each one small, each one irritating, each one findable only by actually living in the app.

    So the rhythm now is: write, hit something odd, note it, keep writing. Fix the batch when it’s worth a detour. The commit log shows it — June was a wall of commits at hours I’m not proud of; July is a steady trickle of small, weird, satisfying fixes. Meanwhile the manuscript’s word count, flat for weeks, has started climbing like it finally got permission.

    I won’t pretend texspark is finished. v0.7.0 is not v1.0; the roadmap still has real items on it. But there’s a threshold every tool-building detour eventually meets: the moment the tool recedes into the background and only the work remains — surfacing just often enough to hand you a bug report written in your own manuscript.

    Three chapters down, twelve to go. The editor works. Back to the book — which is, it turns out, also the test suite.


  • A random thought hit me the other day: if the information is identical, which human language requires the fewest LLM tokens? You’d think this is a linguistics question. It turns out to be an economics question wearing a linguistics costume.

    The intuition

    Chinese should win, right? 猫 is one character; “cat” is three. Classical information-density arguments say logographic scripts pack more meaning per glyph. If tokens tracked meaning, dense languages would be cheap.

    The reality

    Tokens don’t track meaning. They track what the tokenizer saw during training — and tokenizers grew up reading mostly English.

    Tokenizers don’t operate on characters; they operate on sub-word units, so character-level efficiency doesn’t automatically translate to token efficiency. A Chinese character can get fragmented into multiple tokens — sometimes one token per part of a character — because the byte-level vocabulary never merged it into a unit. Meanwhile “the” gets its own cozy token because English dominates the training corpus. arXivMedium

    The numbers bear it out. A study using 2 million professionally translated sentences found that every CJK language uses more tokens than English — no exceptions. On GPT’s cl100k_base tokenizer, Chinese pays roughly 15% more tokens for equivalent content, and low-resource languages fare far worse — Khmer, Lao, and Burmese show notably high length ratios on most open-source LLMs. arxivGitHub

    So English wins?

    On most Western tokenizers, yes — but for the least satisfying reason possible: home-field advantage. The proof: GLM’s Chinese-native tokenizer inverts the pattern, producing fewer tokens for Chinese than English (ratio 0.923). Same languages, opposite winner. The answer to “which language is most efficient” is: whichever one your tokenizer grew up speaking. GitHub

    (For fun: one recent paper asked whether Sanskrit — famously compact — beats everyone. With bias-controlled tokenizers trained at equal vocabulary sizes, Sanskrit does show superior density. The ancient grammarians would be pleased with their compression ratio.) Sicheng Ouyang

    Why a LaTeX person cares

    I write in Korean, English, and LaTeX daily, often through texspark’s AI panel — where the attach-document toggle ships my source to a model with a 60 KB cap and a token bill. My source files are trilingual: Korean prose, English terms, LaTeX markup. Every \begin{equation} is a flat tax in any language.

    The practical takeaway is almost embarrassing: prompting in English is usually cheapest, not because English is better, but because the meter was calibrated in it. Somewhere in that fact is a whole essay about soft power. This is not that essay. This was just a random thought that turned out to have a real answer.


  • I’ve noticed something about texspark’s bug reports lately — most of them filed by me, to me, at unreasonable hours: debugging keeps getting more complicated.

    Early on, bugs were honest. The app crashed on launch. The PDF didn’t load. Autocomplete inserted the wrong text, visibly, right in front of you. You could reproduce them in five seconds, fix them in an hour, and feel like a genius before lunch.

    The current crop is different.

    The recent specimen: code folding. Fold a section and, sometimes, the text below it drew on top of the folded region — two layers of document, overlapping like a double-exposed photograph. Ugly, obvious, clearly wrong.

    And it would not reproduce.

    That was the real problem. Not the glitch itself — the fact that I couldn’t summon it. Same file, same folds, same steps: clean. Then an hour later, doing nothing special, there it was again. A bug you can’t reproduce is a bug you can’t even begin to fix; you’re not debugging anymore, you’re waiting for a ghost to walk past.

    When it became clear the ghost lived somewhere deep in the text layout stack, the fix stopped being a fix and became a decision: I tore out the TextKit layer entirely and rebuilt on a different foundation. Not four lines. Not forty. The whole floor.

    Here’s the reframe that keeps me sane: this is what progress looks like. Easy bugs are a property of immature software — they’re everywhere, so you trip over them constantly. When the remaining bugs are non-deterministic rendering ghosts that force architectural surgery, it means the five-second bugs are gone. The floor got raised. The weird stuff is what’s left because everything normal already works.

    There’s a name for this in quality engineering — surviving bugs are survivors for a reason. They live in the corners, in timing and layout internals, precisely because everything in the open has been shot.

    So: the debugging is slower now, the git log less heroic, and one commit last week just says “replace text layout system.” And that’s the best evidence I have that texspark is becoming a real, grown-up piece of software.

    The bugs are getting harder. Good.


  • It starts innocently. Someone sends you a figure for the paper — a .png, 800×600, screenshot of a matplotlib window. You paste it in, compile, zoom to 400% the way you always do, and there it is: the blur. The soft, fuzzy edges of a rasterized line. And something in you dies a little.

    Congratulations. You have the condition. There’s no cure.

    Symptoms

    You know you have it when:

    • You can identify, from across a conference hall, which posters were made in PowerPoint. The pixelated axis labels call to you.
    • You’ve said the phrase “can you send me the PDF version?” more times than you’ve said “happy birthday.”
    • Your matplotlib scripts end in savefig('fig3.pdf') and have for a decade. You don’t remember choosing this. There was never a choice.
    • You’ve zoomed into your own compiled PDF to 6400% — not to check anything. Just to watch the curve stay perfect. Just to feel something.
    • TikZ has made you cry exactly twice: once learning it, once realizing you can never go back.

    The pathology

    Here’s the thing — the obsession is correct. That’s what makes it incurable. A raster image is a lie told at one resolution. A vector image is the truth: the actual curve, the actual glyph, described mathematically, rendered perfectly at any scale, printed at any DPI, forever.

    LaTeX people were always going to fall hard for this. The entire premise of TeX is that a document is a program, not a picture — so of course its users demand that figures be equations too. Pixels are someone else’s compromise.

    The suffering

    The condition has costs. You will spend forty minutes converting a collaborator’s .jpg chart into pgfplots — “it’s just cleaner this way” — for a figure that appears at 4cm wide. You will maintain strong opinions about PDF vs EPS. You will see a beautiful, useful diagram on the web and feel genuine grief that it’s a PNG.

    And journals will rasterize your perfect figures in production anyway, and you will never emotionally recover.

    For the record

    My entire book — every figure, every diagram — is vector. Some of those figures took longer than the sections they illustrate. I regret nothing. At 6400% zoom, the curves are perfect.

    Nobody will ever zoom to 6400%.

    They’re perfect anyway.