<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:base="en">
	<title>Tim Disney</title>
	<subtitle>I&#39;m Tim Disney and I make code and things</subtitle>
	<link href="https://disnetdev.com/feed/feed.xml" rel="self"/>
	<link href="https://disnetdev.com/"/>
	<updated>2026-01-27T00:00:00Z</updated>
	<id>https://disnetdev.com/</id>
	<author>
		<name>Tim Disney</name>
		<email>tim@disnetdev.com</email>
	</author>
	
	<entry>
		<title>Stuff I Enjoyed in 2025 - Publications &amp; Writing</title>
		<link href="https://disnetdev.com/blog/2026-01-27-stuff-i-enjoyed-in-2025-publications-and-writing/"/>
		<updated>2026-01-27T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2026-01-27-stuff-i-enjoyed-in-2025-publications-and-writing/</id>
		<content type="html">&lt;p&gt;Continuing my (delayed) 2025 reflection series with the publications and articles I most enjoyed reading in 2025. Previously: &lt;a href=&quot;https://www.disnetdev.com/blog/2026-01-16-stuff-i-enjoyed-in-2025-books/&quot;&gt;Stuff I Enjoyed in 2025 - Books&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My religious read for the year was &lt;a href=&quot;https://www.garbageday.email/&quot;&gt;Garbage Day&lt;/a&gt;. They do a great job of contextualizing the wild and frustrating events in an entertaining way. Also great is &lt;a href=&quot;https://www.todayintabs.com/&quot;&gt;Today in Tabs&lt;/a&gt; with such sharp writing.&lt;/p&gt;
&lt;p&gt;The (semi)political writers I followed included &lt;a href=&quot;https://www.unpopularfront.news/&quot;&gt;John Ganz&lt;/a&gt;, &lt;a href=&quot;https://www.programmablemutter.com/&quot;&gt;Henry Farrell&lt;/a&gt;, and &lt;a href=&quot;https://davekarpf.substack.com/&quot;&gt;Dave Karpf&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.filfre.net/&quot;&gt;The Digital Antiquarian&lt;/a&gt; has also been a really fun read going through the archives of old games. &lt;a href=&quot;https://www.filfre.net/2025/11/the-space-sims-last-hurrah/&quot;&gt;The Space Sim&#39;s Last Hurrah&lt;/a&gt; and &lt;a href=&quot;https://www.filfre.net/2025/06/alpha-centauri/&quot;&gt;Alpha Centauri&lt;/a&gt; in particular were great. &lt;em&gt;Alpha Centauri&lt;/em&gt; and &lt;em&gt;Freespace 2&lt;/em&gt; were two of my favorite games growing up and essentially no one remembers them.&lt;/p&gt;
&lt;p&gt;To make sense of all the AI developments &lt;a href=&quot;https://simonwillison.net/&quot;&gt;Simon Willison&#39;s&lt;/a&gt; blog was indispensable. Also great was &lt;a href=&quot;https://www.cognitiveresonance.net/&quot;&gt;Cognitive Resonance&lt;/a&gt; putting things in a cognitive science framework, &lt;a href=&quot;https://www.normaltech.ai/&quot;&gt;AI Snake Oil/AI as Normal Technology&lt;/a&gt; and their seminal &lt;a href=&quot;https://knightcolumbia.org/content/ai-as-normal-technology&quot;&gt;AI as Normal Technology&lt;/a&gt; article, Ethan Mollick from &lt;a href=&quot;https://www.oneusefulthing.org/&quot;&gt;One Useful Thing&lt;/a&gt; (taken with a grain of salt), and &lt;a href=&quot;https://contraptions.venkateshrao.com/&quot;&gt;Venkatesh Rao&lt;/a&gt; for seeing someone explore going all in without being a complete grifter.&lt;/p&gt;
&lt;p&gt;Favorite articles:&lt;/p&gt;
&lt;p&gt;(note: I&#39;m not necessarily cosigning the claims or ideas of any of these articles. They just got me thinking the most in 2025.)&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.programmablemutter.com/p/were-getting-the-social-media-crisis?publication_id=1745679&amp;amp;post_id=154328417&amp;amp;isFreemail=true&amp;amp;r=qcnxw&amp;amp;triedRedirect=true&amp;amp;__readwiseLocation=&quot;&gt;We&#39;re getting the social media crisis wrong&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The fundamental problem, as I see it, is not that social media &lt;em&gt;misinforms individuals&lt;/em&gt; about what is true or untrue but that it creates &lt;em&gt;publics with malformed collective understandings&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This reframing is just great.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://contraptions.venkateshrao.com/p/be-slightly-monstrous?publication_id=9973&amp;amp;post_id=180215443&amp;amp;isFreemail=true&amp;amp;r=1dcd14&amp;amp;triedRedirect=true&quot;&gt;Be Slightly Monstrous&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The real conceit here is about consciously surrendering to a machinic reshaping of your patterns of cognition. Your ways of seeing. Your ways of feeling into reality.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;He&#39;s exploring something interesting here. Not sure I like it but it&#39;s interesting.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://contraptions.venkateshrao.com/p/revenge-of-the-dilettantes?publication_id=9973&amp;amp;post_id=182114230&amp;amp;isFreemail=true&amp;amp;r=1dcd14&amp;amp;triedRedirect=true&quot;&gt;Revenge of the Dilettantes&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The future is &lt;em&gt;bespokeness.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The claim is something like AI is in the process of driving the cost of production so low that there won&#39;t be any reason not to spin up bespoke productions for basically any creative output.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://fivetwelvethirteen.substack.com/p/why-some-students-learn-faster?__readwiseLocation=&quot;&gt;Why Some Students Learn Faster&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Researchers divide intelligence into two parts: crystallized intelligence and fluid intelligence. Crystallized intelligence refers to how much you know: knowing things makes you smarter. [...] Fluid intelligence is a broad term for how well we can think and reason when we don’t have crystallized intelligence to rely on.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I hadn&#39;t come across the distinction between crystallized and fluid intelligence before so this was a bit of a revelation for me.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://thepointmag.com/politics/the-bookmaker/?__readwiseLocation=&quot;&gt;The Bookmaker&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;But what Silver willfully ignores is that the successful players in this world aren’t the bettors. They are the bookies and casino owners—the house that never loses.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Gambling is bad.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://fly.io/blog/youre-all-nuts/?__readwiseLocation=&quot;&gt;My AI Skeptic Friends Are All Nuts&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Some of the smartest people I know share a bone-deep belief that AI is a fad — the next iteration of NFT mania. I’ve been reluctant to push back on them, because, well, they’re smarter than me. But their arguments are unserious, and worth confronting. Extraordinarily talented people are doing work that LLMs already do better, out of spite.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;My read is that the consensus has definitively shifted after the release of Opus 4.5 at the end of the year to acknowledge coding agents are good actually but during the year there was a lot of &lt;em&gt;discourse&lt;/em&gt;. This was my favorite piece trying to convince the skeptics.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://maxread.substack.com/p/the-zizians-and-the-rationalist-death?publication_id=392873&amp;amp;post_id=156012376&amp;amp;isFreemail=true&amp;amp;r=1dcd14&amp;amp;triedRedirect=true&quot;&gt;The Zizians and the Rationalist death cults&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Feeling comfortable with your own epistemological position, even if you know it’s flawed, is not the preferred mode for Rationalist development, but it’s pretty foundational to building a stable sense of self. By the same token, the ability to dismiss an argument with a “that sounds nuts,” without needing recourse to a point-by-point rebuttal, is anathema to the rationalist project. But it’s a pretty important skill to have if you want to avoid joining cults.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I think this is a sharp insight into one of the flaws inherent to the Rationalist community.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://knightcolumbia.org/content/ai-as-normal-technology&quot;&gt;AI as Normal Technology&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This was probably the most important article about AI in 2025. A well thought through middle path between &amp;quot;the singularity is coming in &lt;a href=&quot;https://ai-2027.com/&quot;&gt;2027&lt;/a&gt;&amp;quot; and &amp;quot;AI is a fad like NFTs&amp;quot;.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Skyreader: A RSS Reader on the AT Protocol</title>
		<link href="https://disnetdev.com/blog/2026-01-20-skyreader-a-rss-reader-on-the-at-protocol/"/>
		<updated>2026-01-20T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2026-01-20-skyreader-a-rss-reader-on-the-at-protocol/</id>
		<content type="html">&lt;p&gt;I&#39;ve just released &lt;a href=&quot;https://skyreader.app/&quot;&gt;Skyreader&lt;/a&gt;, a RSS reader built on the AT Protocol.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;login with your bluesky account&lt;/li&gt;
&lt;li&gt;share articles like Google Reader but on the AT protocol&lt;/li&gt;
&lt;li&gt;your feeds and shares are stored on your server, not locked in my app&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://disnetdev.com/img/ae204373.png&quot; alt=&quot;Screenshot of Skyreader showing a list of RSS feeds&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;rss-is-neat&quot; tabindex=&quot;-1&quot;&gt;RSS is neat &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2026-01-20-skyreader-a-rss-reader-on-the-at-protocol/#rss-is-neat&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://pluralistic.net/2024/10/16/keep-it-really-simple-stupid/&quot;&gt;You should be using an RSS reader&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;RSS readers are simple. They manage a list of websites you care about and show you new articles when they&#39;re posted. No algorithm deciding what you should see.&lt;/p&gt;
&lt;h2 id=&quot;what-makes-skyreader-different&quot; tabindex=&quot;-1&quot;&gt;What makes Skyreader different &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2026-01-20-skyreader-a-rss-reader-on-the-at-protocol/#what-makes-skyreader-different&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;My favorite feature from the late, great Google Reader was article sharing. You could share articles to your followers in one click. It was a low-effort way to see what your friends were reading and share what you found interesting.&lt;/p&gt;
&lt;p&gt;That feature died with Google Reader. Sure, you can post links in group chats or on social media now, but that collapses too many contexts. A dedicated feed of articles from a friend hits different.&lt;/p&gt;
&lt;p&gt;Other RSS readers added social features after Google Reader shut down (like &lt;a href=&quot;https://www.theoldreader.com/en/&quot;&gt;the old reader&lt;/a&gt;), but they all had the same problem: the social graph was locked into their platform. RSS itself is client-agnostic but article sharing was never part of the protocol, so it stayed locked in closed ecosystems.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://atproto.com/&quot;&gt;AT Protocol&lt;/a&gt; fixes this. AT Protocol is the underlying protocol for &lt;a href=&quot;https://bsky.app/&quot;&gt;Bluesky&lt;/a&gt;  and other decentralized apps. It&#39;s a kind of &lt;a href=&quot;https://overreacted.io/a-social-filesystem/&quot;&gt;social filesystem&lt;/a&gt; that lets apps interoperate.&lt;/p&gt;
&lt;p&gt;Skyreader writes the feeds you follow and the shares you make to the AT Protocol, so anyone could build a RSS reader that shows your shares. Your data is yours and the social layer is as portable as the feeds themselves.&lt;/p&gt;
&lt;p&gt;I wrote Skyreader to match how I think about feeds. That might not work for you; the sheer number of different RSS readers suggests we all think about this differently. The neat thing about building on the AT protocol is we can all share the underlying data (feeds, shares) and move between readers as we like.&lt;/p&gt;
&lt;p&gt;Take a look at Skyreader and let me know what you think. If you find any bugs let me know, but if you want it to work differently just make your own! RSS readers are simple, you can probably get Claude to knock one out in an afternoon (that&#39;s how long the initial Skyreader prototype took me). The code for Skyreader is available on &lt;a href=&quot;https://github.com/disnet/skyreader&quot;&gt;Github&lt;/a&gt; if you want a starting point with the &lt;a href=&quot;https://github.com/disnet/skyreader/blob/main/docs/LEXICONS.md&quot;&gt;lexicon&lt;/a&gt; being the main thing you&#39;ll need to interoperate.&lt;/p&gt;
&lt;p&gt;It&#39;s time to read like it&#39;s 2010!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Flint January Updates: Markdown Live Preview &amp; Search</title>
		<link href="https://disnetdev.com/blog/2026-01-18-flint-january-updates-markdown-live-preview-and-search/"/>
		<updated>2026-01-18T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2026-01-18-flint-january-updates-markdown-live-preview-and-search/</id>
		<content type="html">&lt;p&gt;Flint now supports live preview for markdown syntax!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://disnetdev.com/img/46b4554c.png&quot; alt=&quot;Screenshot with live preview&quot;&gt;&lt;/p&gt;
&lt;p&gt;This should make viewing your notes much nicer. I&#39;d been reluctant to implement live preview before now because I figured it would be tricky to implement and also I like plain markdown just fine. But, my husband&#39;s first round of feedback when I made him try Flint was that raw markdown sucks (he said it gently of course lol). Getting it working was way easier than I&#39;d made it out to be so I really should have gotten to it earlier. Ah well.&lt;/p&gt;
&lt;p&gt;Relatedly, I&#39;ve also added a bunch of UX affordances to make formatting easier and more discoverable.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://disnetdev.com/img/57099d6e.png&quot; alt=&quot;Screenshot with formatting bar&quot;&gt;&lt;/p&gt;
&lt;p&gt;Now when you select text a formatting window pops up so you can apply your &lt;strong&gt;bold&lt;/strong&gt; formatting choices.&lt;/p&gt;
&lt;p&gt;We also now have a &amp;quot;+&amp;quot; button in the gutter (alternatively toggled by typing &lt;code&gt;/&lt;/code&gt;) that allows you to insert block level syntax like headers and quotes.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://disnetdev.com/img/f296f4ae.png&quot; alt=&quot;Screenshot with block bar&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;search-improvements&quot; tabindex=&quot;-1&quot;&gt;Search improvements &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2026-01-18-flint-january-updates-markdown-live-preview-and-search/#search-improvements&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Up until now search results have been limited to showing matched titles and small snippets of note content. Now &lt;code&gt;Cmd+Shift+Enter&lt;/code&gt; (or &lt;code&gt;Ctrl+Shift+Enter&lt;/code&gt; on Windows/Linux) opens an expanded search result screen that shows matches across all notes. Searches can also be saved in the sidebar too so you can refer back if needed.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://disnetdev.com/img/8b6d550f.png&quot; alt=&quot;Screenshot of search&quot;&gt;&lt;/p&gt;
&lt;p&gt;So that&#39;s what&#39;s changed recently. Take a look and as always let me know what you think.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Stuff I Enjoyed in 2025 - Books</title>
		<link href="https://disnetdev.com/blog/2026-01-16-stuff-i-enjoyed-in-2025-books/"/>
		<updated>2026-01-16T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2026-01-16-stuff-i-enjoyed-in-2025-books/</id>
		<content type="html">&lt;p&gt;This is part of my 2025 yearly roundup covering the books I read. tbh the middle of January is a bit late for an annual reflection but whatever, this is my blog and I can do what I want lol.&lt;/p&gt;
&lt;p&gt;I didn&#39;t read as many books in 2025 as I would have liked so one of my 2026 goals is to fix that. Part of my issue is that I read multiple books at the same time. Not ideal so maybe in 2026 I can try and focus on one book at a time.&lt;/p&gt;
&lt;h2 id=&quot;books-actually-finished&quot; tabindex=&quot;-1&quot;&gt;Books actually finished &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2026-01-16-stuff-i-enjoyed-in-2025-books/#books-actually-finished&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://press.uchicago.edu/ucp/books/book/chicago/U/bo252799883.html&quot;&gt;The Unaccountability Machine&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The most interesting book I finished all year, will be thinking about this one for a while. It&#39;s about &amp;quot;the industrialisation of decision-making&amp;quot; and how accountability (or unaccountability as the case might be) now works (or doesn&#39;t).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;we began to get into the habit of ignoring the fact that every year, more of the decisions that affect our lives are made not by people but by systems. Strange, alien intelligences with desires and drives quite different from our own. They’re taking over the world – and not only that, for it seems that some of them are going mad.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;By &amp;quot;strange, alien intelligences&amp;quot; he mostly means a corporation and related kinds of decision-making organizations rather than AI but this line is becoming even more true as we restructure the world with LLMs.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.amazon.com/Deep-Response-Emergency-Education-Post-Consumer/dp/B0DR7F5SFJ&quot;&gt;Deep Response&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;My brother wrote a book! It&#39;s about figuring out how to deal with The Predicament. Sort of? Maybe?&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.simonandschuster.com/books/Abundance/Ezra-Klein/9781668023488&quot;&gt;Abundance&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Interesting in the abstract but I wouldn&#39;t necessarily recommend it. &lt;a href=&quot;https://davekarpf.substack.com/p/abundance-is-a-book-for-an-alternate&quot;&gt;A book for an alternate timeline&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.hachettebookgroup.com/titles/adam-becker/more-everything-forever/9781541619593/&quot;&gt;More Everything Forever&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Required reading for our current technological/political moment if you haven&#39;t been following the thinking of &amp;quot;those guys&amp;quot; (MacAskill, Altman, SBF, Kurzweil, Yudkowsky, etc.) for a while.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.nealstephenson.com/termination-shock.html?trk=article-ssr-frontend-pulse_little-text-block&quot;&gt;Termination Shock&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A classic Neal Stephenson book for both good and bad.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Frankenstein&quot;&gt;Frankenstein&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Picked it up after watching the Guillermo del Toro movie version. Thought I had read it before but apparently not. It&#39;s good!&lt;/p&gt;
&lt;h2 id=&quot;started-but-not-finished&quot; tabindex=&quot;-1&quot;&gt;Started but not finished &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2026-01-16-stuff-i-enjoyed-in-2025-books/#started-but-not-finished&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.upress.umn.edu/9781517919320/language-machines/&quot;&gt;Language Machines&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Most interesting book I started but didn&#39;t finish. The basic claim is that structuralism has something interesting to say about LLMs.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://roland-allen.com/&quot;&gt;The Notebook&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Not the Nicholas Sparks novel. Instead a history of note-taking and actual notebooks. Obviously relevant to my interests with &lt;a href=&quot;https://www.flintnote.com/&quot;&gt;Flint&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.penguinrandomhouse.com/books/648051/the-tainted-cup-by-robert-jackson-bennett/&quot;&gt;The Tainted Cup&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Just a really fun fantasy novel about detectives solving a murder in a empire that has to deal with the occasional leviathan invasion.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ifanyonebuildsit.com/&quot;&gt;If Anyone Builds It, Everyone Dies&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I don&#39;t agree with the conclusion or arguments but worth reading to get a sense of how the LessWrong crowd thinks (without wading through that site). Pair with &lt;a href=&quot;https://www.hachettebookgroup.com/titles/adam-becker/more-everything-forever/9781541619593/&quot;&gt;More Everything Forever&lt;/a&gt; if you must read it.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>New Year, New Flint</title>
		<link href="https://disnetdev.com/blog/2026-01-03-new-year-new-flint/"/>
		<updated>2026-01-03T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2026-01-03-new-year-new-flint/</id>
		<content type="html">&lt;p&gt;Big changes with &lt;a href=&quot;https://www.flintnote.com/&quot;&gt;Flint&lt;/a&gt;! Over the holidays I completely reworked just about every part of Flint.&lt;/p&gt;
&lt;p&gt;The UI has been totally refreshed, making every view cleaner and easier to navigate.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://disnetdev.com/img/2026-01-03-flint-interface.png&quot; alt=&quot;Screenshot of Flint with the Agent panel open&quot;&gt;&lt;/p&gt;
&lt;p&gt;Under the hood, the way Flint stores  data has also changed. Previously we used a local SQLite database with a two-way sync to markdown files. This worked well enough (though the sync code was gross and had unresolved bugs) but the architecture made it hard to implement features I really wanted like versioning and syncing.&lt;/p&gt;
&lt;p&gt;So, the new Flint now uses &lt;a href=&quot;https://automerge.org/&quot;&gt;Automerge&lt;/a&gt; to store notes, while still keeping the two-way markdown file syncing of the previous version. Automerge is a &lt;a href=&quot;https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type&quot;&gt;CRDT&lt;/a&gt; library that makes it possible to sync data across devices without needing to store all your data in a central server. The current rework doesn&#39;t including syncing yet but guess what feature I&#39;ll be working on soon 😆.&lt;/p&gt;
&lt;p&gt;The other capability Automerge gives us is the ability to easily make a web app that stores all your note data locally in the browser. You can try it out &lt;a href=&quot;https://app.flintnote.com/&quot;&gt;here&lt;/a&gt; to see the new interface and features without installing anything. The only capabilities that aren&#39;t included at the moment are markdown file syncing, review mode, and the AI agent.&lt;/p&gt;
&lt;p&gt;I think Flint is really starting to come together. More to come soon but take a look and let me know what you think!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Flint December Beta Updates (Open source and so many features)</title>
		<link href="https://disnetdev.com/blog/2025-12-08-flint-december-beta-updates-open-source-and-so-many-features/"/>
		<updated>2025-12-08T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2025-12-08-flint-december-beta-updates-open-source-and-so-many-features/</id>
		<content type="html">&lt;p&gt;Progress on Flint has been going incredibly well! I&#39;m recently back home from a great trip to Japan and with the release of Claude Opus 4.5 I&#39;ve kinda been going beast mode on Flint development. Here&#39;s a roundup of all the features I&#39;ve managed to ship in the past couple of weeks.&lt;/p&gt;
&lt;h2 id=&quot;flint-beta-is-open-source&quot; tabindex=&quot;-1&quot;&gt;Flint Beta is Open (Source) &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2025-12-08-flint-december-beta-updates-open-source-and-so-many-features/#flint-beta-is-open-source&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First up though, the Flint beta is now open to anyone who wants to kick the tires. You can download it &lt;a href=&quot;https://www.flintnote.com/#download&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Not only is it free to download but I&#39;ve also committed to open source. Flint&#39;s code is now free and available on &lt;a href=&quot;https://github.com/disnet/flint-note&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Core to my vision of Flint is that you own your thinking and for that to be true you must also have control over the means of (note) production. So open source it is.&lt;/p&gt;
&lt;p&gt;On to the actual features.&lt;/p&gt;
&lt;h2 id=&quot;review-mode&quot; tabindex=&quot;-1&quot;&gt;Review Mode &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2025-12-08-flint-december-beta-updates-open-source-and-so-many-features/#review-mode&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Review mode is a key piece of the &amp;quot;resurface&amp;quot; design pillar I&#39;ve written about &lt;a href=&quot;https://www.disnetdev.com/blog/2025-11-14-whats-the-point-of-a-note-taking-app/&quot;&gt;previously&lt;/a&gt;, which is all about helping you meaningfully re-engage with your notes over time.&lt;/p&gt;
&lt;p&gt;The way it works is any note you click &amp;quot;Enable Review&amp;quot; on is added to your review queue in the new &amp;quot;Review&amp;quot; system view. When you start a review the agent reads your notes and generates a question to get you to meaningfully engage with the material.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://disnetdev.com/img/2025-12-08-review-mode.png&quot; alt=&quot;Reviewing a note with agent prompts and feedback&quot;&gt;&lt;/p&gt;
&lt;p&gt;You can then write a response and mark how well your engagement with the note went. Based on your response the note is scheduled for review sometime in the future.&lt;/p&gt;
&lt;p&gt;I think this mode is a pretty big deal. &lt;a href=&quot;https://en.wikipedia.org/wiki/Spaced_repetition&quot;&gt;Spaced repetition&lt;/a&gt; is a well-studied and powerful technique for learning but creating effective prompts has always been a challenge. I think integrating the prompt and scheduling interface into your note-taking system unlocks something special.&lt;/p&gt;
&lt;h2 id=&quot;epub-pdf-web-viewers-with-highlighting&quot; tabindex=&quot;-1&quot;&gt;EPUB/PDF/Web Viewers with Highlighting &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2025-12-08-flint-december-beta-updates-open-source-and-so-many-features/#epub-pdf-web-viewers-with-highlighting&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To help create more material for you to review, you can now add EPUBs, PDFs, and web pages to Flint. Each file type has its own optimized viewer and each viewer has support for making highlights. And, of course, the agent can read your books too.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://disnetdev.com/img/2025-12-08-epub.png&quot; alt=&quot;Screenshot of an EPUB of &amp;quot;Language Machines&amp;quot; with the agent giving a summary of the introduction.&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;decks-aka-queries-databases-bases&quot; tabindex=&quot;-1&quot;&gt;Decks (aka Queries/Databases/Bases) &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2025-12-08-flint-december-beta-updates-open-source-and-so-many-features/#decks-aka-queries-databases-bases&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To help you keep track of all the notes you will now be creating I&#39;ve also added Decks. Decks allow you to build dashboards of notes that match specific filters (a bit like Notion&#39;s Databases or Obsidian&#39;s Bases). Use it to track things like reading/watch lists, todo lists, etc.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://disnetdev.com/img/2025-12-08-deck.png&quot; alt=&quot;Screenshot of a Deck showing a list of movies&quot;&gt;&lt;/p&gt;
&lt;p&gt;For example, if you create a &amp;quot;movie&amp;quot; note type with properties like &amp;quot;rating&amp;quot; and &amp;quot;status&amp;quot; you can create a deck to track your favorites (&lt;code&gt;type = movie AND rating &amp;gt;= 8&lt;/code&gt;) and another deck to track your watchlist (&lt;code&gt;type = movie AND status != &amp;quot;seen&amp;quot;&lt;/code&gt;). No need to memorize the query syntax though, the UI lets you easily build complex filters and the agent is also very capable at building decks for you.&lt;/p&gt;
&lt;p&gt;Each row in a deck is live—you can directly edit the title and properties to quickly keep your notes up to date.&lt;/p&gt;
&lt;h2 id=&quot;workspaces&quot; tabindex=&quot;-1&quot;&gt;Workspaces &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2025-12-08-flint-december-beta-updates-open-source-and-so-many-features/#workspaces&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Workspaces are another feature to help you keep track of all your notes. They allow you to create focused groups of Pinned/Recent notes and quickly switch between them with keyboard shortcuts. Workspaces are great for creating dedicated groups of notes for managing different projects. As an example, I currently use the following spaces:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Default (unorganized, in-the-moment notes)&lt;/li&gt;
&lt;li&gt;Flint (my notes about Flint development)&lt;/li&gt;
&lt;li&gt;Writing (blog post drafts and supporting material)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://disnetdev.com/img/2025-12-08-workspace.png&quot; alt=&quot;Screenshot showing three workspaces&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;full-text-search&quot; tabindex=&quot;-1&quot;&gt;Full Text Search &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2025-12-08-flint-december-beta-updates-open-source-and-so-many-features/#full-text-search&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The search bar now performs full text search across your notes:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://disnetdev.com/img/2025-12-08-search.png&quot; alt=&quot;Screenshot showing a search with matching in note content&quot;&gt;&lt;/p&gt;
&lt;p&gt;Previously search only matched note titles. It now prioritizes note titles to make switching between notes easier but will also search note content.&lt;/p&gt;
&lt;h2 id=&quot;note-archiving&quot; tabindex=&quot;-1&quot;&gt;Note Archiving &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2025-12-08-flint-december-beta-updates-open-source-and-so-many-features/#note-archiving&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To keep your vault clean you can now archive notes. Archived notes are not deleted but will no longer show up in search or link autocomplete lists. All existing links to archived notes will still work, you just can&#39;t make any edits until you unarchive.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://disnetdev.com/img/2025-12-08-archive.png&quot; alt=&quot;Screenshot of an archived note&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;image-embedding&quot; tabindex=&quot;-1&quot;&gt;Image Embedding &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2025-12-08-flint-december-beta-updates-open-source-and-so-many-features/#image-embedding&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can now embed images in your notes:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://disnetdev.com/img/2025-12-08-image.png&quot; alt=&quot;Screenshot of a note with embedded images&quot;&gt;&lt;/p&gt;
&lt;p&gt;Just drag and drop in image files from the finder/file explorer.&lt;/p&gt;
&lt;h2 id=&quot;agent-suggestions&quot; tabindex=&quot;-1&quot;&gt;Agent Suggestions &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2025-12-08-flint-december-beta-updates-open-source-and-so-many-features/#agent-suggestions&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You can now have the agent generate suggestions for how to improve a note with comments along the side:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://disnetdev.com/img/2025-12-08-suggestions.png&quot; alt=&quot;Screenshot showing agent suggestions on a draft of the blog post. Hope I took the suggestion.&quot;&gt;&lt;/p&gt;
&lt;p&gt;Suggestions are only generated on demand so you need to click the &amp;quot;Generate Suggestions&amp;quot; first to see them:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://disnetdev.com/img/2025-12-08-menu.png&quot; alt=&quot;Screenshot of the note menu&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;next-up&quot; tabindex=&quot;-1&quot;&gt;Next Up &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2025-12-08-flint-december-beta-updates-open-source-and-so-many-features/#next-up&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I&#39;ve got big plans for more features as I work towards getting Flint ready for a 1.0 but the next few releases should be focused on polishing and responding to feedback. So try things out now and let me know how things are working (or not) for you.&lt;/p&gt;
&lt;p&gt;We now have a bunch of places to drop feedback:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GitHub &lt;a href=&quot;https://github.com/disnet/flint-note/issues&quot;&gt;issues&lt;/a&gt; for reporting bugs and &lt;a href=&quot;https://github.com/disnet/flint-note/discussions&quot;&gt;discussions&lt;/a&gt; for general questions or suggestions&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://discord.gg/GbpYCfzE3y&quot;&gt;Discord server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Email: tim@flintnote.com&lt;/li&gt;
&lt;li&gt;Bluesky: &lt;a href=&quot;https://bsky.app/profile/disnetdev.com&quot;&gt;@disnetdev.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&#39;m excited to hear what you think!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>How Flint Helps You Externalize</title>
		<link href="https://disnetdev.com/blog/2025-11-30-how-flint-helps-you-externalize/"/>
		<updated>2025-11-30T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2025-11-30-how-flint-helps-you-externalize/</id>
		<content type="html">&lt;p&gt;As I wrote about in a &lt;a href=&quot;https://www.disnetdev.com/blog/2025-11-14-whats-the-point-of-a-note-taking-app/&quot;&gt;previous post&lt;/a&gt;, a core design goal for Flint is to make externalization, the process of getting ideas out of your head, super simple. Easy note creation results in more notes and this is critical because it supports the other phases of deep knowledge (internalizing and resurfacing) by creating the raw material for you to work with (pure thoughts are hard to manipulate in an app!). Flint tries to accomplish this goal by minimizing the decision of where to start capturing ideas and deferring organization decisions that kill note-taking momentum.&lt;/p&gt;
&lt;p&gt;So how does this work in practice?&lt;/p&gt;
&lt;p&gt;It starts with always having a zero-decision place to begin writing: the Daily view. When you open up Flint with a brilliant idea to capture, just open today&#39;s daily note (&lt;code&gt;Cmd-2&lt;/code&gt;/&lt;code&gt;Ctrl-2&lt;/code&gt;) and start typing.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://disnetdev.com/img/daily-view.png&quot; alt=&quot;Screenshot showing Daily view with the entry &amp;quot;App idea: socks but AI powered and on the blockchain.&amp;quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The daily view displays all your other entries for the week at a glance, making it easy to reflect on what you&#39;ve been thinking about recently while you write about today.&lt;/p&gt;
&lt;p&gt;While capturing in the daily note, you&#39;ll start to identify concepts that are more concrete and deserves their own note. When that happens you can create a new note via the &lt;code&gt;[[title of note]]&lt;/code&gt; link syntax while you&#39;re already typing or with the new note button (shortcut &lt;code&gt;Cmd-Shift-N&lt;/code&gt;/&lt;code&gt;Ctrl-Shift-N&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://disnetdev.com/img/new-note.png&quot; alt=&quot;Screenshot showing a new note being created &amp;quot;Project BitSockGPT&amp;quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Flint doesn&#39;t force you to think about how to organize new notes up front. The note is just created immediately and you can keep typing.
You can decide what kind of note it should be or what metadata it needs later. You don&#39;t even need to pick a title; write first and organize later.&lt;/p&gt;
&lt;p&gt;When you make a new note two other things happen: the note shows up in the &amp;quot;Recents&amp;quot; list on the left sidebar and it&#39;s added to the Inbox (notice the badge on &lt;em&gt;Inbox&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;The Recents and Pinned section of the sidebar are how you manage your open notes. Notes are added to the Recents list when you click on a link or create a new note. The Pinned list is for keeping track of notes you are working on. These lists are manually sorted (via drag and drop), which engages your &lt;a href=&quot;https://en.wikipedia.org/wiki/Spatial_memory&quot;&gt;spatial memory&lt;/a&gt; to help you keep track of where things are.&lt;/p&gt;
&lt;p&gt;This design pattern isn&#39;t new, it draws inspiration from how &lt;a href=&quot;https://arc.net/&quot;&gt;Arc Browser&lt;/a&gt; manages tabs. The fundamental design concept is managing different time horizons for ephemeral items (recents) and items you keep for a longer period of time (pinned).&lt;/p&gt;
&lt;p&gt;The Inbox is another way to help you manage notes across time. Each newly created note goes into the Inbox and has a button to mark it as &amp;quot;Processed&amp;quot;, which removes it from the list.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://disnetdev.com/img/inbox-view.png&quot; alt=&quot;Screenshot of the inbox showing Project BitSockGPT&quot;&gt;&lt;/p&gt;
&lt;p&gt;The Inbox allows you to create a bunch of notes without interrupting your flow to organize immediately. Once you&#39;ve done your initial externalization you can find all the notes you just created in the Inbox and then decide what to do with them later. The Inbox gives you a little routine to make small organizational decisions and prevents notes from falling through the cracks. It gives you confidence to make lots of notes and know that you&#39;ll get back to them when you are ready.&lt;/p&gt;
&lt;p&gt;What I&#39;m trying to accomplish with the design of Flint is the feeling of being confident to externalize. Writing things down should always feel effortless. From knowing where to start writing to feeling confident you&#39;ll be able to organize things later, nothing should slow you down.&lt;/p&gt;
&lt;p&gt;If any of this sounds interesting definitely check out Flint, the beta is now open and you can download it &lt;a href=&quot;https://www.flintnote.com/#download&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>What&#39;s the point of a note-taking app?</title>
		<link href="https://disnetdev.com/blog/2025-11-14-whats-the-point-of-a-note-taking-app/"/>
		<updated>2025-11-14T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2025-11-14-whats-the-point-of-a-note-taking-app/</id>
		<content type="html">&lt;p&gt;Note-taking apps are a bit weird. Most productivity apps you use every day have an obvious and tangible &lt;em&gt;output&lt;/em&gt; that you spend all your time working towards. For example, the point of using Photoshop is to make an image. You spend all your time futzing with an image and eventually you get an image to use somewhere.&lt;/p&gt;
&lt;p&gt;But the notes in a note-taking app are not really an output you directly use. Some people and systems approach them as if they &lt;em&gt;were&lt;/em&gt; the goal  but I think this is a mistake and explains why people often have bad experiences with note-taking apps.&lt;/p&gt;
&lt;p&gt;So if not notes then what are we actually trying to achieve with a note-taking app? In a single phrase: deep learning (for humans, not the &lt;a href=&quot;https://en.wikipedia.org/wiki/Deep_learning&quot;&gt;ML kind&lt;/a&gt;). The output we are looking for is the &lt;strong&gt;mental change&lt;/strong&gt; that occurs via the process of note-taking that deepens our understanding about the things we care about: a topic of interest, ourselves, the world around us. By spending time taking notes we become smarter; our &lt;a href=&quot;https://en.wikipedia.org/wiki/Fluid_and_crystallized_intelligence&quot;&gt;crystallized intelligence&lt;/a&gt; grows.&lt;/p&gt;
&lt;p&gt;This means that a note-taking app is a cognitive tool, not a document manager. Most apps are built as the latter, which I think is why many people struggle with them.&lt;/p&gt;
&lt;p&gt;So if the primary goal of a note-taking app is to deepen our understanding of the things we care about, how do we go about designing for that? Well, first we need to understand how learning works, which I think can be broken down into three main components:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Externalizing&lt;/strong&gt;: Getting ideas out of your head and into a trusted system&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Internalizing&lt;/strong&gt;: Synthesizing what you&#39;ve externalized into new insights and understanding&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Resurfacing&lt;/strong&gt;: Reinforcing your understanding through spaced retrieval and repeated engagement over time&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These three processes feed on each other. Externalizing produces the raw material to internalize which sparks new ideas to be externalized while resurfacing what you&#39;ve externalized and synthesized deepens your understanding and sparks new insights. Without all three you can get stuck. If you don&#39;t externalize, ideas are stuck in your head. If you only externalize, you&#39;re left with a bunch of notes that serve no one. If you don&#39;t resurface and review what you&#39;ve externalized, your understanding is shallow and quickly fades.&lt;/p&gt;
&lt;p&gt;Deep learning requires all three components working together in a virtuous cycle.&lt;/p&gt;
&lt;p&gt;Where things go wrong for most note-taking systems is too much friction with one or more of these components. Friction during externalization keeps thoughts locked in your head. This might be due to an organization system that is too complex (too many options for creating a new note) or too simple (you don&#39;t trust the organizational system to find the note again). If you can&#39;t easily find and connect old notes, you miss the synthesis that deepens understanding. If the system doesn&#39;t support resurfacing those notes over time, your knowledge fades away. Designing a note-taking app around deep learning means minimizing friction at each of these stages.&lt;/p&gt;
&lt;p&gt;While the goal of a good note-taking app should be to minimize the friction of the note-taking process, you can never completely eliminate it because some friction &lt;strong&gt;is&lt;/strong&gt; learning. Having an LLM write your notes for example would be counterproductive, you skip the necessary friction that causes learning to occur. Actual learning requires the friction of articulating vague thoughts into precise language, the friction of recognizing connections between notes, the friction of intentional recall that reinforces and strengthens your memory.&lt;/p&gt;
&lt;p&gt;A well-designed note-taking system minimizes &lt;em&gt;accidental&lt;/em&gt; friction that gets in the way while preserving the productive &lt;em&gt;essential&lt;/em&gt; friction that results in deep learning. It should feel natural and freeing to quickly capture thoughts as they come, knowing the system will help you find, organize, and revisit them later. It should resurface old insights to strengthen your memory and reveal new connections. It should amplify rather than replace your thinking.&lt;/p&gt;
&lt;p&gt;This is the kind of system I&#39;m trying to build with &lt;a href=&quot;https://www.flintnote.com/&quot;&gt;Flint&lt;/a&gt;, which is designed around the idea that note-taking is about deep learning and tries to minimize the accidental friction you encounter by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;using higher level abstractions in the UI than files and folders&lt;/li&gt;
&lt;li&gt;making linking effortless&lt;/li&gt;
&lt;li&gt;using Arc-style tabs that help you organize notes with your spatial memory&lt;/li&gt;
&lt;li&gt;using a LLM agent to help with organization&lt;/li&gt;
&lt;li&gt;using a LLM agent to resurface old notes to cement your memory&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Over the next few weeks, I&#39;ll dive deeper into how Flint&#39;s design reduces friction and contributes to each of the components that enables that deep learning cycle in practice. But the core idea is simple: a good note-taking app should get out of the way while keeping you engaged with the friction that matters.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Introducing Flint</title>
		<link href="https://disnetdev.com/blog/2025-10-10-introducing-flint/"/>
		<updated>2025-10-10T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2025-10-10-introducing-flint/</id>
		<content type="html">&lt;p&gt;&lt;a href=&quot;https://www.flintnote.com/&quot;&gt;Flint&lt;/a&gt; is a new note-taking/thinking-system I’m working on that fixes a lot of the frustrations I’ve had with traditional note-taking apps (or at lest it &lt;em&gt;will try&lt;/em&gt; to fix those frustrations 😅)&lt;/p&gt;
&lt;p&gt;I’ve long been obsessed with note-taking systems in both paper and digital forms because I love the idea of a system that helps me think better.&lt;/p&gt;
&lt;p&gt;At the start of this summer (after &lt;a href=&quot;https://www.disnetdev.com/blog/2025-06-03-new-things/&quot;&gt;freeing up&lt;/a&gt; a bunch of my time) I started &lt;a href=&quot;https://www.disnetdev.com/blog/2025-06-16-mcp-is-neat/&quot;&gt;experimenting&lt;/a&gt; with &lt;a href=&quot;https://www.disnetdev.com/blog/2025-06-30-the-note-taking-trap-why-ai-could-save-or-destroy-how-we-think/&quot;&gt;how&lt;/a&gt; to &lt;a href=&quot;https://www.disnetdev.com/blog/2025-07-02-building-a-personal-gtd-system-in-plain-text-with-ai-agents/&quot;&gt;best&lt;/a&gt; improve my personal note taking system using LLMs. One of the outcomes of those experiments was &lt;a href=&quot;https://github.com/disnet/flint-note-mcp&quot;&gt;flint-note-mcp&lt;/a&gt; an MCP server that gave LLMs the ability to write and manage a directory of structured notes. It was an attempt to see just how far you could push note taking away from a UI. Just chat with any LLM and have the AI write your notes.&lt;/p&gt;
&lt;p&gt;The MCP server was an interesting experiment but ultimately it made me realize two things. First, LLMs are magic and have serious potential but also they have a tendency to take over your thinking, which is the opposite of what you want in a good note-taking system. Second, I really needed a good UI.&lt;/p&gt;
&lt;p&gt;So, I started working on &lt;a href=&quot;https://www.flintnote.com/&quot;&gt;Flint&lt;/a&gt;, an attempt to make a good UI that uses LLMs in a way that won’t harm your thinking.&lt;/p&gt;
&lt;p&gt;I’ll write a bunch more about all of this but the main philosophy behind Flint is this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;You own your notes&lt;/strong&gt;. Flint is plaintext-first. No lock-in and no complex formats that make migrating to a different system a pain. Flint just makes normal markdown files on your hard drive. Eventually I might add an optional sync system but your notes will always start as just normal text files on your computer that you control.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A UI that is humane&lt;/strong&gt;. The UI should surface &lt;em&gt;appropriate abstractions&lt;/em&gt; that respects the way &lt;em&gt;you&lt;/em&gt; think. This means you mange &lt;em&gt;notes&lt;/em&gt; rather than files and folders. The UI should give you a workspace where you can make a mess and also give you tools to clean it up.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Writing is thinking and you do the thinking&lt;/strong&gt;. LLMs are incredible bits of magic but they can easily damage your thinking by automating your writing. Flint will incorporate LLMs and AI agents in a way that allows you to be ambitious with your thinking system without replacing the writing and thinking work that only &lt;em&gt;you&lt;/em&gt; can do.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’ve got a bunch more thinking, writing, and building to do but if this sounds interesting to you, go subscribe to the Flint &lt;a href=&quot;https://buttondown.com/flintnote&quot;&gt;newsletter&lt;/a&gt; where I’ll send out links to the beta when it&#39;s ready. If you have any questions just shoot me an email at &lt;a href=&quot;mailto:tim@flintnote.com&quot;&gt;tim@flintnote.com&lt;/a&gt;.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>GPT-5 Thoughts</title>
		<link href="https://disnetdev.com/blog/2025-08-07-gpt-5-thoughts/"/>
		<updated>2025-08-07T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2025-08-07-gpt-5-thoughts/</id>
		<content type="html">&lt;p&gt;I watched the &lt;a href=&quot;https://www.youtube.com/watch?v=0Uu_VJeVVfo&quot;&gt;OpenAI livestream&lt;/a&gt; introducing GPT-5 today and had some thoughts.&lt;/p&gt;
&lt;p&gt;First, the presentations were all oddly stilted and awkward. Most of the presenters seemed to be mimicking Sam Altman&#39;s affect. It was weird, like I&#39;m not expecting them to be as polished as an Apple keynote (even then Apple has a spectrum of polish) but like maybe they could have done a few more run-throughs?&lt;/p&gt;
&lt;p&gt;Second, they had blindingly obvious errors in some of their graphs. They had a bar chart where 52 was taller than 69, which was the same height as 30. Clear case of automation bias since I&#39;m sure they had GPT-5 check for errors and it didn&#39;t catch it so the humans didn&#39;t either.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://disnetdev.com/img/bad-graph-gpt-5.jpeg&quot; alt=&quot;Really bad graph&quot;&gt;&lt;/p&gt;
&lt;p&gt;Third, one of the demos they had was of GPT-5 explaining the &lt;a href=&quot;https://en.wikipedia.org/wiki/Bernoulli%27s_principle&quot;&gt;Bernoulli principle&lt;/a&gt; in relation to how flight works. It made a web visualization showing how lift is created based on the principle and how air travels over a wing. The wild thing is that the Wikipedia page on the Bernoulli principle calls out how this is a common misconception. Now, maybe the details of the demo were actually correct but it was hard to tell from just watching (Hacker News had a good time &lt;a href=&quot;https://news.ycombinator.com/item?id=44827498&quot;&gt;nerdsnipping themselves&lt;/a&gt; over it). Strange that they went with this example because it&#39;s so fraught with misconceptions and easy to get (subtly) wrong.&lt;/p&gt;
&lt;p&gt;Also, not a huge point, but they kept saying how GPT-5 was like having a PhD in your pocket. As a PhD haver who has worked with plenty of other PhD havers, this is just so funny. Like I get what they are trying to communicate (it&#39;s so smart!) but it&#39;s not nearly as impressive as it sounds (in the same way that &lt;a href=&quot;https://www.youtube.com/watch?v=D4Dd3zAeN-U&quot;&gt;Bruce Banner having 7 PhDs&lt;/a&gt; is supposed to read as smart but is completely absurd). People really need to understand that a PhD does not make you smart.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Building a Personal GTD System in Plain Text with AI Agents</title>
		<link href="https://disnetdev.com/blog/2025-07-02-building-a-personal-gtd-system-in-plain-text-with-ai-agents/"/>
		<updated>2025-07-02T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2025-07-02-building-a-personal-gtd-system-in-plain-text-with-ai-agents/</id>
		<content type="html">&lt;p&gt;I&#39;ve been experimenting with trying to build a plain-text &lt;a href=&quot;https://en.wikipedia.org/wiki/Getting_Things_Done&quot;&gt;GTD&lt;/a&gt; system with &lt;a href=&quot;https://github.com/disnet/flint-note/&quot;&gt;Flint&lt;/a&gt;. I started by just creating a &lt;em&gt;todo&lt;/em&gt; note type with a couple of simple metadata fields (e.g. &lt;em&gt;status&lt;/em&gt;, &lt;em&gt;due date&lt;/em&gt;, etc.) with agent instructions to keep things concise and action-oriented.&lt;/p&gt;
&lt;p&gt;Creating and updating todos then happens conversationally:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Me: make a todo to schedule a dentist appointment today&lt;/p&gt;
&lt;p&gt;Agent: Done.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Later in the day:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Me: mark dentist appointment done&lt;/p&gt;
&lt;p&gt;Agent: Updated.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;My favorite part of this approach is you can then ask the agent &amp;quot;what should I be working on today&amp;quot; and it&#39;s generally smart enough to look through all your todos but also other kinds of notes (daily logs, project notes, etc.) and give you a pretty intelligent response.&lt;/p&gt;
&lt;p&gt;This is fine but gets awkward to update multiple items at a time. What I wanted was a way of seeing and updating multiple todos at a time while still keeping the benefits of text and agent smarts. So I just asked Flint to make me a special note that it would keep in sync:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Me: create a todo note that is special called &amp;quot;today&amp;quot;, it should:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;list all the other todo items that should be worked on today&lt;/li&gt;
&lt;li&gt;format items like &lt;code&gt;- [ ] todo item&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;update agent instructions to update this note when updating other notes&lt;/li&gt;
&lt;li&gt;when the note has items checked off, synchronize with corresponding note status&lt;/li&gt;
&lt;li&gt;have a section called &amp;quot;Quick Add New Tasks&amp;quot; to easily add new items&lt;/li&gt;
&lt;li&gt;each todo should be in one of three states: now (I want to focus on working on it today), upcoming (ready to be worked on soon), someday (a backlog of stuff to plan out eventually)&lt;/li&gt;
&lt;li&gt;the today note should group by status but not show all the someday tasks (just show a count)&lt;/li&gt;
&lt;li&gt;items in the now section should be written like &lt;code&gt;- [ ] + todo item&lt;/code&gt; and items in the upcoming sections are written like &lt;code&gt;- [ ] todo item&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;when syncing the today note look for changes to the + to move items from the now state to the upcoming or vice versa&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Flint then made a &amp;quot;todo&amp;quot; note that looks like this:&lt;/p&gt;
&lt;pre class=&quot;language-markdown&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-markdown&quot;&gt;&lt;span class=&quot;token title important&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;#&lt;/span&gt; Today - [Current Date]&lt;/span&gt;

&lt;span class=&quot;token title important&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;##&lt;/span&gt; NOW (Focus on today) 🎯&lt;/span&gt;
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; [ ] + Finish quarterly report draft
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; [ ] + Review team feedback on project proposal
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; [ ] + Schedule dentist appointment
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; [ ] + Follow up on client contract (OVERDUE)

&lt;span class=&quot;token title important&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;##&lt;/span&gt; UPCOMING (Ready to work on soon) 📋&lt;/span&gt;
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; [ ] Plan next week&#39;s team meeting (Due: Friday)
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; [ ] Update budget spreadsheet (Due: End of month)
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; [ ] Research new project management tools

&lt;span class=&quot;token title important&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;##&lt;/span&gt; Quick Add New Tasks&lt;/span&gt;
&lt;span class=&quot;token italic&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token content&quot;&gt;Add new todo items below - use + for NOW, - for SOMEDAY, no symbol for UPCOMING&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;*&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; [ ]
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; [ ]
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; [ ]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now I can easily check off (e.g. change &lt;code&gt;[ ]&lt;/code&gt; to &lt;code&gt;[x]&lt;/code&gt;) multiple items and then ask Flint to sync the note and it will update each todo note as completed and refresh the today note.&lt;/p&gt;
&lt;p&gt;A day&#39;s interaction could look something like this:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Morning (9:00 AM)&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;User opens Today note, sees:
- [ ] + Write project proposal
- [ ] + Call insurance company
- [ ] Review budget numbers (Due: Thursday)

User adds + symbol to &amp;quot;Review budget numbers&amp;quot;:
- [ ] + Review budget numbers (Due: Thursday)

System automatically:
- Updates individual todo note workflow_state to &amp;quot;now&amp;quot;
- Moves task to NOW section in Today note
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Midday (1:00 PM)&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;User checks off completed task in Today note:
- [x] + Write project proposal ✅

System automatically:
- Updates individual todo note status to &amp;quot;completed&amp;quot;
- Adds completion timestamp
- Moves to &amp;quot;Recently Completed&amp;quot; section
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Evening (6:00 PM)&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;User adds new task to Quick Add section:
- [ ] + Book flight for conference

System automatically:
- Creates new individual todo note: &amp;quot;Book flight for conference&amp;quot;
- Sets workflow_state to &amp;quot;now&amp;quot; (because of + symbol)
- Adds to NOW section in Today note
- Clears the Quick Add entry
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I think this is pretty cool, you can build an approximation of a full-fledged GTD app like &lt;a href=&quot;https://culturedcode.com/things/&quot;&gt;Things&lt;/a&gt; or &lt;a href=&quot;https://www.omnigroup.com/omnifocus&quot;&gt;OmniFocus&lt;/a&gt; in plain text just by writing down a few simple instructions.&lt;/p&gt;
&lt;p&gt;Another neat thing is I built this workflow conversationally. My example above defined the &lt;em&gt;today&lt;/em&gt; note in one instruction but I actually went back and forth with the agent a bunch to narrow down how the today note should best be structured.&lt;/p&gt;
&lt;p&gt;This bidirectional sync between plain text and AI agents feels like a fundamental building block. You get the benefits of structured data and automation while keeping the flexibility and ownership of plain text. I suspect this pattern will be useful beyond task management.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>The Note-Taking Trap - Why AI Could Save (or Destroy) How We Think</title>
		<link href="https://disnetdev.com/blog/2025-06-30-the-note-taking-trap-why-ai-could-save-or-destroy-how-we-think/"/>
		<updated>2025-06-30T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2025-06-30-the-note-taking-trap-why-ai-could-save-or-destroy-how-we-think/</id>
		<content type="html">&lt;p&gt;&lt;strong&gt;Update, October 2025&lt;/strong&gt;: &lt;em&gt;This post introduced an initial experiment with using MCP for note-taking that has morphed into something &lt;a href=&quot;https://www.flintnote.com&quot;&gt;bigger&lt;/a&gt;. Check out &lt;a href=&quot;https://www.disnetdev.com/blog/2025-10-10-introducing-flint/&quot;&gt;this post&lt;/a&gt; for more details.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I&#39;m obsessed with note-taking systems. I&#39;ve been obsessed with them for most of my computer-using life. Evernote, Notion, Roam, Obsidian—each promised to be my &amp;quot;external brain&amp;quot;. I spent hours building out workflows to help me think and act on the things that mattered to me. But inevitably I would hit the same wall when my system became unmanageable and I had to start over from scratch.&lt;/p&gt;
&lt;p&gt;Here&#39;s the problem: your thinking changes. Your projects shift. Your interests expand. But most note-taking systems lock you into structures that become prisons over time. Maybe you organize by project phases—&amp;quot;Research&amp;quot;, &amp;quot;Planning&amp;quot;, &amp;quot;Execution&amp;quot;, &amp;quot;Review&amp;quot;. Then you start working on iterative projects that don&#39;t follow linear phases, and your structure crumbles.&lt;/p&gt;
&lt;p&gt;You either stick with categories that no longer fit, or you &lt;a href=&quot;https://www.joanwestenberg.com/p/i-deleted-my-second-brain&quot;&gt;abandon&lt;/a&gt; the system entirely and start over.&lt;/p&gt;
&lt;p&gt;Now AI promises a solution: just dump everything into a smart assistant and let it handle the thinking for you. Sounds perfect, right?&lt;/p&gt;
&lt;p&gt;Maybe, but I think that approach is dangerous.&lt;/p&gt;
&lt;p&gt;When we fully outsource our thinking to AI, our thinking atrophies. Think about the Google Maps effect: before GPS, we mentally mapped neighborhoods, remembered landmarks, and built spatial reasoning. After GPS, we can&#39;t navigate familiar areas without turn-by-turn directions. The same thing happens with AI-assisted thinking.&lt;/p&gt;
&lt;p&gt;The messy work of organizing ideas, making connections, and structuring knowledge isn&#39;t busy work—it&#39;s how we actually think and learn. Automate that away, and you&#39;re automating away your own intelligence.&lt;/p&gt;
&lt;p&gt;Plus, you&#39;re handing over your most valuable asset—your accumulated knowledge and thinking—to systems you don&#39;t control.&lt;/p&gt;
&lt;p&gt;So here&#39;s what I want: an AI thinking system that I control and that &lt;strong&gt;augments&lt;/strong&gt; my thinking instead of replacing it.&lt;/p&gt;
&lt;p&gt;Instead of throwing everything into an AI void, imagine an agent that works &lt;em&gt;with&lt;/em&gt; you based on &lt;strong&gt;your explicit preferences&lt;/strong&gt; for how you want to think and organize. You tell the system what kinds of notes you work with—daily journals, project logs, book summaries, meeting notes, research captures—and what workflows matter to you: weekly reviews, concept mapping, progressive summarization, or building arguments over time.&lt;/p&gt;
&lt;p&gt;For example, you specify that you keep &amp;quot;insight notes&amp;quot; and &amp;quot;reference notes&amp;quot; separate, and prefer connecting ideas through explicit linking rather than tagging. The AI then notices when you write about &amp;quot;flow state&amp;quot; in an insight note, remembers you mentioned &amp;quot;deep work&amp;quot; in a book reference from 6 months ago and &amp;quot;maker&#39;s schedule&amp;quot; in a meeting capture, then suggests creating a synthesis document that fits your preferred workflow—maybe a new insight note that builds on these connections, or links to add to your existing concept map.&lt;/p&gt;
&lt;p&gt;Or when your project logs increasingly reference the same underlying problems across different domains, the AI suggests a reorganization that aligns with how you actually think—perhaps shifting from department-based folders to problem-solution frameworks, but only because you&#39;ve indicated you prefer outcome-oriented organization over categorical filing.&lt;/p&gt;
&lt;p&gt;The AI handles the friction—the tedious reorganization, automatically tagging notes with concepts and people mentioned, the structural updates—while you focus on the actual thinking. The goal isn&#39;t to eliminate the work of thinking. It&#39;s to eliminate the work that gets in the way of thinking.&lt;/p&gt;
&lt;p&gt;This vision sounds great in theory, but how do you actually build it? The traditional approach would be to create another proprietary platform, which is exactly the kind of lock-in I want to avoid. Instead, we need a way for AI models to work with your note-taking system while keeping your notes completely under your control.&lt;/p&gt;
&lt;h2 id=&quot;mcp-is-neat&quot; tabindex=&quot;-1&quot;&gt;MCP Is Neat &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2025-06-30-the-note-taking-trap-why-ai-could-save-or-destroy-how-we-think/#mcp-is-neat&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is where I think &lt;a href=&quot;https://modelcontextprotocol.io/introduction&quot;&gt;Model Context Protocol&lt;/a&gt; (MCP) unlocks something special. Unlike proprietary systems that lock you into a platform, MCP unlocks the potential for any AI model to work with your data while &lt;em&gt;you&lt;/em&gt; stay in control.&lt;/p&gt;
&lt;p&gt;Consider the difference: In traditional systems, your notes are locked in Notion&#39;s proprietary format. Want to switch to Obsidian? Technically there is an export but the export breaks formatting and loses connections. Company gets &lt;a href=&quot;https://techcrunch.com/2022/11/16/bending-spoons-acquires-evernote-marking-the-end-of-an-era/&quot;&gt;acquired&lt;/a&gt;? Your thinking system disappears.&lt;/p&gt;
&lt;p&gt;With an MCP-enabled system, your notes can just be files in a folder. The AI agent reads and writes through the MCP protocol, but you can switch AI models, sync services, or editing tools without losing anything. Your 10-year+ knowledge base outlasts any single company or platform.&lt;/p&gt;
&lt;p&gt;But unlike traditional file-based systems like Obsidian where you&#39;re on your own for organization, the AI agent becomes your active partner in managing, connecting, and evolving this information.&lt;/p&gt;
&lt;p&gt;This separation of concerns (intelligence versus data storage) enables something that wasn&#39;t possible before: true agent-first design where the AI can be deeply integrated with your thinking process and you control your data.&lt;/p&gt;
&lt;p&gt;This isn&#39;t some distant future vision. It&#39;s what I&#39;m building right now with &lt;a href=&quot;https://github.com/disnet/flint-note/&quot;&gt;Flint Note&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;how-flint-works&quot; tabindex=&quot;-1&quot;&gt;How Flint Works &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2025-06-30-the-note-taking-trap-why-ai-could-save-or-destroy-how-we-think/#how-flint-works&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Flint is an MCP server that organizes your notes as a vault of ordinary markdown files with semantic note types. Each note type defines its purpose, custom agent instructions, and metadata schema. Let me show you how this works in practice by walking through setting up a vault with three common note types.&lt;/p&gt;
&lt;h3 id=&quot;setting-up-your-vault&quot; tabindex=&quot;-1&quot;&gt;Setting Up Your Vault &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2025-06-30-the-note-taking-trap-why-ai-could-save-or-destroy-how-we-think/#setting-up-your-vault&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A vault starts as just a directory of markdown and YAML config files:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;my-notes/
├── .flint-note/
│   └── config.yml
├── daily/
│   └── _description.md
├── todos/
│   └── _description.md
└── reading/
    └── _description.md
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The magic happens when you define what each note type means and how the AI should behave when working with it.&lt;/p&gt;
&lt;h3 id=&quot;creating-note-types-through-conversation&quot; tabindex=&quot;-1&quot;&gt;Creating Note Types Through Conversation &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2025-06-30-the-note-taking-trap-why-ai-could-save-or-destroy-how-we-think/#creating-note-types-through-conversation&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Let&#39;s start by defining our note types:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You: lets create three note types: daily, todo, and reading&lt;/p&gt;
&lt;p&gt;Agent: I&#39;ll create all three note types for you: daily, todo, and reading. Let me set each one up with thoughtful agent instructions and useful metadata schemas.&lt;/p&gt;
&lt;p&gt;[Creates daily/_description.md, todo/_description.md, reading/_description.md]&lt;/p&gt;
&lt;p&gt;Perfect! I&#39;ve created all three note types for your vault:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;📅 Daily (Journal &amp;amp; Reflection)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Purpose&lt;/strong&gt;: Daily journal entries for reflection, planning, and personal growth&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Features&lt;/strong&gt;: Mood tracking, energy levels, gratitude lists, key insights, and tomorrow&#39;s focus&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Agent Behavior&lt;/strong&gt;: Structures entries with morning intentions, daily events, and evening reflection while identifying patterns and celebrating progress&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;✅ Todo (Task Management)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Purpose&lt;/strong&gt;: Task management with priority, deadlines, and progress monitoring&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Features&lt;/strong&gt;: Priority levels, categories, completion tracking, due dates, and project connections&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Agent Behavior&lt;/strong&gt;: Formats tasks as checkboxes, organizes by priority, identifies dependencies, and suggests productivity improvements&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;📚 Reading (Books &amp;amp; Articles)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Purpose&lt;/strong&gt;: Reading notes for books, articles, and other materials with insights and connections&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Features&lt;/strong&gt;: Author tracking, reading status, ratings, key takeaways, and topic organization&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Agent Behavior&lt;/strong&gt;: Structures notes with summaries and key ideas, identifies connections to other materials, and encourages critical thinking&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Your vault is now ready for comprehensive knowledge management! You can start creating notes of any of these types. Just say something like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;quot;Create today&#39;s daily note&amp;quot;&lt;/li&gt;
&lt;li&gt;&amp;quot;Add a todo list for this week&#39;s tasks&amp;quot;&lt;/li&gt;
&lt;li&gt;&amp;quot;I want to create a reading note for [book/article name]&amp;quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What would you like to create first?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The resulting &lt;code&gt;daily/_description.md&lt;/code&gt; looks like this:&lt;/p&gt;
&lt;pre class=&quot;language-markdown&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-markdown&quot;&gt;&lt;span class=&quot;token title important&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;#&lt;/span&gt; Daily&lt;/span&gt;

&lt;span class=&quot;token title important&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;##&lt;/span&gt; Purpose&lt;/span&gt;

Daily journal entries for reflection, planning, and personal
growth tracking

&lt;span class=&quot;token title important&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;##&lt;/span&gt; Agent Instructions&lt;/span&gt;

&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; Structure daily notes with clear sections: Morning
  intentions, daily events, evening reflection
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; Extract and highlight key insights, lessons learned,
  and personal growth moments
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; Identify patterns in mood, energy, productivity,
  and relationships
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; Suggest connections to previous daily entries when
  similar themes emerge
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; Encourage reflection questions: What went well? What
  could be improved? What am I grateful for?
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; Track recurring themes and suggest deeper exploration
  through follow-up questions
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; Notice and celebrate small wins and progress toward
  personal goals
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; When appropriate, suggest creating separate notes for
  significant insights or ideas that emerge

&lt;span class=&quot;token title important&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;##&lt;/span&gt; Metadata Schema&lt;/span&gt;

Expected frontmatter or metadata fields for this note type:

&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token code-snippet code keyword&quot;&gt;`mood`&lt;/span&gt;: Overall mood for the day (optional, select,
  options: [&lt;span class=&quot;token code-snippet code keyword&quot;&gt;`energized`&lt;/span&gt;, &lt;span class=&quot;token code-snippet code keyword&quot;&gt;`content`&lt;/span&gt;, &lt;span class=&quot;token code-snippet code keyword&quot;&gt;`neutral`&lt;/span&gt;, &lt;span class=&quot;token code-snippet code keyword&quot;&gt;`tired`&lt;/span&gt;,
  &lt;span class=&quot;token code-snippet code keyword&quot;&gt;`stressed`&lt;/span&gt;, &lt;span class=&quot;token code-snippet code keyword&quot;&gt;`excited`&lt;/span&gt;, &lt;span class=&quot;token code-snippet code keyword&quot;&gt;`reflective`&lt;/span&gt;, &lt;span class=&quot;token code-snippet code keyword&quot;&gt;`grateful`&lt;/span&gt;])
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token code-snippet code keyword&quot;&gt;`energy_level`&lt;/span&gt;: Energy level (1-10 scale) (optional,
  number, min: 1, max: 10)
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token code-snippet code keyword&quot;&gt;`gratitude`&lt;/span&gt;: Things you&#39;re grateful for today (optional, array)
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token code-snippet code keyword&quot;&gt;`key_events`&lt;/span&gt;: Significant events or moments from the
  day (optional, array)
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token code-snippet code keyword&quot;&gt;`insights`&lt;/span&gt;: Key insights or lessons learned (optional, array)
&lt;span class=&quot;token list punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token code-snippet code keyword&quot;&gt;`tomorrow_focus`&lt;/span&gt;: Main focus or intention for
   tomorrow (optional)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since the description is just a plain text markdown file, you can have the agent update it or edit it yourself with a text editor.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Adding Notes Through Natural Conversation&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Now let&#39;s see the system in action:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You: Add today&#39;s daily note&lt;/p&gt;
&lt;p&gt;Agent: [Creates daily/2025-06-27.md with structured content]&lt;/p&gt;
&lt;p&gt;Perfect! I&#39;ve created your daily note for today, &lt;em&gt;June 27, 2025&lt;/em&gt;. Following the agent instructions for daily notes, I&#39;ve structured it with clear sections to guide your reflection:&lt;/p&gt;
&lt;h2 id=&quot;your-daily-note-structure&quot; tabindex=&quot;-1&quot;&gt;Your Daily Note Structure &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2025-06-30-the-note-taking-trap-why-ai-could-save-or-destroy-how-we-think/#your-daily-note-structure&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Morning Intentions&lt;/strong&gt; (Space to set your focus for the day)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Daily Events&lt;/strong&gt; (Capture key moments, interactions, and accomplishments)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Evening Reflection&lt;/strong&gt; (Process how the day went with guided questions)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gratitude Section&lt;/strong&gt; (Practice appreciation)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Key Insights &amp;amp; Lessons&lt;/strong&gt; (Extract learning and growth moments)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tomorrow&#39;s Focus&lt;/strong&gt; (Set intention for the next day)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The note is ready for you to fill in! As you use it, I&#39;ll help you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Identify patterns in your mood, energy, and productivity&lt;/li&gt;
&lt;li&gt;Connect themes to previous daily entries&lt;/li&gt;
&lt;li&gt;Celebrate your small wins and progress&lt;/li&gt;
&lt;li&gt;Extract insights that might be worth exploring in separate notes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can also add metadata like your mood, energy level (1-10), and specific gratitude items if you&#39;d like more structured tracking. How would you like to start filling it in?&lt;/p&gt;
&lt;p&gt;You: My energy is about a 7, pretty good energy&lt;/p&gt;
&lt;p&gt;Agent: Great! I&#39;ve updated your daily note to capture that energy level of 7. That&#39;s solid energy for the day!&lt;/p&gt;
&lt;p&gt;With that good energy level, it sounds like you&#39;re having a productive day. What&#39;s been contributing to that energy? Any particular events, accomplishments, or moments that have stood out so far today?&lt;/p&gt;
&lt;p&gt;I can help you capture those in the daily events section, or if you&#39;re reflecting on the day, we could work on the evening reflection part. What would you like to add to your daily note?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Adding a reading note:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You: Add a reading note for &amp;quot;The Unaccountability Machine&amp;quot; by Dan Davies. I&#39;ve finished it, here&#39;s a great quote:&lt;/p&gt;
&lt;p&gt;&amp;quot;An organisation does things, and it systematically does some things rather than others. But that&#39;s as far as it goes. Systems don&#39;t make mistakes – if they do something, that&#39;s their purpose.&amp;quot;&lt;/p&gt;
&lt;p&gt;Agent: Excellent! I&#39;ve added that powerful quote and updated your reading note to show you&#39;ve completed the book. That&#39;s a really striking insight – the idea that &amp;quot;systems don&#39;t make mistakes, if they do something, that&#39;s their purpose&amp;quot; cuts right to the heart of how we think about organizational accountability.&lt;/p&gt;
&lt;p&gt;Since you&#39;ve finished the book, I&#39;d love to help you capture more of your insights:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What was the main thesis that resonated most with you?&lt;/li&gt;
&lt;li&gt;How does this quote connect to the broader argument about unaccountability?&lt;/li&gt;
&lt;li&gt;Are there specific examples from the book that illustrate this &amp;quot;systems don&#39;t make mistakes&amp;quot; principle?&lt;/li&gt;
&lt;li&gt;Does this change how you think about organizations you&#39;ve worked with or observed?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This seems like the kind of concept that could warrant its own separate note if it becomes a recurring theme in your thinking about systems and organizations. What other key takeaways stood out to you from the book?&lt;/p&gt;
&lt;p&gt;[Creates reading/the-unaccountability-machine.md with the quote and reading status]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Evolving Your System&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The real power emerges when you want to adapt how the system works:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You: Update my daily notes to also ask about tomorrow&#39;s top priority&lt;/p&gt;
&lt;p&gt;Agent: I&#39;ll modify your daily note instructions to include planning tomorrow&#39;s main focus.&lt;/p&gt;
&lt;p&gt;[Updates daily/_description.md to add tomorrow planning prompt]&lt;/p&gt;
&lt;p&gt;Updated! Now when you create daily notes, I&#39;ll also ask: &amp;quot;What&#39;s your top priority for tomorrow?&amp;quot; This will help bridge your reflection with forward planning.&lt;/p&gt;
&lt;p&gt;You: Actually, make it three priorities, not just one&lt;/p&gt;
&lt;p&gt;Agent: Good adjustment! Three priorities gives you more flexibility while still maintaining focus.&lt;/p&gt;
&lt;p&gt;[Updates the instruction again]&lt;/p&gt;
&lt;p&gt;Done! I&#39;ll now ask for your top three priorities for tomorrow in each daily note.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;The Result: Intelligent, Adaptive Organization&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;What you end up with is a system that understands the different contexts of your thinking:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Daily notes&lt;/strong&gt; become reflective conversations that build self-awareness over time&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Todos&lt;/strong&gt; match tasks to your energy and connect to bigger projects&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reading notes&lt;/strong&gt; capture insights with precision and link to your active work&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But unlike rigid templates, every aspect can evolve through natural conversation. The AI learns your preferences and adapts its behavior, while your data remains simple markdown files you can edit anywhere.&lt;/p&gt;
&lt;p&gt;The system grows with you, becoming more intelligent about your specific needs while keeping your information completely portable and under your control.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why This Matters&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We&#39;re at an inflection point where AI can finally deliver on the vision of an external brain that truly enhances thinking. But only if we&#39;re willing to rethink our assumptions about how knowledge systems should work.&lt;/p&gt;
&lt;p&gt;Most AI-enhanced note apps are still designed for the old world where humans do the organizing and AI occasionally helps out. Flint flips that: the AI is your thinking partner from day one, and the system is designed to make that partnership as natural and powerful and flexible as possible.&lt;/p&gt;
&lt;p&gt;Since all your notes are just markdown files, there&#39;s no lock-in. You can work on your notes with Flint, or fire up &lt;a href=&quot;https://neovim.io/&quot;&gt;vim&lt;/a&gt; or &lt;a href=&quot;https://obsidian.md/&quot;&gt;Obsidian&lt;/a&gt; or &lt;a href=&quot;https://ia.net/writer&quot;&gt;iA Writer&lt;/a&gt; or any other local markdown editor you want. You can sync or backup with whatever file syncing service you already use (git, Dropbox, iCloud, Obsidian Sync, etc.).&lt;/p&gt;
&lt;p&gt;But unlike other markdown-based systems, Flint is architected from the ground up to be agent-first. Every design decision (from the vault structure to the metadata schemas to the conversation patterns) optimizes for AI collaboration rather than human maintenance.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Getting Started&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If this sounds interesting, you can try Flint by adding it to your &lt;a href=&quot;https://github.com/punkpeye/awesome-mcp-clients&quot;&gt;MCP client&lt;/a&gt; of choice. You&#39;ll need &lt;a href=&quot;https://nodejs.org/&quot;&gt;Node.js&lt;/a&gt; installed first:&lt;/p&gt;
&lt;pre class=&quot;language-json&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-json&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;&quot;mcpServers&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;&quot;flint-note&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;command&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;npx&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;&quot;args&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;@flint-note/server@latest&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I&#39;ve also created system prompts to help guide your model&#39;s interactions: &lt;a href=&quot;https://github.com/disnet/flint-note/blob/main/prompts/system_core.md&quot;&gt;system_core.md&lt;/a&gt; for intelligent models like Claude 4 or ChatGPT 4, and &lt;a href=&quot;https://github.com/disnet/flint-note/blob/main/prompts/simple_models_detailed.md&quot;&gt;simple_models_detailed.md&lt;/a&gt; for simpler or local models.&lt;/p&gt;
&lt;p&gt;The project is still early, but if you try it out I&#39;d love to hear what you think. The system is designed to evolve based on how people actually want to interact with their knowledge.&lt;/p&gt;
&lt;p&gt;Check out the &lt;a href=&quot;https://github.com/disnet/flint-note/&quot;&gt;GitHub project&lt;/a&gt; to dive deeper, or just give it a try. The future of knowledge work is agent-first, and Flint is my attempt to build part of that future today.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>MCP is neat</title>
		<link href="https://disnetdev.com/blog/2025-06-16-mcp-is-neat/"/>
		<updated>2025-06-16T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2025-06-16-mcp-is-neat/</id>
		<content type="html">&lt;p&gt;Jotting down an aha! moment I had about how &lt;a href=&quot;https://modelcontextprotocol.io/introduction&quot;&gt;MCP&lt;/a&gt; can augment the utility of LLMs in some of the things I do every day.&lt;/p&gt;
&lt;p&gt;The background is I&#39;ve been trying to be more intentional about committing things to memory using &lt;a href=&quot;https://apps.ankiweb.net/&quot;&gt;Anki&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Spaced_repetition&quot;&gt;spaced repetition&lt;/a&gt;. I was inspired years ago by Michael Nielsen&#39;s &lt;a href=&quot;https://augmentingcognition.com/ltm.html&quot;&gt;article&lt;/a&gt; about using SRS to read and remember ideas from papers so that&#39;s my main goal: commit interesting ideas from papers to memory.&lt;/p&gt;
&lt;p&gt;When I first read that article I tried to build an Anki routine but fell off—the activation energy required to add cards was always too high (also &lt;a href=&quot;https://notes.andymatuschak.org/z2D1qPwddPktBjpNuwYFVva?stackedNotes=zKy4FsHTcf8LdkgXkMueeGL&quot;&gt;writing good prompts is hard&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;LLMs are really good at summarizing and restructuring text so I wondered if they could help with writing Anki cards. I&#39;m not sure if this is the right approach long-term since writing cards by hand would almost certainly aid in the learning process. That said, it turns out I couldn&#39;t sustain the manual effort so I think it&#39;s worth experimenting to see if a different approach could help.&lt;/p&gt;
&lt;p&gt;So my approach is to use an LLM to help write the cards. MCP then lets me easily connect the LLM directly to Anki and even further reduce the activation energy required for authoring cards.&lt;/p&gt;
&lt;p&gt;I&#39;m using &lt;a href=&quot;https://www.raycast.com/&quot;&gt;Raycast&lt;/a&gt;, but the basic idea works in any MCP-capable LLM client (e.g. &lt;a href=&quot;https://claude.ai/download&quot;&gt;Claude desktop&lt;/a&gt;). The MCP server I&#39;m using is &lt;a href=&quot;https://github.com/nailuoGG/anki-mcp-server&quot;&gt;anki-mcp-server&lt;/a&gt;, which requires Anki and the &lt;a href=&quot;https://ankiweb.net/shared/info/2055492159&quot;&gt;AnkiConnect&lt;/a&gt; plugin. Wiring up the Anki MCP server to Raycast is super straightforward and took me all of five minutes.&lt;/p&gt;
&lt;p&gt;For articles, there are a few kinds of prompts that seem to work. If the article is well-known and in the model&#39;s training set, you can simply say:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;suggest some anki cards for the article &amp;quot;As We May Think&amp;quot; by Vannevar Bush&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Claude 4 responds with something like:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Basic Information Cards&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Card 1:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;• &lt;strong&gt;Front:&lt;/strong&gt; Who wrote &amp;quot;As We May Think&amp;quot; and when was it published?&lt;/p&gt;
&lt;p&gt;• &lt;strong&gt;Back:&lt;/strong&gt; Vannevar Bush, published in The Atlantic Monthly in July 1945&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Core Concepts&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Card 2:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;• &lt;strong&gt;Front:&lt;/strong&gt; What is the &amp;quot;Memex&amp;quot; as described by Vannevar Bush?&lt;/p&gt;
&lt;p&gt;• &lt;strong&gt;Back:&lt;/strong&gt; A hypothetical electromechanical device that would store books, records, and communications, allowing users to retrieve and link information through associative trails&lt;/p&gt;
&lt;p&gt;...&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For newer or less well-known articles, you can paste the entire article or a URL (if the model supports web browsing). Not every suggested card will be useful, sometimes the model suggests trivia I don&#39;t care about, but it&#39;s easy to go back and forth with the model to pick the best ones. You can also add some pre-prompt instructions to guide the model toward the kinds of cards that are most helpful, but honestly, it&#39;s quick enough to just pick out the good ones.&lt;/p&gt;
&lt;p&gt;Once I have the cards I like, it’s a simple instruction to add them to Anki:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;now add those cards to @anki&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;(Raycast uses the &lt;code&gt;@&lt;/code&gt; notation to add an MCP server to a chat, but you can also provide it as a chat preset.)&lt;/p&gt;
&lt;p&gt;Raycast also provides a nice feature to wrap commonly used prompts in &lt;a href=&quot;https://manual.raycast.com/ai#block-1cfd6e4a8215812f87f5dbc614adbccf&quot;&gt;AI commands&lt;/a&gt;. For example, I’ve added an “ankify” command with a prompt like:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;from the article in {browser-tab}, suggest some anki cards to help me remember the salient points. when referencing the article use a short version of its title and link to it&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This does what it sounds like: it provides the currently focused browser tab as context to the model. I can then check the suggested cards and follow up by telling it to add them to my Anki deck.&lt;/p&gt;
&lt;p&gt;I think it&#39;s pretty neat that thanks to MCP we can now wire up these powerful capabilities to our LLMs in a matter of minutes.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>New Things</title>
		<link href="https://disnetdev.com/blog/2025-06-03-new-things/"/>
		<updated>2025-06-03T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2025-06-03-new-things/</id>
		<content type="html">&lt;p&gt;Big changes happening in my life. After almost a decade, today was my last day working at Shape Security / F5.&lt;/p&gt;
&lt;p&gt;It was a really good run. I had the chance to work with incredible folks building wild things on the web and I think we make it a little safer and more convenient for everyone.&lt;/p&gt;
&lt;p&gt;Now it&#39;s time for something completely different. Not entirely sure what that is yet but I&#39;ll figure out something fun soon.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Large AI Models Are Cultural and Social Technologies</title>
		<link href="https://disnetdev.com/blog/2025-03-19-large-ai-models-are-cultural-and-social-technologies/"/>
		<updated>2025-03-19T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2025-03-19-large-ai-models-are-cultural-and-social-technologies/</id>
		<content type="html">&lt;p&gt;&lt;a href=&quot;https://www.programmablemutter.com/p/large-ai-models-are-cultural-and&quot;&gt;Large AI Models Are Cultural and Social Technologies&lt;/a&gt;. The way LLMs are often framed is as &amp;quot;intelligent agents&amp;quot; but maybe this is the wrong framing. Rather we should view them as &amp;quot;cultural and social technologies&amp;quot; (like the printing press or markets) that are &amp;quot;allowing humans to take advantage of information other humans have accumulated&amp;quot;.&lt;/p&gt;
&lt;p&gt;Not as snappy or exciting in a science fiction sort of way but more accurate without being dismissive of their impact on society.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Zed Edit Prediction Feature</title>
		<link href="https://disnetdev.com/blog/2025-02-13-zed-edit-prediction-feature/"/>
		<updated>2025-02-13T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2025-02-13-zed-edit-prediction-feature/</id>
		<content type="html">&lt;p&gt;&lt;a href=&quot;https://zed.dev/blog/edit-prediction&quot;&gt;Zed now predicts your next edit with Zeta, our new open model&lt;/a&gt;. Played around with Zed&#39;s edit prediction feature today and it worked surprisly well.&lt;/p&gt;
&lt;p&gt;I like this feature because it sits on the spectrum betwen &amp;quot;just chat with Claude&amp;quot; on the one hand and &amp;quot;describe what Cursor should do&amp;quot; on the other. It augments your process rather than trying to do it entirely.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Hypermedia Controls - From Feral to Formal</title>
		<link href="https://disnetdev.com/blog/2025-01-25-hypermedia-controls-from-feral-to-formal/"/>
		<updated>2025-01-25T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2025-01-25-hypermedia-controls-from-feral-to-formal/</id>
		<content type="html">&lt;p&gt;&lt;a href=&quot;https://dl.acm.org/doi/pdf/10.1145/3648188.3675127&quot;&gt;Hypermedia Controls: From Feral to Formal&lt;/a&gt;. An interesting paper that tries to locate and formalize a set of core primitives in hypermedia systems as expressed in &lt;a href=&quot;https://htmx.org/&quot;&gt;HTMX&lt;/a&gt;. It identifies a &amp;quot;hypermedia control&amp;quot; as consisting of four mechanisms: (1) an element that (2) responds to an event trigger by (3) sending a network request and (4) placing the response in at some position in the viewport. By enhancing a hypermedia system with primitives that allow you to manipulate each of those mechanisms you can declaratively extend the system with your own hypermedia controls.&lt;/p&gt;
&lt;p&gt;An example they give:&lt;/p&gt;
&lt;pre class=&quot;language-html&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;button&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;hx-trigger&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;click&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;hx-post&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;/clicked&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;hx-target&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;#output&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
  Issue a request
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;button&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;output&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;output&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;output&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When the user clicks on the button the system will issue a network request to &lt;code&gt;/clicked&lt;/code&gt; and place the response in the &lt;code&gt;&amp;lt;output id=&amp;quot;output&amp;quot;&amp;gt;&lt;/code&gt; element.&lt;/p&gt;
&lt;p&gt;This is interesting in so far as it goes but I&#39;m not convinced that the &amp;quot;hypermedia maximalist&amp;quot; approach is really all that great of a way to develop systems.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>We&#39;re Getting the Social Media Crisis Wrong</title>
		<link href="https://disnetdev.com/blog/2025-01-16-we-re-getting-the-social-media-crisis-wrong/"/>
		<updated>2025-01-16T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2025-01-16-we-re-getting-the-social-media-crisis-wrong/</id>
		<content type="html">&lt;p&gt;&lt;a href=&quot;https://www.programmablemutter.com/p/were-getting-the-social-media-crisis&quot;&gt;We&#39;re Getting the Social Media Crisis Wrong&lt;/a&gt;. It&#39;s not about misinformation, it&#39;s about groups with collective misunderstandings:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The fundamental problem, as I see it, is not that social media misinforms individuals about what is true or untrue but that it creates publics with malformed collective understandings.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I really like this subtle shift in perspective. It aligns with my distrust of social media as distorting people&#39;s behavior around chasing engagement but he actually identifies a more specific issue:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The more important change is to our beliefs about &lt;em&gt;what other people think&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Our beliefs and opinions about the world are influenced by what we think other people think and social media is a (distorted) machine that tells us what other people think.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Decentralized Systems Aren&#39;t</title>
		<link href="https://disnetdev.com/blog/2025-01-11-decentralized-systems-arent/"/>
		<updated>2025-01-11T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2025-01-11-decentralized-systems-arent/</id>
		<content type="html">&lt;p&gt;&lt;a href=&quot;https://blog.dshr.org/2024/04/decentralized-systems-arent.html&quot;&gt;Decentralized Systems Aren&#39;t&lt;/a&gt;. Centralized systems will always layer on top of decentralized systems unless you figure out how to fix the underlying economic problem of increasing returns to scale.&lt;/p&gt;
&lt;p&gt;To actually get a permissionless decentralized system you need:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a business model that has &lt;em&gt;decreasing&lt;/em&gt; returns to scale&lt;/li&gt;
&lt;li&gt;a way to prevent Sybil attacks without massive cost&lt;/li&gt;
&lt;li&gt;a way to prevent collusion between independent nodes&lt;/li&gt;
&lt;/ul&gt;
</content>
	</entry>
	
	<entry>
		<title>Never Forgive Them</title>
		<link href="https://disnetdev.com/blog/2025-01-07-never-forgive-them/"/>
		<updated>2025-01-07T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2025-01-07-never-forgive-them/</id>
		<content type="html">&lt;p&gt;&lt;a href=&quot;https://www.wheresyoured.at/never-forgive-them/&quot;&gt;Never Forgive Them&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I will never forgive these people for what they’ve done to the computer, and the more I learn about both their intentions and actions the more certain I am that they are unrepentant and that their greed will never be sated. I have watched them take the things that made me human — social networking, digital communities, apps, and the other connecting fabric of our digital lives — and turned them into devices of torture, profitable mechanisms of abuse, and find it disgusting how many reporters seem to believe it&#39;s their responsibility to thank them and explain why it&#39;s good this is happening to their readers.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Last year Ed Zitron became my favorite critic of the tech industry&#39;s rot. He&#39;s incisive and angry and it&#39;s cathartic to read him.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Some Games I Enjoyed In 2024</title>
		<link href="https://disnetdev.com/blog/2025-01-01-some-games-i-enjoyed-in-2024/"/>
		<updated>2025-01-01T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2025-01-01-some-games-i-enjoyed-in-2024/</id>
		<content type="html">&lt;h1 id=&quot;palworld&quot; tabindex=&quot;-1&quot;&gt;Palworld &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2025-01-01-some-games-i-enjoyed-in-2024/#palworld&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Pokemon but with guns.&lt;/p&gt;
&lt;p&gt;Was briefly very into this game. Wrote a bit about it at the &lt;a href=&quot;https://www.disnetdev.com/blog/2024-01-28-division-of-labor-how-palworlds-mechanics-hooked-me/&quot;&gt;time&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Quickly dropped off because it was very early access and those kind of engagement hooks have a very short half-life on me. Might circle back at some point but probably not.&lt;/p&gt;
&lt;h1 id=&quot;final-fantasy-xiv&quot; tabindex=&quot;-1&quot;&gt;Final Fantasy XIV &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2025-01-01-some-games-i-enjoyed-in-2024/#final-fantasy-xiv&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;WoW but make it good.&lt;/p&gt;
&lt;p&gt;I finished the story content up through Endwalker this year and very much enjoyed it. I&#39;d been working through the main story of FF14 off and on since 2021 (got interested in the game off the hype for the initial Endwalker release).&lt;/p&gt;
&lt;p&gt;As much as I enjoyed my time I think I&#39;m done with FF14. The story could be incredibly affecting but working through the MSQ too often felt like a slog.&lt;/p&gt;
&lt;h1 id=&quot;persona-5-royal&quot; tabindex=&quot;-1&quot;&gt;Persona 5 Royal &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2025-01-01-some-games-i-enjoyed-in-2024/#persona-5-royal&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Persona but make it the fifth one.&lt;/p&gt;
&lt;p&gt;I&#39;ve been playing this one off and on for years. Unless it&#39;s an automation game I find it difficult to really stick with a game beyond twenty hours or so and Persona 5 Royal is &lt;strong&gt;much&lt;/strong&gt; longer than that. Finally pushed through to the end and really glad I did.&lt;/p&gt;
&lt;h1 id=&quot;destiny-2-the-final-shape&quot; tabindex=&quot;-1&quot;&gt;Destiny 2: The Final Shape &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2025-01-01-some-games-i-enjoyed-in-2024/#destiny-2-the-final-shape&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Destiny but make it good finally (&lt;a href=&quot;https://www.forbes.com/sites/paultassi/2024/08/01/mass-bungie-layoffs-draw-fury-from-destiny-2-fans-past-and-present-employees/&quot;&gt;finally&lt;/a&gt; 🪦).&lt;/p&gt;
&lt;p&gt;I&#39;ve been a casual Destiny enjoyer off and on ever since D1 came out in 2014 so it was nice to see everything really come together after a decade. I dropped off hard after finishing the campaign though and don&#39;t expect I&#39;ll be coming back.&lt;/p&gt;
&lt;h1 id=&quot;elden-ring-shadow-of-the-erdtree&quot; tabindex=&quot;-1&quot;&gt;Elden Ring: Shadow of the Erdtree &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2025-01-01-some-games-i-enjoyed-in-2024/#elden-ring-shadow-of-the-erdtree&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Elden Ring but even more.&lt;/p&gt;
&lt;p&gt;Consort Radahn was BS. 10/10&lt;/p&gt;
&lt;h1 id=&quot;metaphor-refantazio&quot; tabindex=&quot;-1&quot;&gt;Metaphor ReFantazio &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2025-01-01-some-games-i-enjoyed-in-2024/#metaphor-refantazio&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Persona but make it fantasy and extremely relevant to our current moment.&lt;/p&gt;
&lt;p&gt;Only half way through but having a great time. Has been more consistently compelling to me than Persona 5 (which took forever to finish). Better story pacing, refined job system, and unique world building helps a lot. Also doesn&#39;t hurt that I &amp;quot;get&amp;quot; persona-type games better now after having played a few.&lt;/p&gt;
&lt;h1 id=&quot;factorio-space-age&quot; tabindex=&quot;-1&quot;&gt;Factorio: Space Age &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2025-01-01-some-games-i-enjoyed-in-2024/#factorio-space-age&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Factorio but make it space.&lt;/p&gt;
&lt;p&gt;Automation games in general and factorio in particular are extremely my jam. I&#39;ll be playing this one for a while. I&#39;m taking my time, sixty hours in and I&#39;ve only managed to get to one of the new planets so far (Vulcanus).&lt;/p&gt;
&lt;h1 id=&quot;ufo-50&quot; tabindex=&quot;-1&quot;&gt;UFO 50 &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2025-01-01-some-games-i-enjoyed-in-2024/#ufo-50&quot;&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Retro games but make them modern and alt-history and 50 of them.&lt;/p&gt;
&lt;p&gt;I was surprised how much I enjoyed this since I&#39;m not usually much of a retro gamer. My nostalgia goggles aren&#39;t corrective enough to look past the frustrating game designs of the past.&lt;/p&gt;
&lt;p&gt;But modern game designers interpreting the games of old through the conceit of alt-history works really well. While a few of the games in the collection are intentionally frustrating in the style of actual 80s games, most are a clever injection of modern sensibilities under 8-bit constraints. Party House, Pilot Quest, Campanella 2, Rail Heist, and Avianos are particular standouts for me.​​​​​​​​​​​​​​​​&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Don&#39;t Get Burned</title>
		<link href="https://disnetdev.com/blog/2024-12-31-dont-get-burned/"/>
		<updated>2024-12-31T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2024-12-31-dont-get-burned/</id>
		<content type="html">&lt;p&gt;&lt;a href=&quot;https://chrisholdgraf.com/blog/2024/bluesky&quot;&gt;How I’m Trying to Use BlueSky Without Getting Burned Again&lt;/a&gt;. I really like the principle of assuming the platform/service you are using will go away in three years. That&#39;s a long enough timeline to derive value without overcommitting.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Some of the Apps I used in 2024</title>
		<link href="https://disnetdev.com/blog/2024-12-31-some-of-the-apps-i-used-in-2024/"/>
		<updated>2024-12-31T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2024-12-31-some-of-the-apps-i-used-in-2024/</id>
		<content type="html">&lt;p&gt;&lt;strong&gt;Browser&lt;/strong&gt;: &lt;a href=&quot;https://arc.net/&quot;&gt;Arc&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Still a transformative browser UX but I&#39;m worried about its future considering their recent pivot to a new &amp;quot;AI first&amp;quot; browser. We&#39;ll see how things go in 2025.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Notes&lt;/strong&gt;: &lt;a href=&quot;https://obsidian.md/&quot;&gt;Obsidian&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Continues to &lt;a href=&quot;https://www.disnetdev.com/blog/2023-07-09-using-obsidian/&quot;&gt;run my life&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Read it Later&lt;/strong&gt;: &lt;a href=&quot;https://readwise.io/read&quot;&gt;Readwise Reader&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Still the best thing ever. I have highlights sync to Obsidian, which is the best thing ever.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Task Management&lt;/strong&gt;: &lt;a href=&quot;https://www.omnigroup.com/omnifocus/&quot;&gt;OmniFocus&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I tried to switch to Things last year but it didn&#39;t stick. Back to OmniFocus and it&#39;s great although the v4 update was a bit rough but it&#39;s mostly evened out now.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Code Editor&lt;/strong&gt;: &lt;a href=&quot;https://zed.dev/&quot;&gt;Zed&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Zed is incredible. Fast, great VIM mode, AI integration is great (though I need to check out &lt;a href=&quot;https://www.cursor.com/&quot;&gt;Cursor&lt;/a&gt; at some point too).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AI Assistant&lt;/strong&gt;: &lt;a href=&quot;https://claude.ai/&quot;&gt;Claude&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This was the year I started to actually get productive with AI assistants. They aren’t always good but when they are they really are. I mostly use Claude at this point though I don’t really do extensive comparisons.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Launcher&lt;/strong&gt;: &lt;a href=&quot;https://www.raycast.com/&quot;&gt;Raycast&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A bunch of my one-off AI assistants use is actually via Raycast. Super helpful to have it always a keystroke away.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Calendar&lt;/strong&gt;: &lt;a href=&quot;https://flexibits.com/fantastical&quot;&gt;Fantastical&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Continues to be great.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Podcasts&lt;/strong&gt;: &lt;a href=&quot;https://overcast.fm/&quot;&gt;Overcast&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Continues to be great&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Email&lt;/strong&gt;: Mail.app&lt;/p&gt;
&lt;p&gt;Boring but I’ve come around on that being what I like out of email.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Finance&lt;/strong&gt;: &lt;a href=&quot;https://www.ynab.com/&quot;&gt;YNAB&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Continues to be great.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>AI Scaling Myths</title>
		<link href="https://disnetdev.com/blog/2024-12-29-ai-scaling-myths/"/>
		<updated>2024-12-29T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2024-12-29-ai-scaling-myths/</id>
		<content type="html">&lt;p&gt;&lt;a href=&quot;https://www.aisnakeoil.com/p/ai-scaling-myths&quot;&gt;AI Scaling Myths&lt;/a&gt;. As 2024 went on, more and more AI discourse started to come around to the idea that AI scaling was probably about to end. One things I learned from this article is that &amp;quot;scaling laws&amp;quot; have a more precise meaning than what I&#39;d known.&lt;/p&gt;
&lt;p&gt;I had a general understanding of &amp;quot;scaling laws&amp;quot; to mean that the bigger the model the more &amp;quot;capabilities&amp;quot; were supposed to pop out. But the original meaning in AI research is about the &amp;quot;decrease in perplexity&amp;quot; (&lt;a href=&quot;https://en.wikipedia.org/wiki/Perplexity&quot;&gt;perplexity&lt;/a&gt; being jargon I also learned from this article meaning a measure of word prediction uncertainty). A decrease in perplexity is not quite the same thing as new capabilities.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Division of Labor: How Palworld&#39;s Mechanics Hooked Me</title>
		<link href="https://disnetdev.com/blog/2024-01-28-division-of-labor-how-palworlds-mechanics-hooked-me/"/>
		<updated>2024-01-28T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2024-01-28-division-of-labor-how-palworlds-mechanics-hooked-me/</id>
		<content type="html">&lt;p&gt;I&#39;ve been playing a bunch of &lt;a href=&quot;https://www.pocketpair.jp/palworld&quot;&gt;Palworld&lt;/a&gt; recently (along with &lt;a href=&quot;https://www.ign.com/articles/palworld-has-huge-weekend-sells-5-million-and-overtakes-cyberpunk-2077-in-steams-most-played-games-list&quot;&gt;everyone else apparently&lt;/a&gt;) and been having a great time. It&#39;s open-world survival crafting (think Valheim) mixed with monster collecting (Pokémon) mixed with some very light (at least in the first ten or so hours, might get more complicated later) automation (a little bit of Satisfactory).&lt;/p&gt;
&lt;p&gt;I&#39;m a little surprised how much it has hooked me since I&#39;ve always bounced off the survival crafting and monster collecting genres. I understand their appeal but the tedium inherent in both have been too much for me (also the combat in Pokémon just straight up sucks, don&#39;t @ me). That said, I&#39;ve sunk hundreds of hours into automation games (every few months I circle back to either Satisfactory, Factorio, or Dyson Sphere Program), and those games definitely have plenty of tedium baked into their design.&lt;/p&gt;
&lt;p&gt;So what makes Palworld click for me?&lt;/p&gt;
&lt;p&gt;I think the key is the way that Palworld uses monster collecting to relieve the survival crafting tedium. The pals you collect are not just used in combat, you put them to work in your base to gather resources and craft items. The tedium is a motivator to find new and better Pals. There is a virtuous cycle at work here; you collect Pals to build a better base and craft better items that you use to find better Pals that you use to build a better base and so on.&lt;/p&gt;
&lt;p&gt;This ever-building cycle is exactly the hook that pulls me so deep into automation games, the initial tedium is a motivator to build more complicated factories that you use to build yet more complicated factories and so on.&lt;/p&gt;
&lt;p&gt;I&#39;m only ten or so hours into Palworld so I&#39;m curious to see if its hook can sustain itself to an endgame. I suspect not, automation games have another endgame hook that Palworld seems to be missing: player expression. As you build out more complicated factories in a game like Satisfactory the player expresses their design sensibilities in their builds (how they prioritize aesthetics, compactness, modularity, etc.). At least so far, I don&#39;t see an equivalent space for player expression in Palworld (I&#39;m not counting base building because it&#39;s not tied back into the core mechanics, bases are mostly cosmetic).&lt;/p&gt;
&lt;p&gt;In any case, Palworld is very enjoyable and I&#39;m interested to see how it unfolds both as I play more of it and as the developers evolve it during the early access period.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Neat simple LLM use for text manipulation</title>
		<link href="https://disnetdev.com/blog/2024-01-06-neat-simple-llm-use-for-text-manipulation/"/>
		<updated>2024-01-06T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2024-01-06-neat-simple-llm-use-for-text-manipulation/</id>
		<content type="html">&lt;p&gt;I had a neat little interaction with an LLM this week where I had a markdown note in Obsidian I wanted to convert some of its formatting. The note had a bunch of external markdown links:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;- [Note1](app://obsidian.md/path/to/Note1)
- [Note2](app://obsidian.md/path/to/Note2)
- ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;that I wanted to convert to internal links:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;- [[Note1]]
- [[Note2]]
- ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Previously to do this I&#39;d either reach for something like a &lt;a href=&quot;https://vim.fandom.com/wiki/Macros&quot;&gt;vim macro&lt;/a&gt; or write a little regex. Realistically for most cases the activation energy would be too much and I&#39;d just not do the reformatting at all.&lt;/p&gt;
&lt;p&gt;But with a LLM (in this case I used the &lt;a href=&quot;https://text-gen.com/&quot;&gt;TextGen&lt;/a&gt; plugin) you can just show an example and tell the LLM to do it and it just works. The prompt was something like&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;- [Note1](app://obsidian.md/path/to/Note1)
- [Note2](app://obsidian.md/path/to/Note2)
- ...

---

convert the list above from `[Note](path/to/Note)` to `[[Note]]`
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&#39;s pretty cool that we basically get a kind of &lt;a href=&quot;https://en.wikipedia.org/wiki/Programming_by_example&quot;&gt;programming by example&lt;/a&gt; for &amp;quot;free&amp;quot; with LLMs.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Some of the Apps I used in 2023</title>
		<link href="https://disnetdev.com/blog/2023-12-26-some-of-the-apps-i-used-in-2023/"/>
		<updated>2023-12-26T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2023-12-26-some-of-the-apps-i-used-in-2023/</id>
		<content type="html">&lt;ul&gt;
&lt;li&gt;Browser: &lt;a href=&quot;https://arc.net/&quot;&gt;Arc&lt;/a&gt; (it&#39;s soooo good, love the clever rethinking of tabs)&lt;/li&gt;
&lt;li&gt;Notes: &lt;a href=&quot;https://obsidian.md/&quot;&gt;Obsidian&lt;/a&gt; (it&#39;s now &lt;a href=&quot;https://www.disnetdev.com/blog/2023-07-09-using-obsidian/&quot;&gt;running my life&lt;/a&gt;, so so good. I&#39;d tried so many solutions over the years, this one is really sticking)&lt;/li&gt;
&lt;li&gt;Read it later: &lt;a href=&quot;https://readwise.io/read&quot;&gt;Readwise Reader&lt;/a&gt; (basically what I&#39;ve wanted for years, captures everything, handles article processing workflows like I want, syncs highlights to Obsidian)&lt;/li&gt;
&lt;li&gt;Task Management: &lt;a href=&quot;https://culturedcode.com/things/&quot;&gt;Things&lt;/a&gt; (switched from OmniFocus after &amp;gt; 10 years, OF 4 was not sparking joy)&lt;/li&gt;
&lt;li&gt;Code: &lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;VS Code&lt;/a&gt; (meh, it&#39;s fine)&lt;/li&gt;
&lt;li&gt;LLM for coding: &lt;a href=&quot;https://github.com/features/copilot&quot;&gt;Copilot&lt;/a&gt; (I find it hit or miss, but scary neat when it hits)&lt;/li&gt;
&lt;li&gt;Task Launcher: &lt;a href=&quot;https://www.raycast.com/&quot;&gt;Raycast&lt;/a&gt; (its ChatGPT integration is pretty great)&lt;/li&gt;
&lt;li&gt;Mastodon Client: &lt;a href=&quot;https://tapbots.com/ivory/&quot;&gt;Ivory&lt;/a&gt; (for iPhone, love the feel) and &lt;a href=&quot;https://elk.zone/&quot;&gt;Elk&lt;/a&gt; (for desktop Web, love the threading of conversations)&lt;/li&gt;
&lt;li&gt;Calendar: &lt;a href=&quot;https://flexibits.com/fantastical&quot;&gt;Fantastical&lt;/a&gt; (continues to be great)&lt;/li&gt;
&lt;li&gt;Podcasts: &lt;a href=&quot;https://overcast.fm/&quot;&gt;Overcast&lt;/a&gt; (continues to be great)&lt;/li&gt;
&lt;li&gt;Email: &lt;a href=&quot;https://app.fastmail.com/&quot;&gt;Fastmail&lt;/a&gt; (great, starting to move from gmail), &lt;a href=&quot;https://sparkmailapp.com/&quot;&gt;Spark&lt;/a&gt; (meh, slightly better than Mail.app)&lt;/li&gt;
&lt;li&gt;Finance: &lt;a href=&quot;https://www.ynab.com/&quot;&gt;YNAB&lt;/a&gt; (continues to be great)&lt;/li&gt;
&lt;li&gt;RSS Reader: &lt;a href=&quot;https://feedbin.com/&quot;&gt;Feedbin&lt;/a&gt; and &lt;a href=&quot;https://netnewswire.com/&quot;&gt;NetNewsWire&lt;/a&gt; (good apps but my RSS consumption is sporadic)&lt;/li&gt;
&lt;/ul&gt;
</content>
	</entry>
	
	<entry>
		<title>Using Obsidian with Readwise, dataview, and periodic notes</title>
		<link href="https://disnetdev.com/blog/2023-07-09-using-obsidian-with-readwise-dataview-and-periodic-notes/"/>
		<updated>2023-07-09T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2023-07-09-using-obsidian-with-readwise-dataview-and-periodic-notes/</id>
		<content type="html">&lt;p&gt;This is a writeup of how I use &lt;a href=&quot;https://obsidian.md/&quot;&gt;Obsidian&lt;/a&gt; to organize my personal knowledge base (PKB).&lt;/p&gt;
&lt;p&gt;My goal in building out a PKB is to capture and reflect on the most relevant thoughts, ideas, and events in my life. I&#39;ve tried a bunch of different tools over the years and have found that it is critical to decide on the right level of structure to impose. Too much structure is overwhelming and nothing gets written down. Too little structure leads to sprawling write-once read-never snake nests.&lt;/p&gt;
&lt;p&gt;As a disclaimer, PKBs are very, well, &lt;em&gt;personal&lt;/em&gt; so this approach might not work for you.&lt;/p&gt;
&lt;p&gt;At a high level, the kinds of notes I use are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;project notes
&lt;ul&gt;
&lt;li&gt;notes to collect links, ideas, and brainstorms about a particular project&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://notes.andymatuschak.org/Evergreen_notes&quot;&gt;evergreen&lt;/a&gt; notes
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Chunking_(psychology)&quot;&gt;chunked concepts&lt;/a&gt; that I find particularly relevant (e.g. &amp;quot;Beware of automation bias&amp;quot;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;daily, weekly, and quarterly notes
&lt;ul&gt;
&lt;li&gt;the focus for this post&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On any given day I use a &lt;em&gt;daily note&lt;/em&gt; to capture whatever comes up. Daily notes serve as a kind of scratchpad to capture random thoughts, drafts of other documents, and any other bits of ephemera.&lt;/p&gt;
&lt;p&gt;The only structure I impose in a daily note is for capturing meeting notes where I&#39;ll use a heading and link to the related project or person. For example, a 1/1 meeting will have a heading like &lt;code&gt;# [[Person Name]] 1/1&lt;/code&gt;. The links in the heading to &lt;code&gt;[[Person Name]]&lt;/code&gt; provide backlinks so that in the future I can quickly see all the topics we&#39;ve covered.&lt;/p&gt;
&lt;p&gt;For a while I tried to get by with just the daily note level of structure but it wasn&#39;t enough. It was too easy for something I wrote in a daily note to get lost. I needed a structured way to reflect on a longer timeline than a day.&lt;/p&gt;
&lt;p&gt;So, I use the &lt;a href=&quot;https://github.com/liamcain/obsidian-periodic-notes/&quot;&gt;periodic notes&lt;/a&gt; plugin to create both weekly and quarterly notes.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;weekly note&lt;/em&gt; is more structured than a daily note and I use a template to fill in headings that I expand on throughout the week.&lt;/p&gt;
&lt;p&gt;The first section is for reflection on how the week went. It uses a retro format I&#39;ve used for years at work with simple &amp;quot;happy&amp;quot; and &amp;quot;sad&amp;quot; sections.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Reflect

## Happy

- good progress on [[Project X]]
- three day weekend!

## Sad

- [[Twitter]] is at it again
- stalled discussion on [[Project Y]]
    - need to follow up with [[John Smith]]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The next section is to track the media I consumed that week. Any movies, shows, or games.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Media Consumed

- [[Silo]]
- [[Factorio]]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I don&#39;t bother rating or writing down much else since the point is just to remember what and when I encountered various bits of media.&lt;/p&gt;
&lt;p&gt;The final section is the Readwise highlights from the week. I use &lt;a href=&quot;https://readwise.io/read&quot;&gt;Readwise Reader&lt;/a&gt; for almost all my reading so when I make a highlight in Reader it gets automatically synced to Obsidian via the &lt;a href=&quot;https://github.com/readwiseio/obsidian-readwise&quot;&gt;Readwise plugin&lt;/a&gt;. Having highlights synced is great for preservation but realistically I never looked at them again (outside of the Readwise spaced repetition emails). What I wanted was a way to see my recent highlights and have a chance to reflect on them again.&lt;/p&gt;
&lt;p&gt;Enter the &lt;a href=&quot;https://github.com/blacksmithgu/obsidian-dataview&quot;&gt;dataview&lt;/a&gt; plugin:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;list
 from &amp;quot;Readwise&amp;quot;
 where
  file.ctime &amp;gt; date(&amp;quot;{{date:YYYY-MM-DD}}&amp;quot;)
  and file.ctime &amp;lt; date(&amp;quot;{{date:YYYY-MM-DD}}&amp;quot;) + dur(7 day)
sort file.ctime
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That query pulls back a list of all the Readwise notes created during the week. At the end of the week I look over them and create any &lt;a href=&quot;https://notes.andymatuschak.org/Evergreen_notes&quot;&gt;evergreen notes&lt;/a&gt; that might make sense.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;quarterly notes&lt;/em&gt; are similar to weekly notes but with a few more sections to encourage me to reflect a bit deeper.&lt;/p&gt;
&lt;p&gt;Quarter notes start with a Happy/Sad reflection section just like weekly notes however this isn&#39;t meant to be inclusive of all the reflections from every week, just the most salient items from the quarter.&lt;/p&gt;
&lt;p&gt;The other sections are aspects of my life that I want to spend time reflecting on and should be fairly self-explanatory:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Life Events&lt;/li&gt;
&lt;li&gt;Professional Events&lt;/li&gt;
&lt;li&gt;Tech Events&lt;/li&gt;
&lt;li&gt;World Events&lt;/li&gt;
&lt;li&gt;Media Consumed&lt;/li&gt;
&lt;li&gt;Health&lt;/li&gt;
&lt;li&gt;Finances&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I try to spend a bit more time on each of these sections than I would in a weekly note, writing full sentences and paragraphs rather than just listing out bullet points.&lt;/p&gt;
&lt;p&gt;So the way I use my PKB is essentially jotting down whatever is happening in the moment in a daily note, on the weekend filling out the weekly note and reflecting on highlights from that week, and then at the end of the quarter spending a bit more time reflecting on what happened in a number of different areas over the past few months.&lt;/p&gt;
&lt;p&gt;I&#39;ve struggled over the years trying to find the right cadence and tools to effectively capture and reflect on my &amp;quot;personal knowledge&amp;quot;, but this combination of daily, weekly, and quarterly notes has been working pretty well for me so far.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Announcing ParserLang</title>
		<link href="https://disnetdev.com/blog/2019-06-30-announcing-parserlang/"/>
		<updated>2019-06-30T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2019-06-30-announcing-parserlang/</id>
		<content type="html">&lt;p&gt;I&#39;m excited to announce a new project I&#39;ve been working on called &lt;a href=&quot;https://github.com/disnet/parser-lang&quot;&gt;ParserLang&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;🎉🎉🎉&lt;/p&gt;
&lt;p&gt;ParserLang is a parser combinator library for JavaScript with declarative superpowers. In addition to defining parsers in JavaScript, ParserLang allows you to use declarative syntax via template literals:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; lang &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;parser-lang&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; calc &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; lang&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
  num = /[0-9]+/ &gt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;ch&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;parseInt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ch&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;;

  addExpr = num &#39;+&#39; multExpr &gt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;left&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; op&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; right&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; left &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; right&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
          | num ;

  multExpr = addExpr &#39;*&#39; multExpr &gt; &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;left&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; op&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; right&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; left &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; right&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;
           | addExpr ;
  
  calc = multExpr ;
&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

calc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;tryParse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;1+1*2&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 3&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A thing that has surprised me about JavaScript in the post-ES2015 era is how few projects have made use of tagged template literals even though they are incredibly powerful. This is my attempt to rectify that situation.&lt;/p&gt;
&lt;p&gt;More details in the &lt;a href=&quot;https://github.com/disnet/parser-lang#documentation&quot;&gt;documentation&lt;/a&gt;.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Sweetening syntactic abstractions</title>
		<link href="https://disnetdev.com/blog/2017-04-09-sweetening-syntactic-abstractions/"/>
		<updated>2017-04-09T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2017-04-09-sweetening-syntactic-abstractions/</id>
		<content type="html">&lt;p&gt;Version 3.0 of &lt;a href=&quot;http://sweetjs.org&quot;&gt;Sweet.js&lt;/a&gt; has just been released! 🎉&lt;/p&gt;
&lt;p&gt;To set expectations, keep in mind that I consider Sweet to still be an experiment and under heavy work. The version number is a reflection of semver (we&#39;ve made breaking changes) not project maturity. Since the big &lt;a href=&quot;https://medium.com/@disnet/announcing-sweet-js-1-0-e7f4f3e15594&quot;&gt;redesign&lt;/a&gt; last year tons of progress has been made, but I expect at least one or two more breaking changes (major version bumps) before things start to get baked and really ready to use. That said, if you are excited about the idea of true syntactic abstractions in JavaScript please dive in!&lt;/p&gt;
&lt;p&gt;So what&#39;s new?&lt;/p&gt;
&lt;h2 id=&quot;custom-operators&quot; tabindex=&quot;-1&quot;&gt;Custom Operators &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2017-04-09-sweetening-syntactic-abstractions/#custom-operators&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Custom operators are back! In the old pre-1.0 days we had the ability to define new operators with custom precedence and associativity but it was dropped in the redesign.&lt;/p&gt;
&lt;p&gt;Operators are defined with the new &lt;code&gt;operator&lt;/code&gt; keyword:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;operator &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;=&lt;/span&gt; left &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;left&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; right&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; #&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;left&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;.then(&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;right&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/foo.json&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;resp&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; resp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                   &lt;span class=&quot;token operator&quot;&gt;&gt;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;json&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;processJson&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;json&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That expands to:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token function&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;/foo.json&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resp&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; resp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;json&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;processJson&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;json&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The implementation of custom operators is pretty experimental at the moment but give it a whirl and let us know if you run into any problems. More details are in the &lt;a href=&quot;http://sweetjs.org/doc/1.0/tutorial.html&quot;&gt;tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Note: the technical underpinnings for custom operators comes out of Jon Rafkind&#39;s dissertation on the &lt;a href=&quot;https://www.cs.utah.edu/~rafkind/papers/dissertation.pdf&quot;&gt;Honu&lt;/a&gt; language.&lt;/p&gt;
&lt;h2 id=&quot;modules&quot; tabindex=&quot;-1&quot;&gt;Modules &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2017-04-09-sweetening-syntactic-abstractions/#modules&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We&#39;ve been steadily adding ES module support over the past few releases. The interaction between macros and modules is fairly complex so this is an ongoing process.&lt;/p&gt;
&lt;p&gt;We currently have the ability to import macros from another module:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// foo.js&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&#39;lang sweet.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; syntax m &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// main.js&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&#39;lang sweet.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; m &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;./foo&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

m &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note the use of the &lt;code&gt;&#39;lang sweet.js&#39;&lt;/code&gt; directives. These directives are currently required in any module that uses macros. It allows the Sweet compiler to avoid needlessly expanding modules that don&#39;t contain any macros. At present the directive is &amp;quot;just&amp;quot; an optimization but soon we&#39;ll be using it for some pretty cool stuff.&lt;/p&gt;
&lt;p&gt;You can now also import modules into compiletime code (macro definitions) by using the &lt;code&gt;for syntax&lt;/code&gt; form of &lt;code&gt;import&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// log.js&lt;/span&gt;
&lt;span class=&quot;token string&quot;&gt;&#39;lang sweet.js&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// main.js&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; log &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;./log.js&#39;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; syntax&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

syntax &lt;span class=&quot;token function-variable function&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;ctx&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;doing some Sweet things&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We&#39;re taking the Racket approach of dividing everything up into &lt;em&gt;phases&lt;/em&gt;. Runtime syntax is in phase 0 and compiletime macro definitions are in phase 1. Importing &lt;code&gt;for syntax&lt;/code&gt; allows you to phase shift your code around. Phases greater than phase 1 happen when you import &lt;code&gt;for syntax&lt;/code&gt; a macro that uses another macro that was imported &lt;code&gt;for syntax&lt;/code&gt;. This gives rise to an infinite &amp;quot;tower of phases&amp;quot; which sounds complicated but turns out to be pretty straightforward in practice.&lt;/p&gt;
&lt;p&gt;Still to come are better support for implicit runtime imports, finer grain support for phases that let you import for a specific phase, and an equivalent to Racket&#39;s &lt;code&gt;begin-for-syntax&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Note: the technical underpinnings of modules and macros comes out of the Racket approach set forward by Matthew Flatt in his &lt;a href=&quot;https://www.cs.utah.edu/plt/publications/macromod.pdf&quot;&gt;&amp;quot;You want it &lt;em&gt;when&lt;/em&gt;?&amp;quot;&lt;/a&gt; paper.&lt;/p&gt;
&lt;h2 id=&quot;readtables&quot; tabindex=&quot;-1&quot;&gt;Readtables &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2017-04-09-sweetening-syntactic-abstractions/#readtables&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;While macros allow you to extend how syntax is parsed, sometimes you also need to extend how source text is lexed. The lexing extension approach we are taking is called &lt;em&gt;readtables&lt;/em&gt; and &lt;a href=&quot;https://twitter.com/gabeijohnson&quot;&gt;@gabejohnson&lt;/a&gt; has been doing some amazing design and implementation work. Sweet now uses readtables internally and will soon be exposing them to users.&lt;/p&gt;
&lt;h2 id=&quot;internals-and-helpers&quot; tabindex=&quot;-1&quot;&gt;Internals and helpers &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2017-04-09-sweetening-syntactic-abstractions/#internals-and-helpers&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;During expansion Sweet constructs several intermediate representations of syntax that can be manipulated and eventually turned into a &lt;a href=&quot;http://shift-ast.org/&quot;&gt;Shift AST&lt;/a&gt;.
The exact representation we want to use is under flux but unfortunately it is exposed to macro authors inside macro definitions.
Exposing what should be internal details is bad so to move away from that Sweet now provides a helper library for macro authors:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;H&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;sweet.js/helpers&#39;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; syntax&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

syntax &lt;span class=&quot;token function-variable function&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token parameter&quot;&gt;ctx&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; v &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ctx&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;H&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isIdentifier&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;v&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;foo&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;H&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fromString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;v&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;bar&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;H&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fromString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;v&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;baz&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
m foo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// expands to &#39;bar&#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Macro authors should only use the helper library to inspect and manipulate syntax objects rather than rely on the current representation of syntax. Eventually we will document and freeze a intermediate syntax representation but until then just use the helpers.&lt;/p&gt;
&lt;h2 id=&quot;whats-next&quot; tabindex=&quot;-1&quot;&gt;What&#39;s next? &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2017-04-09-sweetening-syntactic-abstractions/#whats-next&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The current plan is to get Sweet to a solid and stable place where we can start building declarative conveniences on top its foundation. In particular, the current macro definition syntax is intentionally low-level and not convenient to work in. We&#39;ve got some &lt;a href=&quot;https://github.com/sweet-js/sweet.js/issues/516&quot;&gt;ideas&lt;/a&gt; about what this might look like but first we&#39;re going to make sure the base is solid.&lt;/p&gt;
&lt;p&gt;If any of this excites you, please &lt;a href=&quot;https://github.com/sweet-js/sweet.js&quot;&gt;jump in&lt;/a&gt;! We&#39;d love to have you!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Announcing Sweet.js 1.0</title>
		<link href="https://disnetdev.com/blog/2016-03-28-announcing-sweet-js-1-0/"/>
		<updated>2016-03-28T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2016-03-28-announcing-sweet-js-1-0/</id>
		<content type="html">&lt;p&gt;Sweet.js, the hygienic macro system for JavaScript, just got a shiny new release: the magical 1.0! 🎉&lt;/p&gt;
&lt;p&gt;If you’ve been following the development of Sweet for a while you might have noticed a dearth of activity. Part of that was life (I recently finished grad school and started a new job) but part of that seeming lack of activity was actually a giant rewrite in progress.&lt;/p&gt;
&lt;p&gt;Yes I know, &lt;a href=&quot;http://www.joelonsoftware.com/articles/fog0000000069.html&quot;&gt;that’s a thing you should never do&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But I swear it made sense this time. The collection of bad decisions I made early in development had finally made forward progress all but impossible. And so, Sweet has been completely rewritten.&lt;/p&gt;
&lt;p&gt;So what’s good about the rewrite? Lot’s of stuff, but two I want to call out specifically here.&lt;/p&gt;
&lt;p&gt;First, a proper parser is now integrated in the expansion pipeline. Previously, Sweet had a half-baked pseudo-parser that kinda-sorta built up an AST during expansion and then immediately flattened it back to tokens to let our crazy fork of &lt;a href=&quot;http://esprima.org/&quot;&gt;esprima&lt;/a&gt; build up a proper AST before doing codegen.&lt;/p&gt;
&lt;p&gt;Yeah, totes reasonable.&lt;/p&gt;
&lt;p&gt;This insane pipeline had tons of bugs especially related to proper ES2015 support.&lt;/p&gt;
&lt;p&gt;Now we have a proper parser modeled after the &lt;a href=&quot;http://shift-ast.org/parser.html&quot;&gt;Shift Parser&lt;/a&gt; and producing a &lt;a href=&quot;https://github.com/shapesecurity/shift-spec&quot;&gt;Shift AST&lt;/a&gt; with Babel as an optional backend for great ES2015 support everywhere. It’s amazing.&lt;/p&gt;
&lt;p&gt;Second, Sweet now has much more reasonable macro binding forms. Previously, you could define a macro in two ways, the recursive and non-recursive declaration forms:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// recursive form&lt;/span&gt;
macro foo &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* ... */&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// non-recursive form&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; foo &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; macro &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* ... */&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The recursive form binds the macro name inside the macro definition while the non-recursive form does not. This was gross and confusing because standard let in ES2015 does not work like this at all. Now, Sweet uses &lt;code&gt;syntax&lt;/code&gt; and &lt;code&gt;syntaxrec&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// non-recursive form&lt;/span&gt;
syntax &lt;span class=&quot;token function-variable function&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* ... */&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// recursive form&lt;/span&gt;
syntaxrec &lt;span class=&quot;token function-variable function&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;ctx&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* ... */&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These are more symmetric and fit in better as a compiletime extension of the &lt;code&gt;var&lt;/code&gt;/&lt;code&gt;let&lt;/code&gt;/&lt;code&gt;const&lt;/code&gt; binding forms of ES2015.&lt;/p&gt;
&lt;p&gt;While all these changes are great, there are a few items from the pre-1.0 days that have not been re-implemented yet. Custom operators and infix macros in particular are not currently supported. However, the foundation provided by the rewrite will make adding these features back pretty straightforward so expect them to be available soon.&lt;/p&gt;
&lt;p&gt;So should you dive in with the new Sweet? Well, to be honest it really depends on how risk averse you are. Since so much has changed with the rewrite there are bound to be bugs we still need to shake out. Maybe don’t go running Sweet over your production code just yet.&lt;/p&gt;
&lt;p&gt;But if you’d like to help out by putting Sweet through its paces we would love to have you! The best way to get started is to familiarize yourself with all the new syntax by reading the &lt;a href=&quot;http://sweetjs.org/doc/1.0/tutorial.html&quot;&gt;tutorial&lt;/a&gt;. If you’ve got questions or need help, head on over to &lt;a href=&quot;https://gitter.im/mozilla/sweet.js&quot;&gt;gitter&lt;/a&gt; or #sweet.js on irc.mozilla.org.&lt;/p&gt;
&lt;p&gt;Have fun sweetening your code!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Hygiene in sweetjs</title>
		<link href="https://disnetdev.com/blog/2013-09-27-hygiene-in-sweetjs/"/>
		<updated>2013-09-27T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2013-09-27-hygiene-in-sweetjs/</id>
		<content type="html">&lt;p&gt;The most important feature of &lt;a href=&quot;http://sweetjs.org&quot;&gt;sweet.js&lt;/a&gt; is hygiene. Hygiene prevents variables names inside of macros from clashing with variables in the surrounding code. It&#39;s what gives macros the power to actually be syntactic abstractions by hiding implementation details and allowing you to use a hygienic macro &lt;em&gt;anywhere&lt;/em&gt; in your code.&lt;/p&gt;
&lt;p&gt;For hygiene to work sweet.js must rename variables. Recently several people have asked me why sweet.js renames &lt;strong&gt;all&lt;/strong&gt; the variables. Wouldn&#39;t it be better and cleaner to only rename the variables that macros introduce?&lt;/p&gt;
&lt;p&gt;The tl;dr is &amp;quot;because hygiene&amp;quot; but let&#39;s unpack that a little.&lt;/p&gt;
&lt;h2 id=&quot;hygiene-part-1-binding&quot; tabindex=&quot;-1&quot;&gt;Hygiene Part 1 (Binding) &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2013-09-27-hygiene-in-sweetjs/#hygiene-part-1-binding&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The part of hygiene most people intuitively grok is keeping track of the variable &lt;em&gt;bindings&lt;/em&gt; that a macro introduces. For example, the swap macro creates a &lt;code&gt;tmp&lt;/code&gt; variable that should only be bound inside of the macro:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;macro swap &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  rule &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;$a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; $b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; tmp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; $a&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    $a &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; $b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    $b &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; tmp&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; tmp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; b &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;swap&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tmp&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hygiene keeps the two &lt;code&gt;tmp&lt;/code&gt; bindings distinct by renaming them both:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; tmp$1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; b$2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; tmp$3 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; tmp$1&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
tmp$1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; b$2&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
b$2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; tmp$3&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is the point where most people say &amp;quot;why bother renaming the variables outside of the macro&amp;quot;? Can&#39;t you just rename the bindings created by the macro? Wouldn&#39;t it be cleaner for the expansion to just be something like:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; tmp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; b &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; tmp$1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; tmp&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
tmp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
b &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; tmp$1&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;hygiene-part-2-reference&quot; tabindex=&quot;-1&quot;&gt;Hygiene Part 2 (Reference) &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2013-09-27-hygiene-in-sweetjs/#hygiene-part-2-reference&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The complication comes in with variable &lt;em&gt;references&lt;/em&gt;. The body of a macro can contain references to bindings declared outside of the macro and those references must be consistent no matter the context in which the macro is invoked.&lt;/p&gt;
&lt;p&gt;Some code to clarify. Let&#39;s say you have a macro that uses a random number function:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;random&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;seed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* ... */&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; m &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; macro &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    rule &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; n &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This macro needs to refer to &lt;code&gt;random&lt;/code&gt; in any context that it gets invoked. But its context could have a different binding to &lt;code&gt;random&lt;/code&gt;!&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; random &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hygiene needs to keep the two &lt;code&gt;random&lt;/code&gt; bindings different. So sweet.js will expand this into something like:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;random$1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;seed$4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;/* ... */&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; random$2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; n$3 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;random$1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that there is no way for hygiene to do this if it only renamed identifiers inside of macros since both &lt;code&gt;random&lt;/code&gt; bindings were declared outside of the macro. Hygiene is necessarily a whole program transformation.&lt;/p&gt;
&lt;p&gt;(ps if this sort of feels like a closure you&#39;re on to something: one of the early techniques that led to modern hygiene algorithms was called &lt;a href=&quot;ftp://publications.ai.mit.edu/ai-publications/pdf/AIM-1049.pdf&quot;&gt;syntactic closures&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Strictly speaking the hygiene algorithm is still conservative. Variable bindings declared outside of a macro that are never referenced by a macro don&#39;t really need to be renamed. However, modifying the hygiene algorithm to only rename &lt;em&gt;exactly&lt;/em&gt; what needs to be renamed seems pretty difficult (especially to do so efficiently). If anyone knows techniques for this definitely let me know (or even better submit a pull request).&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>How to read macros</title>
		<link href="https://disnetdev.com/blog/2012-12-20-how-to-read-macros/"/>
		<updated>2012-12-20T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2012-12-20-how-to-read-macros/</id>
		<content type="html">&lt;p&gt;In my last &lt;a href=&quot;http://disnetdev.com/blog/2012/10/14/hygienic-macros-for-javascript/&quot; title=&quot;Hygienic Macros for JavaScript&quot;&gt;post&lt;/a&gt; I gave a little overview of &lt;a href=&quot;http://sweetjs.org/&quot; title=&quot;Sweet.js&quot;&gt;sweet.js&lt;/a&gt; the hygienic macro system I built over the summer. Today I want to write a little bit about what makes sweet.js possible and why we haven&#39;t really seen a macro system for JavaScript before now. I gave hints at some of this in my intern &lt;a href=&quot;https://air.mozilla.org/sweetjs/&quot; title=&quot;Sweet.js Talk&quot;&gt;talk&lt;/a&gt; but now we can finally do a deep dive!&lt;/p&gt;
&lt;h2 id=&quot;basics&quot; tabindex=&quot;-1&quot;&gt;Basics &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2012-12-20-how-to-read-macros/#basics&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First, let&#39;s take a look at compilers 101:&lt;/p&gt;
&lt;img src=&quot;https://disnetdev.com/static/images/parser_pipeline.png&quot; alt=&quot;Parser Pipeline&quot; width=&quot;100%&quot; height=&quot;109px&quot;&gt;
&lt;p&gt;The traditional way you build a compiler front end is to first write a lexer and a parser. Code (a string) is fed to the lexer which produces an array of tokens which gets fed to the parser which produces an Abstract Syntax Tree (AST).&lt;/p&gt;
&lt;p&gt;For example,&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;foo &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; bar&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;w00t!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;gets lexed into something like:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;if&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;(&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;foo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;bar&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The lexer is basically responsible for throwing away unnecessary whitespace and grouping identifiers, strings, and numbers into discrete chunks (ie tokens). The array of tokens is then parsed into an AST that might look something like this:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// output of esprima&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Program&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token string-property property&quot;&gt;&quot;body&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token string-property property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;IfStatement&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token string-property property&quot;&gt;&quot;test&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token string-property property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;BinaryExpression&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token string-property property&quot;&gt;&quot;operator&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token string-property property&quot;&gt;&quot;left&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token string-property property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Identifier&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token string-property property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;foo&quot;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token string-property property&quot;&gt;&quot;right&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token string-property property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Identifier&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token string-property property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;bar&quot;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token string-property property&quot;&gt;&quot;consequent&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token string-property property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;BlockStatement&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token string-property property&quot;&gt;&quot;body&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                        &lt;span class=&quot;token string-property property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;ExpressionStatement&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;token string-property property&quot;&gt;&quot;expression&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                            &lt;span class=&quot;token string-property property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;CallExpression&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;token string-property property&quot;&gt;&quot;callee&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                                &lt;span class=&quot;token string-property property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Identifier&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                                &lt;span class=&quot;token string-property property&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;alert&quot;&lt;/span&gt;
                            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;token string-property property&quot;&gt;&quot;arguments&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                                    &lt;span class=&quot;token string-property property&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Literal&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                                    &lt;span class=&quot;token string-property property&quot;&gt;&quot;value&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;w00t!&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                                    &lt;span class=&quot;token string-property property&quot;&gt;&quot;raw&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&#92;&quot;w00t!&#92;&quot;&quot;&lt;/span&gt;
                                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token string-property property&quot;&gt;&quot;alternate&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The AST gives you the structure necessary to do code optimization/generation etc.&lt;/p&gt;
&lt;p&gt;So where can we fit macros into this picture? Which representation is best for macros to do their stuff?&lt;/p&gt;
&lt;p&gt;Well, by the time we get to an AST it&#39;s too late since parsers only understand a fixed grammar (well, technically there is research on &lt;a href=&quot;http://en.wikipedia.org/wiki/Adaptive_grammar&quot; title=&quot;Adaptive Grammar&quot;&gt;adaptive/extensible grammars&lt;/a&gt; but that way leads to madness!). Obviously the raw code as a string is too unstructured for macros so how about the array of tokens produced by the lexer?&lt;/p&gt;
&lt;p&gt;Tokens are fine for cpp &lt;code&gt;#define&lt;/code&gt; style macros but we want moar power! And, as it turns out, just normal tokens aren&#39;t going to cut it for us. Consider this simple macro that provides a concise way to define functions:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;macro def &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; $name $params &lt;span class=&quot;token parameter&quot;&gt;$body&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; $name $params $body
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
def &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;which should be expanded into:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Critically, note that the macro needs to match &lt;code&gt;$params&lt;/code&gt; with &lt;code&gt;(a, b)&lt;/code&gt; and &lt;code&gt;$body&lt;/code&gt; with &lt;code&gt;{ return a + b; }&lt;/code&gt;. However, we don&#39;t have enough structure to do this with just the token array &lt;code&gt;[&amp;quot;def&amp;quot;, &amp;quot;add&amp;quot;, &amp;quot;(&amp;quot;, &amp;quot;a&amp;quot;, &amp;quot;,&amp;quot;, &amp;quot;b&amp;quot;, ...]&lt;/code&gt;: we need to match the delimiters (&lt;code&gt;()&lt;/code&gt;, &lt;code&gt;{}&lt;/code&gt;, and &lt;code&gt;[]&lt;/code&gt;) first!&lt;/p&gt;
&lt;p&gt;If you remember your compilers class (or went to wikipedia), delimiter matching is what separates &lt;a href=&quot;http://en.wikipedia.org/wiki/Context-free_language&quot; title=&quot;Context-Free Language&quot;&gt;context-free&lt;/a&gt; languages (what parsers recognize) from &lt;a href=&quot;http://en.wikipedia.org/wiki/Regular_language&quot; title=&quot;Regular Language&quot;&gt;regular&lt;/a&gt; languages (what lexers recognize).&lt;/p&gt;
&lt;p&gt;This is one of the reasons why macros are big in the lisp family of languages (scheme, racket, clojure, etc.). S-expressions (with (all (those (parentheses)))) are already fully delimited so it becomes almost trivial to do delimiter matching. Some people say this is due to &lt;a href=&quot;http://en.wikipedia.org/wiki/Homoiconicity&quot; title=&quot;Homoiconicity&quot;&gt;homoiconicity&lt;/a&gt; but as Dave Herman &lt;a href=&quot;http://calculist.org/blog/2012/04/17/homoiconicity-isnt-the-point&quot; title=&quot;Homoiconicity not the point&quot;&gt;pointed out&lt;/a&gt;, homoiconicity isn&#39;t really the point. It&#39;s not that the lisp family is homoiconic but rather that the nature of s-expressions makes it easy to implement &lt;code&gt;read&lt;/code&gt; which is necessary for macros.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;read&lt;/code&gt; is the crucial function that gives a little bit more structure to the array of tokens by matching up all those delimiters. Now instead of just a flat array of tokens we are going to get a &lt;em&gt;read tree:&lt;/em&gt;&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;def&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;add&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;()&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;innerTokens&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;,&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;b&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;innerTokens&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;return&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;+&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;b&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note this doesn&#39;t have all the structure of a full AST, it just knows about tokens and delimiters not expressions and statements. So now our &lt;code&gt;def&lt;/code&gt; macro pattern variables will match up like so:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;$params &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;()&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;innerTokens&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;,&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;b&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
$body &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;{}&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;innerTokens&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;return&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;a&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;+&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;b&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Great! Now our pipeline looks something like:&lt;/p&gt;
&lt;img src=&quot;https://disnetdev.com/static/images/pipeline_plus_read.png&quot; alt=&quot;Pipeline With Read&quot; width=&quot;100%&quot; height=&quot;87px&quot;&gt;
&lt;h2 id=&quot;the-devil-in-the-details&quot; tabindex=&quot;-1&quot;&gt;The Devil in the Details &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2012-12-20-how-to-read-macros/#the-devil-in-the-details&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Ok, so all well and good but then why haven&#39;t we seen people implement &lt;code&gt;read&lt;/code&gt; and build a macro system for JavaScript before now?&lt;/p&gt;
&lt;p&gt;It turns out that there&#39;s this really annoying token (for potential macro implementers) in JavaScript: &lt;code&gt;/&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here&#39;s the problem, depending on context &lt;code&gt;/&lt;/code&gt; can mean two different things: the divide operator or the beginning of a regular expression literal.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;              &lt;span class=&quot;token comment&quot;&gt;// 5&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;foo&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;foo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;   &lt;span class=&quot;token comment&quot;&gt;// true&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(Well technically I guess &lt;code&gt;/&lt;/code&gt; can also mean the start of a comment but this is always easy to figure out (since &lt;code&gt;//&lt;/code&gt; &lt;strong&gt;always&lt;/strong&gt; means line comment))&lt;/p&gt;
&lt;p&gt;So how do we disambiguate between divide and regex? It turns out that the way a normal parser (like &lt;a href=&quot;http://esprima.org/&quot; title=&quot;Esprima&quot;&gt;esprima&lt;/a&gt; for example) does it is by running the lexer and parser together and resolving the ambiguity via the current &lt;strong&gt;parsing&lt;/strong&gt; context. In other words, as the parser is working through each production, it calls out to the lexer with a flag saying what context it is in. Depending on that context the lexer will either lex &lt;code&gt;/&lt;/code&gt; as a divide token or as a regular expression literal.&lt;/p&gt;
&lt;p&gt;But, we can&#39;t use the parsing context in &lt;code&gt;read&lt;/code&gt; because we don&#39;t have any parsing context yet!&lt;/p&gt;
&lt;p&gt;So, we somehow need to separate the lexer/reader from the parser.&lt;/p&gt;
&lt;p&gt;Now you might think we could get away with just leaving &lt;code&gt;/&lt;/code&gt; as an ambiguous token (say a &lt;code&gt;divOrRegex&lt;/code&gt; token for example) to be handled by the parser once all the macros have been expanded away but consider this code fragment we might want to &lt;code&gt;read&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;foo}bar&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// as a token array this would be&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// [... &quot;{&quot;, &quot;/&quot;, &quot;foo&quot;, &quot;}&quot;, &quot;bar&quot;, &quot;/&quot;, ...]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Remember that the entire point of &lt;code&gt;read&lt;/code&gt; is to do delimiter matching, so should we match the &lt;code&gt;}&lt;/code&gt; with the opening &lt;code&gt;{&lt;/code&gt; or as part of a regular expression literal (remember &lt;code&gt;/}/&lt;/code&gt; is a valid regex that matches a single &lt;code&gt;}&lt;/code&gt;)? It completely depends on our interpretation of &lt;code&gt;/&lt;/code&gt;!&lt;/p&gt;
&lt;p&gt;Therefore, in our lexer/reader we &lt;strong&gt;must&lt;/strong&gt; disambiguate the meaning of &lt;code&gt;/&lt;/code&gt; without the help of the parser. So how do we do that?&lt;/p&gt;
&lt;p&gt;This is the hard technical problem that &lt;a href=&quot;https://twitter.com/PaulStansifer&quot; title=&quot;Paul Stansifer&quot;&gt;Paul Stansifer&lt;/a&gt; (he also designed the &lt;a href=&quot;http://www.rust-lang.org/&quot; title=&quot;Rust&quot;&gt;Rust&lt;/a&gt; macro system) solved this summer, unlocking the power of JavaScript macros for us all!&lt;/p&gt;
&lt;p&gt;The basic idea is when you see a &lt;code&gt;/&lt;/code&gt; as you are reading, just look back a couple of tokens and a small fixed set of tokens will determine unambiguously if &lt;code&gt;/&lt;/code&gt; should be a divide or the start of a regex literal. To figure out exactly how far back and which tokens to look for requires working through all the different cases in the JavaScript grammar which is hard but done!&lt;/p&gt;
&lt;p&gt;A snippet of this algorithm goes something like:&lt;/p&gt;
&lt;p&gt;if tok is /
if tok-1 is )
look back to matching (
if identifier before ( in &amp;quot;if&amp;quot; &amp;quot;while&amp;quot;
&amp;quot;for&amp;quot; &amp;quot;with&amp;quot;
tok is start of regex literal
else
tok is divide
...&lt;/p&gt;
&lt;p&gt;For example, if we have:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;foo &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;24&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; bar&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;baz&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;foo&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When we see the &lt;code&gt;/&lt;/code&gt; we note that the previous token was &lt;code&gt;)&lt;/code&gt; so we find its matching &lt;code&gt;(&lt;/code&gt; and note that the token before that was &lt;code&gt;if&lt;/code&gt; so &lt;code&gt;/&lt;/code&gt; must be the beginning of a regular expression.&lt;/p&gt;
&lt;p&gt;What&#39;s really cool here is that when we need to disambiguate &lt;code&gt;/&lt;/code&gt; we&#39;ve already been reading up to that point so &lt;code&gt;(foo + 24 &amp;gt; bar)&lt;/code&gt; is a single token (the &lt;code&gt;()&lt;/code&gt; token with inner tokens &lt;code&gt;foo&lt;/code&gt;, &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;24&lt;/code&gt;, &lt;code&gt;&amp;gt;&lt;/code&gt;, and &lt;code&gt;bar&lt;/code&gt;) and checking the token before the parens is literally as simple as &lt;code&gt;tokens[idx-2] === &amp;quot;if&amp;quot;&lt;/code&gt;. By creating the read tree as we go along we don&#39;t need to carry lookbehind state in a complicated way; in fact, in the worst case, we only have to look back 5 tokens.&lt;/p&gt;
&lt;p&gt;If you want to read more about how this works, I&#39;ve got the entire algorithm pseudo-coded up &lt;a href=&quot;https://github.com/mozilla/sweet.js/wiki/design&quot; title=&quot;Read Design Doc&quot;&gt;here&lt;/a&gt; and the actual JavaScript implementation in these relatively short &lt;a href=&quot;https://github.com/mozilla/sweet.js/blob/master/src/parser.js#L3713&quot; title=&quot;Github&quot;&gt;two&lt;/a&gt; &lt;a href=&quot;https://github.com/mozilla/sweet.js/blob/master/src/parser.js#L3631&quot; title=&quot;Github&quot;&gt;functions&lt;/a&gt;.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Hygienic Macros for JavaScript</title>
		<link href="https://disnetdev.com/blog/2012-10-14-hygienic-macros-for-javascript/"/>
		<updated>2012-10-14T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2012-10-14-hygienic-macros-for-javascript/</id>
		<content type="html">&lt;p&gt;Been slow to embloggen this (start of the quarter etc.) but my summer intern project was released a little while ago at &lt;a href=&quot;http://sweetjs.org&quot;&gt;sweetjs.org&lt;/a&gt;. Sweet.js is a &lt;a href=&quot;http://en.wikipedia.org/wiki/Hygienic_macro&quot;&gt;hygienic macro&lt;/a&gt; compiler for JavaScript that takes JavaScript written with macros and produces normal JavaScript you can run in your browser or on node. It&#39;s an experiment to see if macros can work well for JavaScript.&lt;/p&gt;
&lt;p&gt;Macros allow you to extend the syntax of JavaScript by writing macro definitions that perform syntax transformations, thus allowing you to do cool things like add sweet syntax for &lt;a href=&quot;https://gist.github.com/3881008&quot;&gt;var destructuring&lt;/a&gt; or even haskell-like &lt;a href=&quot;https://gist.github.com/3831514&quot;&gt;do notation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The idea is to provide a middle ground between no syntax extension and having to build an entire compile-to-js language like CoffeeScript, which can&#39;t compose with other syntax extensions.&lt;/p&gt;
&lt;p&gt;I talk a bit about the motivation and design in this &lt;a href=&quot;https://air.mozilla.org/sweetjs/&quot;&gt;presentation&lt;/a&gt; I gave at the end of my internship.&lt;/p&gt;
&lt;p&gt;The language that most directly inspires sweet.js is, of course, scheme. I&#39;m not really much of a schemer myself but have always admired the fancy work going on in that world and macros are pretty fancy. At the start of the summer I was still somewhat of a macro newbie but being at Mozilla was fantastic since I was able to draw on and learn from two well-versed scheme macrologists &lt;a href=&quot;https://twitter.com/littlecalculist&quot;&gt;Dave Herman&lt;/a&gt; (who&#39;s PhD thesis was on macros) and &lt;a href=&quot;https://twitter.com/PaulStansifer&quot;&gt;Paul Stansifer&lt;/a&gt; (who has been developing the &lt;a href=&quot;http://www.rust-lang.org/&quot;&gt;Rust&lt;/a&gt; macro system).&lt;/p&gt;
&lt;p&gt;Sweet.js is still in very early stages, lots of bugs and missing features, but I think it shows some real promise. Let me know what you think!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Memory Checking in Low-Level JavaScript</title>
		<link href="https://disnetdev.com/blog/2012-07-18-memory-checking-in-low-level-javascript/"/>
		<updated>2012-07-18T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2012-07-18-memory-checking-in-low-level-javascript/</id>
		<content type="html">&lt;p&gt;So this past month I&#39;ve been helping out on the
&lt;a href=&quot;http://lljs.org/&quot; title=&quot;Low-Level JavaScript&quot;&gt;Low-Level JavaScript&lt;/a&gt; (LLJS) project. Bit of a change for me since I usually
hide out at
as &lt;a href=&quot;http://www.quickmeme.com/meme/358lli/&quot; title=&quot;Abstract all the things!&quot;&gt;high a level as I can possibly get&lt;/a&gt; :)&lt;/p&gt;
&lt;p&gt;LLJS is an experiment in adding low-level features like pointers and
manual memory management to a dialect of JavaScript.
These low-level features are pretty cool and can get you some nice
performance wins, but they also come at a cost since
you are always one
null pointer dereference or memory leak away from oblivion.&lt;/p&gt;
&lt;p&gt;One way C/C++ programmers have handled this danger is by using an
analysis tool like &lt;a href=&quot;http://valgrind.org/&quot; title=&quot;Valgrind&quot;&gt;Valgrind&lt;/a&gt; to detect memory errors
that happen while the program is running.
Since memory checking has proven to be useful in the C world, we
figured it might be helpful for LLJS. So, I&#39;ve hacked up a
valgrind-like memory analysis for LLJS. It can detect four kinds
of memory errors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;reads/writes to unallocated memory (pointers we haven&#39;t &lt;code&gt;malloc&lt;/code&gt;&#39;ed)&lt;/li&gt;
&lt;li&gt;reads from undefined memory (&lt;code&gt;malloc&lt;/code&gt;&#39;ed memory we haven&#39;t
written to)&lt;/li&gt;
&lt;li&gt;bad frees (calling &lt;code&gt;free&lt;/code&gt; on memory that hasn&#39;t been &lt;code&gt;malloc&lt;/code&gt;&#39;ed)&lt;/li&gt;
&lt;li&gt;leaks (any unfreed memory at the end of the program run)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;how-to-use&quot; tabindex=&quot;-1&quot;&gt;How to use &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2012-07-18-memory-checking-in-low-level-javascript/#how-to-use&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Go grab the latest version of LLJS from its github &lt;a href=&quot;https://github.com/mbebenita/LLJS&quot; title=&quot;LLJS on github&quot;&gt;repo&lt;/a&gt;.
Then add the following snippet to the end of your script:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; m &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;memory&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;memcheck&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;report&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This pulls in the memory module and prints out the result of the
memory checking (this snippet is for node.js, so use &lt;code&gt;load&lt;/code&gt; if you&#39;re
using SpiderMonkey or grab &lt;code&gt;memory&lt;/code&gt; off the global object if you&#39;re in
the browser).&lt;/p&gt;
&lt;p&gt;Then compile your LLJS code with the &lt;code&gt;-m&lt;/code&gt; flag:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;bin/ljc &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-o&lt;/span&gt; your_file.js your_file.ljs&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and run it:&lt;/p&gt;
&lt;pre class=&quot;language-sh&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-sh&quot;&gt;&lt;span class=&quot;token function&quot;&gt;node&lt;/span&gt; --harmony-proxies your_file.js&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see the memory checker uses &lt;a href=&quot;https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Proxy&quot; title=&quot;Proxy&quot;&gt;Proxies&lt;/a&gt;, which node/V8
hides behind a flag (no flag needed on SpiderMonkey).&lt;/p&gt;
&lt;p&gt;For example, the following script:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;extern console&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_unallocated&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; uint &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// not allocated yet!&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;test_unallocated&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_leak&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// leak!&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; uint &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;leak &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;uint&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;test_leak&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;test_free&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; uint &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;uint&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;test_free&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; m &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;memory&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;memcheck&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;report&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;will print out the following report:&lt;/p&gt;
&lt;p&gt;Unallocated:
0 at:
test_unallocated:3:0&lt;/p&gt;
&lt;p&gt;Undefined:
0 at:
test_unallocated:3:0&lt;/p&gt;
&lt;p&gt;Bad frees:
8184 at:
test_free:16:0&lt;/p&gt;
&lt;p&gt;Leaks:
8200 at:
test_leak:10:0&lt;/p&gt;
&lt;h2 id=&quot;how-it-works&quot; tabindex=&quot;-1&quot;&gt;How it works &lt;a class=&quot;header-anchor&quot; href=&quot;https://disnetdev.com/blog/2012-07-18-memory-checking-in-low-level-javascript/#how-it-works&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Memory allocation in LLJS is implemented as a big &lt;a href=&quot;https://developer.mozilla.org/en/JavaScript_typed_arrays&quot; title=&quot;Typed Arrays&quot;&gt;typed array&lt;/a&gt;
where pointers are really just array indexes into the array.&lt;/p&gt;
&lt;p&gt;To do memory checking we create a second &lt;em&gt;shadow memory&lt;/em&gt; typed array
that stores the allocation status of each byte of real memory (if the byte
has been allocated, initialized, etc.). Calls to &lt;code&gt;malloc&lt;/code&gt; and &lt;code&gt;free&lt;/code&gt;
change the allocation status of the bytes in shadow memory. The real memory
array is
wrapped in a Proxy that
intercepts each get and set operation and
checks the shadow memory
for a possible error.&lt;/p&gt;
&lt;p&gt;For example, say we we allocate an int and try to do some pointer
arithmetic and dereference unallocated memory:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; int &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;x &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;When the dereference of &lt;code&gt;x+1&lt;/code&gt; happens, the Proxy wrapping real memory
will check in shadow memory to see if &lt;code&gt;x+1&lt;/code&gt; has been allocated. Since
it hasn&#39;t, an unallocated memory access error is recorded.&lt;/p&gt;
&lt;p&gt;This approach is basically a simplified version of how
Valgrind &lt;a href=&quot;http://valgrind.org/docs/shadow-memory2007.pdf&quot; title=&quot;Memcheck&quot;&gt;does memory checking&lt;/a&gt;.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Stable node.js now runs contracts.coffee!</title>
		<link href="https://disnetdev.com/blog/2012-07-15-stable-node-js-now-runs-contracts-coffee/"/>
		<updated>2012-07-15T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2012-07-15-stable-node-js-now-runs-contracts-coffee/</id>
		<content type="html">&lt;p&gt;Took almost a year but now the stable version of node.js (0.8.0+) has
a recent enough version of V8 to run contracts.coffee! The much
needed proxy support is still behind a flag so you&#39;ll need to
supply &lt;code&gt;--harmony_proxies&lt;/code&gt; and &lt;code&gt;--harmony-collections&lt;/code&gt; as usual.&lt;/p&gt;
&lt;p&gt;Also, the latest version of contracts.coffee (0.3.1)
and is now up on npm and
collects a few bugs fixes.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Link Roundup</title>
		<link href="https://disnetdev.com/blog/2012-05-13-link-roundup/"/>
		<updated>2012-05-13T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2012-05-13-link-roundup/</id>
		<content type="html">&lt;p&gt;&lt;a href=&quot;http://mbebenita.github.com/Mvm/&quot; title=&quot;*JS&quot;&gt;*JS&lt;/a&gt; is a really cool (if ungoogleable) project that attempts
to be &amp;quot;the bastard child of JavaScript and C&amp;quot; by giving you the low
level tools to build fast programs in a high level language.&lt;/p&gt;
&lt;p&gt;After the recent excitement surrounding Bret Victor&#39;s
&lt;a href=&quot;http://vimeo.com/36579366&quot; title=&quot;Inventing on Principle&quot;&gt;amazing talk&lt;/a&gt;, Jonathan Edwards has a &lt;a href=&quot;http://alarmingdevelopment.org/?p=680&quot; title=&quot;An IDE is not enough&quot;&gt;sobering essay&lt;/a&gt;
about the limits of IDE innovation. Makes the point that languages
must co-evolve to get real innovation.&lt;/p&gt;
&lt;p&gt;Wired has a &lt;a href=&quot;http://www.wired.com/threatlevel/2012/05/everyone-hacked/all/1&quot; title=&quot;Everyone Has Been Hacked&quot;&gt;nice writeup&lt;/a&gt; on the current state of computer security
(spoiler: it sucks) and
The New Yorker has a &lt;a href=&quot;http://www.newyorker.com/reporting/2012/05/07/120507fa_fact_kushner?currentPage=all&quot; title=&quot;Machine Politics&quot;&gt;great article&lt;/a&gt; on the recent geohot vs. Sony
craziness.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Link Roundup</title>
		<link href="https://disnetdev.com/blog/2012-04-28-link-roundup/"/>
		<updated>2012-04-28T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2012-04-28-link-roundup/</id>
		<content type="html">&lt;p&gt;&lt;a href=&quot;http://infrequently.org/2012/04/class-warfare/&quot; title=&quot;Class Warfare&quot;&gt;Lots&lt;/a&gt; of &lt;a href=&quot;http://www.mikealrogers.com/posts/tc-thirty-what.html&quot; title=&quot;TC-thirty-what&quot;&gt;discussion&lt;/a&gt; around classes and
other changes being considered for the future of JavaScript.
Interesting how difficult it has been for the standardization
committee (or the JS community in general) to come to a consensus on
what classes should look like (or if they should even exist).&lt;/p&gt;
&lt;p&gt;In what is almost becoming a weekly story, &lt;a href=&quot;http://sns.cs.princeton.edu/2012/04/javascript-in-javascript-js-js-sandboxing-third-party-scripts/&quot; title=&quot;js.js&quot;&gt;emscripten has been used to
impressive effect again&lt;/a&gt;. This time SpiderMonkey (the JS engine in
Firefox) has been compiled to JavaScript.&lt;/p&gt;
&lt;p&gt;Finally, an
&lt;a href=&quot;http://calculist.org/blog/2012/04/17/homoiconicity-isnt-the-point/&quot; title=&quot;Homoiconicity isn&#39;t the point&quot;&gt;explanation of why Lisp’s syntax is so important and useful&lt;/a&gt;
that finally clicked for me. The key: &amp;quot;it&#39;s possible to &lt;em&gt;read&lt;/em&gt; it
without &lt;em&gt;parsing&lt;/em&gt;.&amp;quot;&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;http://pksunkara.github.com/semicolon/&quot; title=&quot;Semicolon&quot;&gt;greatest language in the world&lt;/a&gt; has been made. PL is done,
we can all go home now.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>contracts.coffee now runs in Chrome!</title>
		<link href="https://disnetdev.com/blog/2012-04-19-contracts-coffee-now-runs-in-chrome/"/>
		<updated>2012-04-19T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2012-04-19-contracts-coffee-now-runs-in-chrome/</id>
		<content type="html">&lt;p&gt;Chrome can now run &lt;a href=&quot;http://disnetdev.com/contracts.coffee/&quot;&gt;contracts.coffee&lt;/a&gt;!
I&#39;ve been waiting a while for the proxy support in Chrome to get far enough along but
it&#39;s finally here.&lt;/p&gt;
&lt;p&gt;Chrome hides experimental JavaScript features
like proxies behind flags so you&#39;ll need to go to
about:flags and enable the experimental JavaScript flag.&lt;/p&gt;
&lt;p&gt;Try it out and if you run into any issues let me know on
&lt;a href=&quot;https://github.com/disnet/contracts.coffee/issues?direction=desc&amp;amp;sort=created&amp;amp;state=open&quot;&gt;github&lt;/a&gt;.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Updates to contracts.coffee</title>
		<link href="https://disnetdev.com/blog/2012-04-16-updates-to-contracts-coffee/"/>
		<updated>2012-04-16T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2012-04-16-updates-to-contracts-coffee/</id>
		<content type="html">&lt;p&gt;A new version of contracts.coffee is up on npm. We&#39;re now synced with
the latest release version of CoffeeScript (1.3.1) and have collected
a few bug fixes. We also have experimental require.js/AMD support.
Change log &lt;a href=&quot;http://disnetdev.com/contracts.coffee/#log&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Get it with &lt;code&gt;npm install contracts.coffee&lt;/code&gt;.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Weekly Link Roundup</title>
		<link href="https://disnetdev.com/blog/2012-04-08-weekly-link-roundup/"/>
		<updated>2012-04-08T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2012-04-08-weekly-link-roundup/</id>
		<content type="html">&lt;p&gt;&lt;a href=&quot;http://bits.blogs.nytimes.com/2012/04/04/google-begins-testing-its-augmented-reality-glasses/&quot; title=&quot;Google Glasses&quot;&gt;Details surface about Google&#39;s project Glass&lt;/a&gt;. The future is now
and all that. &lt;a href=&quot;http://www.amazon.com/Rainbows-End-Vernor-Vinge/dp/0812536363/ref=sr_1_1?ie=UTF8&amp;amp;qid=1333925648&amp;amp;sr=8-1&quot; title=&quot;Rainbows End&quot;&gt;Rainbows End&lt;/a&gt; and &lt;a href=&quot;http://www.amazon.com/Daemon-Daniel-Suarez/dp/B003L1ZXCU/ref=sr_1_1?ie=UTF8&amp;amp;qid=1333925660&amp;amp;sr=8-1&quot; title=&quot;Daemon&quot;&gt;Daemon&lt;/a&gt;/&lt;a href=&quot;http://www.amazon.com/Freedom-TM-Daemon-ebook/dp/B002VUFKDY/ref=sr_1_3?ie=UTF8&amp;amp;qid=1333925660&amp;amp;sr=8-3&quot; title=&quot;Freedom&quot;&gt;Freedom™&lt;/a&gt;
are now required reading.&lt;/p&gt;
&lt;p&gt;I didn&#39;t realize when I first saw it but xkcd&#39;s April 1st comic was
actually quite &lt;a href=&quot;http://www.reddit.com/r/comics/comments/rnpiw/mindboggling_xkcd_april_fools_comic/&quot; title=&quot;April 1st xkcd&quot;&gt;brilliant&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Some &lt;a href=&quot;http://cscs.umich.edu/~crshalizi/weblog/900.html&quot; title=&quot;Academic Talks&quot;&gt;good advice on giving academic talks&lt;/a&gt; under the twin
lenses of memory (your audience&#39;s resource — build context and
be wary of details) and fear (your resource — desensitize and
dissociate).&lt;/p&gt;
&lt;p&gt;An &lt;a href=&quot;https://priv.ly/&quot; title=&quot;Priv.ly&quot;&gt;interesting privacy hack&lt;/a&gt; for the web was announced and
&lt;a href=&quot;http://www.kickstarter.com/projects/229630898/protect-your-content-anywhere-on-the-web-privly&quot; title=&quot;Priv.ly kickstarter&quot;&gt;kickstarted&lt;/a&gt;.
Amusingly enough they use Libya&#39;s &lt;a href=&quot;http://en.wikipedia.org/wiki/CcTLD&quot; title=&quot;ccTLD&quot;&gt;ccTLD&lt;/a&gt; (&lt;a href=&quot;http://en.wikipedia.org/wiki/.ir&quot; title=&quot;Iran&#39;s ccTLD&quot;&gt;.ir&lt;/a&gt; or &lt;a href=&quot;http://en.wikipedia.org/wiki/.eg&quot; title=&quot;Egypt&#39;s ccTLD&quot;&gt;.eg&lt;/a&gt; would also have
been apropos). Hopefully they&#39;ve thought about domain seizures.&lt;/p&gt;
&lt;p&gt;And on a related note, &lt;a href=&quot;http://m.vanityfair.com/culture/2012/05/internet-regulation-war-sopa-pipa-defcon-hacking.print&quot; title=&quot;World War 3.0&quot;&gt;here&#39;s a good read on the internet wars&lt;/a&gt;.
In particular the forces of order (SOPA/PIPA, Iran, China, Egypt,
etc.) vs. the forces of chaos (Anonymous, LulzSec, etc.).&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Link Roundup</title>
		<link href="https://disnetdev.com/blog/2012-03-26-link-roundup/"/>
		<updated>2012-03-26T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2012-03-26-link-roundup/</id>
		<content type="html">&lt;p&gt;Gizmodo has a surprisingly well-reasoned &lt;a href=&quot;http://gizmodo.com/5895010/the-case-against-google&quot; title=&quot;The Case Against Google&quot;&gt;critique&lt;/a&gt; of Google.
Far better than the usual knee-jerk Google bashing that
too often passes for criticism online these days.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.youtube.com/watch?v=Y4MnpzG5Sqc&quot; title=&quot;Kony2012&quot;&gt;Kony 2012&lt;/a&gt; has probably done more for &lt;a href=&quot;http://www.theatlantic.com/international/archive/2012/03/the-white-savior-industrial-complex/254843/2/?single_page=true&quot; title=&quot;White savior industrial complex&quot;&gt;raising&lt;/a&gt; the &lt;a href=&quot;http://africasacountry.com/2012/03/07/phony-2012-risible-children/&quot; title=&quot;Kony 2012 show&quot;&gt;discourse&lt;/a&gt; &lt;a href=&quot;http://homebrewedchristianity.com/2012/03/19/kony-2012-and-apples-mr-daisy/&quot; title=&quot;Kony 2012 and Mr. Daisy&quot;&gt;on&lt;/a&gt;
&lt;a href=&quot;http://boingboing.net/2012/03/08/african-voices-respond-to-hype.html&quot; title=&quot;African Voices&quot;&gt;US&lt;/a&gt; &lt;a href=&quot;http://boingboing.net/2012/03/14/uganda-screening-of-kony-201.html&quot; title=&quot;Uganda Screening&quot;&gt;&amp;quot;aid&amp;quot;&lt;/a&gt; than its stated goal (killing a guy... er, I mean &amp;quot;raising awareness&amp;quot;).
Also, &lt;a href=&quot;http://www.youtube.com/watch?feature=player_embedded&amp;amp;v=hpAMbpQ8J7g&quot; title=&quot;First as Tragedy, then as farce&quot;&gt;Žižek&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://hacks.mozilla.org/2012/03/video-mobile-and-the-open-web/&quot; title=&quot;Video mobile and the open web&quot;&gt;Looks like the web lost the video (H.264) battle&lt;/a&gt;. Lame.&lt;/p&gt;
&lt;p&gt;A fantastic &lt;a href=&quot;http://www.coyotos.org/pipermail/bitc-dev/2012-March/003300.html&quot; title=&quot;Retrospective thoughts on BitC&quot;&gt;retrospective&lt;/a&gt; on &lt;a href=&quot;http://en.wikipedia.org/wiki/BitC&quot; title=&quot;BitC [Wikipedia]&quot;&gt;BitC&lt;/a&gt; with some echoing
&lt;a href=&quot;http://news.ycombinator.com/item?id=3749860&quot; title=&quot;Rust response&quot;&gt;comments from the Rust team&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Fear not! &lt;a href=&quot;http://theproofistrivial.com/&quot; title=&quot;The Proof is Trivial&quot;&gt;The proof is trivial&lt;/a&gt;.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Link roundup</title>
		<link href="https://disnetdev.com/blog/2012-03-18-link-roundup/"/>
		<updated>2012-03-18T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2012-03-18-link-roundup/</id>
		<content type="html">&lt;p&gt;Crista Lopes &lt;a href=&quot;http://tagide.com/blog/2012/03/research-in-programming-languages/&quot; title=&quot;Research in Programming Languages&quot;&gt;bemoans the state of PL research&lt;/a&gt; with good
responses from &lt;a href=&quot;http://tagide.com/blog/2012/03/research-in-programming-languages/#comment-135&quot; title=&quot;Felleisen Comment&quot;&gt;Matthias Felleisen&lt;/a&gt; and &lt;a href=&quot;http://lambda-the-ultimate.org/node/4469&quot; title=&quot;LtU discussion&quot;&gt;LtU&lt;/a&gt;
(read moar &lt;a href=&quot;http://en.wikipedia.org/wiki/The_Structure_of_Scientific_Revolutions&quot; title=&quot;The Structure of Scientific Revolutions&quot;&gt;Kuhn&lt;/a&gt;!).&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://syntensity.com/static/sql.html&quot; title=&quot;SQLite in Emscripten&quot;&gt;SQLite&lt;/a&gt; compiled to JavaScript via &lt;a href=&quot;https://github.com/kripken/emscripten/wiki&quot; title=&quot;Emscripten&quot;&gt;Emscripten&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://longnow.org/seminars/02012/mar/06/nine-planetary-boundaries-finessing-anthropocene/&quot; title=&quot;Planetary Boundaries&quot;&gt;Mark Lynas&lt;/a&gt; seems to think we can get the entire world out of poverty without
breaking the planetary boundaries (think carbon, biodiversity, land
use, etc.) by 2050. Cute.&lt;/p&gt;
&lt;p&gt;Game of Thrones is &lt;a href=&quot;http://www.amazon.com/gp/product/B007HJ84ZK/ref=sr_1_2_vod_0_lgo?ie=UTF8&amp;amp;qid=1332057105&amp;amp;sr=8-2&quot; title=&quot;Amazon.com&quot;&gt;available at long last online&lt;/a&gt; but &lt;a href=&quot;http://theoatmeal.com/comics/game_of_thrones&quot; title=&quot;Game of thrones&quot;&gt;who&#39;s complaining&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The NSA is apparently &lt;a href=&quot;http://www.wired.com/threatlevel/2012/03/ff_nsadatacenter/all/1&quot; title=&quot;NSA data center&quot;&gt;building a massive data center&lt;/a&gt; in Utah. This
doesn&#39;t &lt;a href=&quot;http://en.wikipedia.org/wiki/NSA_warrantless_surveillance_controversy&quot; title=&quot;Warrantless Wiretapping&quot;&gt;concern me at all&lt;/a&gt;.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Occupying Language Design at POPL</title>
		<link href="https://disnetdev.com/blog/2012-02-02-occupying-language-design-at-popl/"/>
		<updated>2012-02-02T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2012-02-02-occupying-language-design-at-popl/</id>
		<content type="html">&lt;p&gt;At POPL last week I gave a student lightning talk on
our Virtual Values &lt;a href=&quot;https://disnetdev.com/papers/virtual-values-for-language-extension&quot;&gt;paper&lt;/a&gt;.
The format was four minutes with the slides advancing every 20 seconds. Very
difficult to communicate the important idea in so short a time but it was
really fun and I think turned out pretty well.&lt;/p&gt;
&lt;p&gt;Check out the &lt;a href=&quot;https://disnetdev.com/talks/virtual_values_lightning.pdf&quot;&gt;slides&lt;/a&gt; if you&#39;re interested. I added notes on
each slide that corresponded more or less to what I was saying.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Updates to contracts.coffee</title>
		<link href="https://disnetdev.com/blog/2012-01-04-updates-to-contracts-coffee/"/>
		<updated>2012-01-04T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2012-01-04-updates-to-contracts-coffee/</id>
		<content type="html">&lt;p&gt;An update to contracts.coffee (0.2.0) is now up on npm. I&#39;ve fixed up
a few bugs since the intial release and it&#39;s now based on the
latest CoffeeScript (1.2.0)
but the big update is a rework of how modules are handled.&lt;/p&gt;
&lt;p&gt;Before this update we were handling module blame tracking by forcing the
programmer to call &lt;code&gt;.use()&lt;/code&gt; before a contracted value could be used. This
did the work of figuring out who the server and client module.&lt;/p&gt;
&lt;p&gt;This was an awkward way to enforce a module pattern since not only do you have to
write more code but it also means you have to know which values in a
module have a contract. This breaks abstraction which is bad.&lt;/p&gt;
&lt;p&gt;So with this latest update we&#39;re completely dropping &lt;code&gt;.use()&lt;/code&gt;. How we keep tack
of the modules without it depends on whether you are using node.js or a browser.&lt;/p&gt;
&lt;p&gt;If you are using node.js then the wiring is handled automatically by wrapping
the &lt;code&gt;require&lt;/code&gt; function and &lt;code&gt;exports&lt;/code&gt; object. If you put a contract on an export
value the correct server and client module names are recorded.&lt;/p&gt;
&lt;p&gt;# file Math.coffee
exports.square :: (Num) -&amp;gt; Pos
exports.square = (x) -&amp;gt; x * x&lt;/p&gt;
&lt;p&gt;#####&lt;/p&gt;
&lt;p&gt;# file Main.coffee
{square} = require &#39;./Math&#39;&lt;/p&gt;
&lt;p&gt;# vioation blaming Main.coffee
square &amp;quot;a string&amp;quot;&lt;/p&gt;
&lt;p&gt;You can also put a contract on a value that isn&#39;t on the &lt;code&gt;exports&lt;/code&gt; object (for use inside
the module), but the module name might get confusing since it&#39;s just the file name with
&amp;quot;(value)&amp;quot; or &amp;quot;(caller)&amp;quot; appened. I will look at adding something like Racket&#39;s
&lt;a href=&quot;http://docs.racket-lang.org/reference/Attaching_Contracts_to_Values.html#%28part._.Nested_.Contract_.Boundaries%29&quot;&gt;nested boundaries&lt;/a&gt;
to clean this up at some point.&lt;/p&gt;
&lt;p&gt;If you&#39;re using the browser, things are a bit more complicated. Since the browser environment
doesn&#39;t currently have a standard way to do modules, we&#39;re stuck doing the wiring by hand.
Details are in the &lt;a href=&quot;http://disnetdev.com/contracts.coffee/&quot;&gt;documentation&lt;/a&gt; but the basic idea is that
the library now provides &lt;code&gt;Contracts.exports&lt;/code&gt; and &lt;code&gt;Contracts.use&lt;/code&gt; which are used to construct
contract aware modules.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Contracts.exports&lt;/code&gt; creates and names an exports object:&lt;/p&gt;
&lt;p&gt;# Math.coffee&lt;/p&gt;
&lt;p&gt;# create and name the exports object
exports = Contracts.exports &amp;quot;Math&amp;quot;&lt;/p&gt;
&lt;p&gt;exports.square :: (Num) -&amp;gt; Pos
exports.square = (x) -&amp;gt; x * x&lt;/p&gt;
&lt;p&gt;# put the exports object on the global object
# for other modules to see and use
window.Math = exports&lt;/p&gt;
&lt;p&gt;And &lt;code&gt;Contracts.use&lt;/code&gt; pulls in a module and names the user of the module.&lt;/p&gt;
&lt;p&gt;# Main.coffee
{square} = Contracts.use window.Math, &amp;quot;Main&amp;quot;&lt;/p&gt;
&lt;p&gt;square 4          # 16
square &amp;quot;a string&amp;quot; # Contract Violation...blaming Main&lt;/p&gt;
&lt;p&gt;I&#39;ll look at ways to automate this more in future updates.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Performance of contracts.coffee</title>
		<link href="https://disnetdev.com/blog/2011-09-27-performance-of-contracts-coffee/"/>
		<updated>2011-09-27T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2011-09-27-performance-of-contracts-coffee/</id>
		<content type="html">&lt;p&gt;I&#39;ve been meaning to get around to running some performance benchmarks on contracts.coffee, but I recently learned a valuable lesson: let the internet do your work for you! :-)&lt;/p&gt;
&lt;p&gt;I woke up this morning to find &lt;a href=&quot;https://twitter.com/#!/paulmillr&quot;&gt;@paulmillr&lt;/a&gt; had put together a nice performance &lt;a href=&quot;http://jsperf.com/performance-impact-of-contracts/4&quot;&gt;benchmark&lt;/a&gt; of contracts.coffee.&lt;/p&gt;
&lt;p&gt;Check it out for all the gory details but suffice it to say contracts makes things...slow. This is about what I&#39;d expected since in addition to running the actual contract check we must wrap the contracted functions/objects in a Proxy which runs handlers for each function call or property set/get. Lots of stuff is in the way of the running code.&lt;/p&gt;
&lt;p&gt;So does the slow performance of contracts make them unusable? Not necessarily. First off, the contracts.coffee compiler can emit JavaScript with contracts completely disabled. So, you can have a &amp;quot;slow&amp;quot; testing/development build with contracts enabled to help track down bugs and a production build with contracts disabled and no slowdown.&lt;/p&gt;
&lt;p&gt;In addition, most code is IO bound not CPU bound. So if you want contracts enabled everywhere but still care about performance, be smart about where you apply them. Put them on module boundaries, but don&#39;t put them on tight loops for example.&lt;/p&gt;
&lt;p&gt;In sum, contracts are another tool in the software engineer&#39;s toolbox that have advantages (bug squashing) and disadvantages (performance slowdowns when enabled). Use them wisely.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Contracts.coffee Works In Node.js!</title>
		<link href="https://disnetdev.com/blog/2011-09-20-contracts-coffee-works-in-node-js/"/>
		<updated>2011-09-20T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2011-09-20-contracts-coffee-works-in-node-js/</id>
		<content type="html">&lt;p&gt;&lt;a href=&quot;http://disnetdev.com/contracts.coffee/&quot;&gt;Contracts.coffee&lt;/a&gt; now works in node.js! V8 (the JavaScript engine used by node) has recently added support for Proxies which contracts.coffee requires.&lt;/p&gt;
&lt;p&gt;You&#39;ll need a bleeding-edge version of node to get it running. Try either master (unstable) or &lt;a href=&quot;https://github.com/joyent/node/tree/v0.5.7&quot;&gt;0.5.7&lt;/a&gt;. Build instructions are &lt;a href=&quot;https://github.com/joyent/node/wiki/Installation&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Proxies are hidden behind a command line flag in V8 so you&#39;ll also need to supply &lt;code&gt;--harmony_proxies&lt;/code&gt; to node when calling the compiler:&lt;/p&gt;
&lt;p&gt;node --harmony_proxies bin/coffee -CL test.coffee&lt;/p&gt;
&lt;p&gt;There are almost certainly node-specific bugs in contracts.coffee so don&#39;t trust it with anything important yet. You can get started playing though!&lt;/p&gt;
&lt;p&gt;Report any bugs you run into on the &lt;a href=&quot;https://github.com/disnet/contracts.coffee/issues?sort=created&amp;amp;direction=desc&amp;amp;state=open&quot;&gt;issue tracker&lt;/a&gt;.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Duck-Typing Invariants In contracts.coffee</title>
		<link href="https://disnetdev.com/blog/2011-09-05-duck-typing-invariants-in-contracts-coffee/"/>
		<updated>2011-09-05T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2011-09-05-duck-typing-invariants-in-contracts-coffee/</id>
		<content type="html">&lt;p&gt;So the response I&#39;ve been getting for &lt;a href=&quot;http://disnetdev.com/contracts.coffee/&quot;&gt;contracts.coffee&lt;/a&gt; has been absolutely incredible! There&#39;s been tons of positive feedback and some really great excitement about the project.&lt;/p&gt;
&lt;p&gt;I&#39;ve also heard a few worries that contracts are too much like static types and might not be such a good fit for a dynamic language like CoffeeScript or JavaScript. Now, I don&#39;t want to get into a huge debate over the merits of static vs. dynamic typing (that way leads to madness and holy wars!) but I would like to clarify a few points and show that contracts actually fit quite nicely into the dynamic ethos of CoffeeScript/JavaScript.&lt;/p&gt;
&lt;p&gt;In dynamic languages like CoffeeScript and JavaScript you&#39;ll often hear about &lt;a href=&quot;http://en.wikipedia.org/wiki/Duck_typing&quot;&gt;duck-typing&lt;/a&gt; where we don&#39;t care about the &amp;quot;type&amp;quot; of an object, just the stuff on the object we actually need to use. So the classic example is a &amp;quot;file-like&amp;quot; object where all we care about are the few properties the code actually uses (like &lt;code&gt;open&lt;/code&gt;, &lt;code&gt;read&lt;/code&gt;, &lt;code&gt;close&lt;/code&gt;, etc.). As long as the properties exist we&#39;re good. If a property don&#39;t exist and we try to use it, just throw an exception so we can track down the bug.&lt;/p&gt;
&lt;p&gt;Contracts allow us to extend this concept quite a lot without sacrificing the awesome flexibility we dynamic language users love about duck-typing. To start out, let&#39;s consider the simple case of a missing property. Let&#39;s first define a contract for a binary tree:&lt;/p&gt;
&lt;p&gt;# A basic binary tree
BinaryTree = ?(Null or {
node: Num
left: Self or Null
right: Self or Null
})&lt;/p&gt;
&lt;p&gt;Pretty simple, a binary tree is either &lt;code&gt;null&lt;/code&gt; or has a &lt;code&gt;node&lt;/code&gt; and two children that are also binary trees. A function can now say it expects a &lt;code&gt;BinaryTree&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;f :: (BinaryTree) -&amp;gt; ...
f = (tree) -&amp;gt;
n = tree.node
...&lt;/p&gt;
&lt;p&gt;And if we call &lt;code&gt;f&lt;/code&gt; with something that isn&#39;t quite a binary tree:&lt;/p&gt;
&lt;p&gt;broken_tree =
nodee: 42  # misspelled!
right: null
left: null&lt;/p&gt;
&lt;p&gt;f broken_tree&lt;/p&gt;
&lt;p&gt;We get a very descriptive error message:&lt;/p&gt;
&lt;pre style=&quot;color: red&quot;&gt;
Contract violation: expected &amp;lt;{node: Num, left: self or Null,
                                right: self or Null}&amp;gt;,
  actual: &quot;[missing property: node]&quot;
Value guarded in: coffee-script.js:53
  -- blame is on: coffee-script.js:56
Parent contracts:
{node: Num, left: self or Null, right: self or Null}
Null or {node: Num, left: self or Null, righ : self or Null}
(Null or {node: Num, left: self or Null, right: self or Null})
  -&amp;gt; any
&lt;/pre&gt;
&lt;p&gt;Now we&#39;re already winning since the error message is triggered as soon as the function is called with an object that is missing the required properties. If we weren&#39;t using contracts, the variable &lt;code&gt;n&lt;/code&gt; in the example above would get the value &lt;code&gt;undefined&lt;/code&gt; which might not surface as an obvious problem until much later (if ever!).&lt;/p&gt;
&lt;p&gt;We&#39;re also not losing any of the flexibility of duck-typing
since contracts allow us to specify just the object properties the function needs in order to work properly.
We&#39;re just being explicit about how our ducks should quack!&lt;/p&gt;
&lt;p&gt;In addition to an early failure, we get lots of information in the error message about what was missing, which contract was violated, and which module was to blame (a powerful notion I explain a little &lt;a href=&quot;http://disnetdev.com/contracts.coffee/#use&quot;&gt;here&lt;/a&gt; but which really deserves a future blog post).&lt;/p&gt;
&lt;p&gt;But we&#39;re just getting warmed up :)&lt;/p&gt;
&lt;p&gt;Contracts on objects can also have arbitrary invariants that get checked whenever properties are modified. So we can have a contract for a binary search tree:&lt;/p&gt;
&lt;p&gt;# A binary search tree is a binary tree where each node is
# greater than the left child but less than the right child
BinarySearchTree = ?(Null or {
node: Num
left: Self or Null
right: Self or Null
| invariant: -&amp;gt;
(@.node &amp;gt;= @.left.node) and (@.node &amp;lt; @.right.node)
})&lt;/p&gt;
&lt;p&gt;And a &lt;a href=&quot;http://en.wikipedia.org/wiki/Red-black_tree&quot;&gt;red-black tree&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;# A red-black tree is a binary search tree
# that keeps its balance
RedBlackTree = ?(Null or {
node: Num
color: Str
left: Self or Null
right: Self or Null
| invariant: -&amp;gt;
(@.color is &amp;quot;red&amp;quot; or @.color is &amp;quot;black&amp;quot;) and
(if @.color is &amp;quot;red&amp;quot;
(@.left.color is &amp;quot;black&amp;quot; and @.right.color is &amp;quot;black&amp;quot;)
else
true
) and
(@.node &amp;gt;= @.left.node) and (@.node &amp;lt; @.right.node)
})&lt;/p&gt;
&lt;p&gt;Note that our contract for a red-black tree is exactly the same as a binary search tree with the addition of the &lt;code&gt;color&lt;/code&gt; property and some related invariants. We have a kind of subtyping going on here: a function that expects a binary search tree will also work with a red-black tree but &lt;em&gt;not&lt;/em&gt; vica versa.&lt;/p&gt;
&lt;p&gt;Now our functions can &amp;quot;duck-type&amp;quot; the invariants on the objects they accept:&lt;/p&gt;
&lt;p&gt;takesBST :: (BinarySearchTree) -&amp;gt; Any
takesBST = (bst) -&amp;gt; ...&lt;/p&gt;
&lt;p&gt;takesRedBlack :: (RedBlackTree) -&amp;gt; Any
takesRedBlack = (rbTree) -&amp;gt; ...&lt;/p&gt;
&lt;p&gt;bst = makeBinarySearchTree()
rb = makeRedBlackTree()&lt;/p&gt;
&lt;p&gt;takesBST bst # works fine
takesBST rb  # works fine&lt;/p&gt;
&lt;p&gt;takesRedBlack rb  # works fine
takesRedBlack bst # might fail if the full
# red-black invariants don&#39;t hold!&lt;/p&gt;
&lt;p&gt;These functions not only specify that they require certain properties but also that certain invariants must hold. This is really powerful! The function that only requires the behavior of a binary search tree can accept a red-black tree just fine and the function that requires the behavior of a red-black tree but is given just a binary search tree will  fail when the invariants are violated (just as we want it to).&lt;/p&gt;
&lt;p&gt;So, contracts allow us to be explicit and fail early when things go wrong while still giving us the flexibility of duck-typing. And they work for both &amp;quot;missing-property&amp;quot; kinds of failures along with a more general &amp;quot;failed invariant&amp;quot;.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Contracts.coffee - Contracts for JavaScript and CoffeeScript</title>
		<link href="https://disnetdev.com/blog/2011-08-23-contracts-coffee-contracts-for-javascript-and-coffeescript/"/>
		<updated>2011-08-23T00:00:00Z</updated>
		<id>https://disnetdev.com/blog/2011-08-23-contracts-coffee-contracts-for-javascript-and-coffeescript/</id>
		<content type="html">&lt;p&gt;This summer I&#39;ve been working at Mozilla looking at bringing the
awesomeness that is
&lt;a href=&quot;http://en.wikipedia.org/wiki/Design_by_contract&quot;&gt;contracts&lt;/a&gt; to
JavaScript. If you aren&#39;t familiar with contracts, think of them as
super powerful asserts.&lt;/p&gt;
&lt;p&gt;Why contracts? Because they allow us to build
better software! They allow us to express invariants (things that will
always be true about our code) in JavaScript about JavaScript and
check at runtime that these invariants hold. And when things break
(like they always do) we get a precise error message pin-pointing the
part of our code the broke the contract.&lt;/p&gt;
&lt;p&gt;Contracts in programming languages were first popularized in the
language Eiffel. In fact, the people behind Eiffel promoted an entire
design methodology centered around contracts (called, appropriately
enough, Design by Contract™) that encouraged thinking about invariants and
interfaces between software component boundaries.&lt;/p&gt;
&lt;p&gt;So if contracts are so great why don&#39;t we see them in JavaScript?
Well, for the most part, the languages that have supported contracts in
the past all share an important characteristic...no lambdas. Or more
specifically in Java and Eiffel functions are not first class (you
can&#39;t pass a function in a method call). Traditional contract systems
fall down in a higher order setting (how do you check a function
argument?).&lt;/p&gt;
&lt;p&gt;Until, that is, the scheme people (err...I mean
&lt;a href=&quot;http://racket-lang.org/&quot;&gt;Racket&lt;/a&gt; people) figured out
&lt;a href=&quot;http://www.eecs.northwestern.edu/~robby/pubs/papers/ho-contracts-techreport.pdf&quot;&gt;what to do&lt;/a&gt;
a few years ago. Now, Racket has a very nice contract system.&lt;/p&gt;
&lt;p&gt;But we haven&#39;t seen anything comparable to Racket&#39;s contracts in
JavaScript so far. So this summer I looked into taking the work that
was done in Racket and trying to fit it into JavaScript. As you
probably know, JavaScript has a bit of scheme in it (just confused by
some C/Java syntax).&lt;/p&gt;
&lt;p&gt;The result of this exploration is a JavaScript libarary called
&lt;a href=&quot;https://github.com/disnet/contracts.js&quot;&gt;contracts.js&lt;/a&gt; and
a fork of the
&lt;a href=&quot;http://jashkenas.github.com/coffee-script/&quot;&gt;CoffeeScript&lt;/a&gt; compiler
(which translates CoffeeScript directly to JavaScript) called
&lt;a href=&quot;http://disnetdev.com/contracts.coffee/&quot;&gt;contracts.coffee&lt;/a&gt;.
The JavaScript library gives us the ability to apply contracts to our
code and the CoffeeScript extension gives us some really pretty
syntax.&lt;/p&gt;
&lt;p&gt;So what does it all look like?&lt;/p&gt;
&lt;p&gt;Here&#39;s some CoffeeScript code with contracts:&lt;/p&gt;
&lt;p&gt;id :: (Num) -&amp;gt; Num
id = (x) -&amp;gt; x&lt;/p&gt;
&lt;p&gt;And the JavaScript translation:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; id &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;guard&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
     &lt;span class=&quot;token function&quot;&gt;fun&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Num&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; Num&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
     &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; x&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This code takes the identity function and wraps it in a
function contract. Now every time &lt;code&gt;id&lt;/code&gt; is called the contract library
first checks that the argument being passed in satisfies the &lt;code&gt;Num&lt;/code&gt;
contract (which checks the the value is a &lt;code&gt;number&lt;/code&gt;) and that the
result of &lt;code&gt;id&lt;/code&gt; also satisfies &lt;code&gt;Num&lt;/code&gt;. If any of these checks fail, an
error is thrown. For example:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token function&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre style=&quot;color: red&quot;&gt;
Error: Contract violation: expected &amp;lt;Number&amp;gt;, actual: &quot;string&quot;
Value guarded in: id_module.js:42
  -- blame is on: client_code.js:104
Parent contracts: (Number) -&gt; Number
&lt;/pre&gt;
&lt;p&gt;Pretty nifty right?&lt;/p&gt;
&lt;p&gt;We can also have contracts on objects:&lt;/p&gt;
&lt;p&gt;person ::
name: Str
age: Num
person =
name: &amp;quot;Bertrand Meyer&amp;quot;
age: 42&lt;/p&gt;
&lt;p&gt;And arrays:&lt;/p&gt;
&lt;p&gt;loc :: [...Num]
loc = [99332, 23452, 123, 2, 5000]&lt;/p&gt;
&lt;p&gt;And various combinations thereof:&lt;/p&gt;
&lt;p&gt;average :: ({name: Str, age: Num}, [...Num]) -&amp;gt; Str
average = (person, loc) -&amp;gt;
sum = loc.reduce (s1, s2) -&amp;gt; s1 + s2
&amp;quot;#{person.name} wrote on average
#{sum / loc.length} lines of code.&amp;quot;&lt;/p&gt;
&lt;p&gt;You can find documentation, install instructions, and a bunch more
examples for contracts.coffee at its
&lt;a href=&quot;http://disnetdev.com/contracts.coffee/&quot;&gt;website&lt;/a&gt;. Docs for the
underlying contracts.js library is coming soon but for now just check
out the &lt;a href=&quot;https://github.com/disnet/contracts.js&quot;&gt;github&lt;/a&gt; page.&lt;/p&gt;
&lt;p&gt;This is still very much a work in progress and I would love
feedback. Let me know if you find it useful!&lt;/p&gt;
</content>
	</entry>
</feed>
