<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Brain on Fire</title>
	<atom:link href="http://www.brainonfire.net/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.brainonfire.net/blog</link>
	<description>Tim McCormack, distilled</description>
	<lastBuildDate>Sat, 18 Feb 2012 04:49:22 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>On the immiscibility of higher order functions and unboxed invocation in Clojure</title>
		<link>http://www.brainonfire.net/blog/hof-vs-prim-invoke-clojure/</link>
		<comments>http://www.brainonfire.net/blog/hof-vs-prim-invoke-clojure/#comments</comments>
		<pubDate>Sat, 18 Feb 2012 01:30:32 +0000</pubDate>
		<dc:creator>Tim McCormack</dc:creator>
				<category><![CDATA[-no category-]]></category>
		<category><![CDATA[boxing]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[compiler]]></category>
		<category><![CDATA[hinting]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[primitives]]></category>
		<category><![CDATA[reflection]]></category>

		<guid isPermaLink="false">http://www.brainonfire.net/blog/?p=893</guid>
		<description><![CDATA[Recently, Tim McIver and I set out to bring clojure.contrib.import-static into the modern world. This is lib that looks on the surface to be quite handy: (import-static java.lang.Math sqrt PI) allows you to write (sqrt PI) instead of (Math/sqrt Math/PI). The huge downside is that sqrt is a macro, so it can't be passed around [...]]]></description>
			<content:encoded><![CDATA[<p>Recently, <a href="http://timmciver.com/">Tim McIver</a> and I set out to bring <a href="http://clojuredocs.org/clojure_contrib/1.2.0/clojure.contrib.import-static">clojure.contrib.import-static</a> into the modern world. This is lib that looks on the surface to be quite handy: <code>(import-static java.lang.Math sqrt PI)</code> allows you to write <code>(sqrt PI)</code> instead of <code>(Math/sqrt Math/PI)</code>. The huge downside is that <code>sqrt</code> is a macro, so it can't be passed around as in <code>(map sqrt (range 10))</code>. (This <em>does</em> allow (with appropriate hinting) primitive invocation (non-boxed passing of primitive JVM types such as long and double) and reflection at compile-time instead of runtime.) Our idea was to replace import-static with def-statics, a macro that could produce prim-invocable functions instead of macros.</p>

<p>Summary: You can't actually do that. HOFs in a dynamically-typed language are not compatible with unboxed primitive invocation.</p>



<p>Our <a href="https://github.com/baznex/imports/blob/44b12db813c2605d1c6b0492018070091f736f9c/src/org/baznex/imports.clj">first pass</a> used <a href="http://clojuredocs.org/clojure_core/1.3.0/clojure.core/proxy">proxy</a> to create a fn that implemented <a href="https://github.com/clojure/clojure/blob/1.3.x/src/jvm/clojure/lang/AFn.java">clojure.lang.AFn</a>, a convenience implementation of IFn, which is the interface the compiler uses to recognize function-like things. For reasons that I am not well-versed in, IFn declares 21 arities of invoke (among other methods) that all take and return Objects. AFn implements these with throwing methods that can be overridden. Besides the fairly involved <code>gen-class</code>, <code>proxy</code> is the only API Clojure provides for subclassing a concrete class, which is a highly discouraged action. (We didn't want to reimplement AFn in order to use reify -- it was more work than necessary.) We finally managed to produce code like this:</p>

<pre class="code">user=&gt; (binding [*print-meta* true] (clojure.pprint/pprint (macroexpand-1 '(org.baznex.imports/def-statics Math abs))))
(do
 (def
  ^{:doc "java.lang.Math/abs via def-statics", :private true} abs
  (clojure.core/proxy
   [clojure.lang.AFn clojure.lang.IFn$LL clojure.lang.IFn$DD] []
   (^java.lang.Object invoke [^java.lang.Object p_167]
                      (. java.lang.Math abs p_167))
   (^long invokePrim [^long p_168]
          (. java.lang.Math abs ^long p_168))
   (^double invokePrim [^double p_169]
            (. java.lang.Math abs ^double p_169)))))</pre>

<p>This gets us an implementation not just of IFn, allowing the compiler to pick it up as a function, but also as an IFn$LL and IFn$DD -- 2 of <a href="https://github.com/clojure/clojure/blob/1.3.x/src/jvm/clojure/lang/IFn.java#L91">358 special interfaces introduced in Clojure 1.3.0</a> that indicate that the function is capable of being invoked with or returning an unboxed primitive.</p>

<p>And that's when we discovered that <code>proxy</code> only supports overloading by arity:</p>

<pre class="code">user=&gt; (org.baznex.imports/def-statics Math abs)
CompilerException java.lang.IllegalArgumentException: Method 'invokePrim' redefined, compiling:(NO_SOURCE_PATH:4)</pre>

<p>I bit the bullet and <a href="https://github.com/baznex/imports/blob/7754d3a565a4db47b68cdf1e86bb6edf6bb8cbbd/src/org/baznex/imports.clj">rewrote</a> def-statics using <code><a href="http://clojuredocs.org/clojure_core/1.3.0/clojure.core/reify">reify</a></code> instead. This meant writing something to loop through all 21 possible arities of <code>invoke</code> (as well as some extra methods), but it got done. The output was horrible (and this is the short version:)</p>

<pre class="code">user=&gt; (binding [*print-meta* true] (clojure.pprint/pprint (macroexpand-1 '(org.baznex.imports/def-statics Math abs))))
(do
 (def
  ^{:doc "java.lang.Math/abs via def-statics", :private true} abs
  (clojure.core/reify

   clojure.lang.IFn

   ;; eliding .run, .call, and .applyTo
   (invoke
    [^clojure.lang.IFn this__144__auto__]
    (throw (clojure.lang.ArityException. 0 "java.lang.Math/abs")))
   (invoke
    [this__137__auto__ ^java.lang.Object p_449]
    (clojure.core/println "Invoked"
     "{:args nil, :ret java.lang.Object, :params (java.lang.Object), :prim nil}")
    (. java.lang.Math abs p_449))
   (invoke
    [^clojure.lang.IFn this__144__auto__ arg450 arg451]
    (throw (clojure.lang.ArityException. 2 "java.lang.Math/abs")))
   (invoke
    [^clojure.lang.IFn this__144__auto__ arg452 arg453 arg454]
    (throw (clojure.lang.ArityException. 3 "java.lang.Math/abs")))
   (invoke
    [^clojure.lang.IFn this__144__auto__ arg455 arg456 arg457 arg458]
    (throw (clojure.lang.ArityException. 4 "java.lang.Math/abs")))
   (invoke
    [^clojure.lang.IFn this__144__auto__ arg459 arg460 arg461 arg462 arg463]
    (throw (clojure.lang.ArityException. 5 "java.lang.Math/abs")))
   ;; eliding arities 6 through 19
   (invoke
    [^clojure.lang.IFn this__144__auto__ arg639 arg640 arg641 arg642 arg643
     arg644 arg645 arg646 arg647 arg648 arg649 arg650 arg651 arg652 arg653
     arg654 arg655 arg656 arg657 arg658]
    (throw (clojure.lang.ArityException. 20 "java.lang.Math/abs")))   
   ;; eliding the weird varargs arity

   clojure.lang.IFn$LL

   (^long invokePrim
    [this__137__auto__ ^long p_447]
    (clojure.core/println
     "Invoked"
     "{:prim clojure.lang.IFn$LL, :ret long, :params (long), :args [long]}")
    (. java.lang.Math abs (long p_447)))

   clojure.lang.IFn$DD

   (^double invokePrim
    [this__137__auto__ ^double p_448]
    (clojure.core/println
     "Invoked"
     "{:prim clojure.lang.IFn$DD, :ret double, :params (double), :args [double]}")
    (. java.lang.Math abs (double p_448))))))</pre>

<p>Note the debugging printlns -- they were the only way I could tell if prim-invocation was occurring. Let's see it in action:</p>

<pre class="code">user=&gt; (abs (long 5))
Invoked {:args nil, :ret java.lang.Object, :params (java.lang.Object), :prim nil}
5</pre>

<p>Oops! We're only getting .invoke, not .invokePrim. With a little <a href="https://github.com/clojure/clojure/blob/1.3.x/src/jvm/clojure/lang/Compiler.java#L3472">poking around in clojure.lang.Compiler</a>, I discovered that arglists are important. Specifically, the type-hinting on the arglists. Here's an example of what they look like:</p>

<pre class="code">user=&gt; (defn noop [^long x] nil)
#'user/noop
user=&gt; (binding [*print-meta* true] (prn (:arglists (meta #'noop))))
([^long x])</pre>

<p>This function is eligible for prim-invocation (that was a lie, and you'll see why in a minute) as confirmed by injecting some print statements into the compiler. So let's add some arglists to that reify!</p>

<pre class="code">(do
 (def
   ^{:doc "java.lang.Math/abs via def-statics", :private true
     :arglists `([^double x] [^long x] [x])} abs
  (clojure.core/reify

...</pre>

<p>It doesn't work. Depending on exactly which function you try to reify, you'll get different results, so I'll just tell you the punchline: Compiler.java picks the first arity that matches the function call and runs with it. In this case, the <code>[^double x]</code> arglist is picked <em>every time</em>, leading to either casting, a cast exception, or a call to regular ol' .invoke. The compiler is completely incapable of choosing the correct IFn (or IFn$___ interface) invocation when there are multiple options for an arity.</p>

<p>But wait, there's more! After further investigation, I discovered that <code>(map abs (range -3 3))</code> will <em>always</em> result in a call to invoke, or even worse, a runtime reflective call. Remember that <strong>:arglists is only present on the Var</strong>, not the IFn. (There's the lie exposed.) With <code>(abs -5)</code>, Compiler.java sees that the call-position of the expression is occupied by a reference to a Var, and it is able to look up arglist info at parse-time. (There's some def-hoisting going on here that I don't entirely follow yet.) The IFn itself isn't available until runtime in all other cases, such as <code>((if P=NP? abs-LL abs-DD) -5)</code>, so bytecode cannot be generated with full knowledge of what optimizations might be available. The takeaway here is that the compiler can only work with whatever type info is statically available at the callsite, and since prim-invocation is a property of the IFn, only Vars of IFns can be optimized for unboxed primitive invocation.</p>

<p>And higher-order-functions? They pretty much <em>never</em> provide hinting information that the compiler could use. Remember that deep down inside <code>(map abs (range -3 3))</code>, the actual callsite we care about looks like <code>(f (first s))</code>. Completely vanilla. If we were using Java or Haskell or some other statically typed language, this information could be carried down inside the map call and used -- but Clojure is dynamic, so HOFs and prim invoke simply cannot mix.</p>

<p><b>Postscript:</b> We plan to remove prim-invocation from the code and go back to proxy'ing AFn. We'll still be able to use hinting sometimes  for its other, completely different purpose: Avoiding reflection. For instance, String/valueOf has a single ternary overload, so we can hint the actual call inside the ternary invoke. Farther down the road, we may combine def-statics and import-static so that users can choose whether they'd like each "import" to be a hinting macro or a boxing, reflecting function.</p>]]></content:encoded>
			<wfw:commentRss>http://www.brainonfire.net/blog/hof-vs-prim-invoke-clojure/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Some brief notes on spam</title>
		<link>http://www.brainonfire.net/blog/some-brief-notes-on-spam/</link>
		<comments>http://www.brainonfire.net/blog/some-brief-notes-on-spam/#comments</comments>
		<pubDate>Tue, 01 Nov 2011 13:22:27 +0000</pubDate>
		<dc:creator>Tim McCormack</dc:creator>
				<category><![CDATA[-no category-]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[spam]]></category>

		<guid isPermaLink="false">http://www.brainonfire.net/blog/?p=876</guid>
		<description><![CDATA[It was probably a mistake to use a catchall account and make up addresses on the fly. Now I get spam on every address that is published! I may do something like the fellow at unstable.nl does and have a dedicated spam address that allows me to deduplicate those, but I haven't yet figured out [...]]]></description>
			<content:encoded><![CDATA[<ul>
  <li>It was probably a mistake to use a catchall account and make up addresses on the fly. Now I get spam on every address that is published! I may do something like the fellow at unstable.nl does and have a dedicated spam address that allows me to deduplicate those, but I haven't yet figured out how to do that in Claws Mail.</li>
  <li>I think spammers may be avoiding honeypots by preferring email addresses that are very likely to be real -- such as those on Bugzilla sites.</li>
  <li>I recently switched my hosting service for my brainonfire.net email address from Lavabit (horrible customer service) to Cotse (they seem like good folks), but I still receive spam at Lavabit! I think spammers are caching MX records. This could be used against them.</li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.brainonfire.net/blog/some-brief-notes-on-spam/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to move personal publishing to the desktop</title>
		<link>http://www.brainonfire.net/blog/moving-personal-publishing-desktop/</link>
		<comments>http://www.brainonfire.net/blog/moving-personal-publishing-desktop/#comments</comments>
		<pubDate>Thu, 12 May 2011 01:34:31 +0000</pubDate>
		<dc:creator>Tim McCormack</dc:creator>
				<category><![CDATA[Proposal]]></category>
		<category><![CDATA[cloud]]></category>
		<category><![CDATA[privacy]]></category>
		<category><![CDATA[publishing]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[social networking]]></category>
		<category><![CDATA[somebody make this]]></category>

		<guid isPermaLink="false">http://www.brainonfire.net/blog/?p=852</guid>
		<description><![CDATA[You can do everything "in the cloud" these days, from blogging to posting photos to running servers. Most impressively, you can now also lose control of your files and personal information with unprecedented ease, or simply lose it, period. This is exactly the worst possible feature for the personal publishing use-cases of cloud computing. Possibly [...]]]></description>
			<content:encoded><![CDATA[<p>You can do everything "in the cloud" these days, from blogging to posting photos to running servers. Most impressively, you can now also <a href="http://mashable.com/2010/03/31/facebook-bug/">lose control of your files and personal information</a> with unprecedented ease, or <a href="https://secure.wikimedia.org/wikipedia/en/wiki/Gnolia">simply lose it</a>, period. This is exactly the worst possible feature for the personal publishing use-cases of cloud computing. Possibly the most distressing aspect of cloud-based publishing is that it firmly designates the intangible network as the primary resting place of one's data. (I will note here that this aspect is itself what I am using to define "cloud computing" for the purposes of this blog post.) If the first place you put your creations is some hosted service on the great wide interwebs, you're playing with fire.</p>



<p>As it stands, the cloud is <em>not safe</em> for primary storage. I lost some data in the Magnolia bookmarking service fiasco myself, with my most recent backup several weeks before the crash. I only backed up my bookmarks when I remembered to, not having the time to work up an automated downloading script. Now I save all my bookmarks locally, and my twice-weekly backup takes care of everything. My <a href="http://gallery.brainonfire.net/">online photo gallery</a> is not in any similar danger, because I wrote it myself with such a failure mode in mind. The photos and tags and descriptions live on my laptop and propagate from there out to my public website. Images and tags that I don't want to be public never even leave my machine.</p>

<p>Why do people use the cloud, then? To put it simply, <strong>front-end convenience</strong>. I can create a Flickr or Numsum account in minutes, and right away I have a URL I can point my friends to to see what I have created. The cost (lost data) only comes much later. These hosted applications also present a reduced computer security risk to users, compared to desktop-based publishing software such as my photo gallery uses. If you want to use my application, you have to trust my code and run it on your own machine. However, Flickr only runs Javascript on your machine, safely sandboxed in your browser.</p>

<p>I want <em>all</em> of our current hosted-publishing systems move to the desktop. Clearly, a competitive answer to the cloud/hosted systems of today must compete on both convenience and easy security. Using an application must be as easy as surfing the web, and publishing photos, text, and video must only take a few clicks of the mouse.</p>

<p>What I envision is a desktop platform that allows users to download from the web and run (in a sandbox) any compatible software in a single click, where each application is given fine-grained permission to talk with other applications, read and write user data, and publish to the web, and a peer-to-peer communication system for non-public publishing (e.g. LiveJournal-like friend-locked blogging.) Since most users will not have always-on desktops, communications and storage would be optionally mediated by paid and freemium hosted services serving only as relays for encrypted user data.</p>

<p>With this imagined software, a user would be able to get started with photo publishing by finding a good-looking gallery application's website, clicking a special URL, and approving installation. Perhaps the user would then approve the application's request for 1) read-only access to a specified photo directory and 2) publishing permissions (to the public web, approved peers' inboxes, and relay servers). The application might provide a tagging and organization interface itself, or possibly just scrape data out of KPhotoAlbum, FSpot, and Picasa's databases. The user would connect certain tags to defined groups in their master contact list, allowing e.g. grandparents to be shown different sets of photos than coworkers.</p>

<p>Now imagine that at platform installation time, users are provided with a brand-new set of encryption keys and instructed how to hold key-signing parties, assisted by the platform's authentication module. Privacy-sensitive content (photos, blog entries, video, source code) would be created on the desktop, encrypted to group and personal public keys, distributed on personal and paid servers or via P2P, and downloaded to peer machines. At no point would the prime copy of a user's creations be offsite -- and at no time would personal information be out of the control of the user or those they trust with it.</p>

<p>This project is totally feasible in technical and social terms. It could revolutionize user privacy and even be the required bootstrap for layman's practical encrypted communication. It just needs the right group of people to start the work. Comment if you think you could be one of those people.</p>]]></content:encoded>
			<wfw:commentRss>http://www.brainonfire.net/blog/moving-personal-publishing-desktop/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Wanted: Chained package management</title>
		<link>http://www.brainonfire.net/blog/wanted-chained-package-management/</link>
		<comments>http://www.brainonfire.net/blog/wanted-chained-package-management/#comments</comments>
		<pubDate>Fri, 04 Mar 2011 15:57:48 +0000</pubDate>
		<dc:creator>Tim McCormack</dc:creator>
				<category><![CDATA[Proposal]]></category>

		<guid isPermaLink="false">http://www.brainonfire.net/blog/?p=834</guid>
		<description><![CDATA[One of the minor pain points (but a major surprise point) of using the Ubuntu Linux package management system occurs when upgrading an application that itself implements package management. A classic example of this is Firefox, which has an extension system with a central repository, version compatibility checking, and automatic updates. On local installs of [...]]]></description>
			<content:encoded><![CDATA[<p>One of the minor pain points (but a major <a href="https://secure.wikimedia.org/wikipedia/en/wiki/Principle_of_least_astonishment"><em>surprise</em> point</a>) of using the Ubuntu Linux package management system occurs when upgrading an application that itself implements package management. A classic example of this is Firefox, which has an extension system with a central repository, version compatibility checking, and automatic updates.</p>

<p>On local installs of Firefox (or in Windows), Firefox handles its own upgrades, and has the ability to warn the user if any extensions will be disabled due to incompatibility with the new Firefox version. However, when Firefox is managed by an external agent such as APT, no such warning can take place. (There's another problem here—upgrading Firefox when it is running results in gradual bitrot of the running process as it loads mismatched bits of itself from disk.)</p>

<p>This is totally a solvable problem. Deb packages can contain pre-install scripts that check for bad install or upgrade conditions, and I would bet they can also prompt the user for input in questionable circumstances, such as forced disabling of extensions. There's the minor issue of how to handle multiple user accounts, networked /home, etc., but these all seem solvable with a reasonable amount of effort.</p>

<p>I suspect this post will be too late to influence the Firefox 4 release, but I'm <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=638799">filing an enhancement request</a> anyway. Hopefully the developers of other apps with package managers will take this advice as well.</p>]]></content:encoded>
			<wfw:commentRss>http://www.brainonfire.net/blog/wanted-chained-package-management/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Emacs quick start: One n00b to another.</title>
		<link>http://www.brainonfire.net/blog/emacs-n00b-start/</link>
		<comments>http://www.brainonfire.net/blog/emacs-n00b-start/#comments</comments>
		<pubDate>Sat, 26 Feb 2011 20:52:08 +0000</pubDate>
		<dc:creator>Tim McCormack</dc:creator>
				<category><![CDATA[-no category-]]></category>

		<guid isPermaLink="false">http://www.brainonfire.net/blog/?p=821</guid>
		<description><![CDATA[I recently got started using Emacs, and I was surprised to see just how bad most of the quick-start guides are. Most lacked the basic commands and definitions that beginners really need. This is my attempt to do better. I'm a n00b myself, so there won't be much explanation, just a basic overview, some useful [...]]]></description>
			<content:encoded><![CDATA[<p><i>I recently got started using Emacs, and I was surprised to see just how bad most of the quick-start guides are. Most lacked the basic commands and definitions that beginners really need. This is my attempt to do better. I'm a n00b myself, so there won't be much explanation, just a basic overview, some useful starter commands, and links to proper tutorials.</i></p>



<p>NB: Emacs is not one thing. This post is abut GNU Emacs 23.</p>

<p>Most interaction with Emacs (besides normal typing of text) is via the issuance of commands. These commands almost exclusively involve modifiers like Control and Meta, which correspond to Ctrl and Alt on most keyboards. If you see the keyboard shortcut <code>M-x</code>, you should type the [X] key while holding down [Alt]. Similarly, <code>C-h</code> means [Control]-[h]. Some commands involve a sequence of keystrokes. You can remap all of these later if you wish. (You should also familiarize yourself with <a href="http://xahlee.org/emacs/keystroke_rep.html">some other key and character conventions</a>.)</p>

<p>Here are your first commands: <code>C-g</code> will cancel just about anything (a command in progress, a selection, etc.) and <code>C-x C-c</code> will quit the program. Note that C-x in most programs is "Cut to clipboard"—this is not what it is bound to in Emacs. In fact, none of the usual keyboard shortcuts apply. You'll learn about their replacements soon.</p>

<a href="/blog/wp-content/uploads/2011/02/emacs23-start.png" class="thumblink"><img src="/blog/wp-content/uploads/2011/02/emacs23-start-150x150.png" alt="Diagram of Emacs start screen" title="Click to embiggen" width="150" height="150"/><span class="caption"></span></a>

<p>When you first launch Emacs, you will probably see a single window split into two panes, one above the other. (Emacs calls this a vertical split instead of a horizontal split, confusingly, but we'll stick with the convention.) These panes are called <strong>windows</strong> in the rest of this document. You have a cursor in each one, but only one will be blinking and active. This is the current window. Want to get rid of all windows except the current one? Use <code>C-x 1</code> to do that. <code>C-x 0</code> will close the current window.</p>

<p>The stuff you see inside each window is a <strong>buffer</strong>, which can be anything from a command line to a document to an interactive settings file. You can have a bunch of buffers open at any given time, and each window can be targeted to show any one of them. You will usually just have one window open and keep switching which buffer is being viewed in it. <code>C-x b</code> will give you an interactive prompt that will let you swap out which buffer you are using, and <code>C-x C-b</code> will give you the full list in the current window until you position your cursor over the one you want and hit [enter].</p>

<p>Emacs is always in one <strong>major mode</strong> at any given time. Major modes generally change with your programming language, and affect syntax highlighting, autocompletion, compilation, etc. There are also minor modes, which can coexist peacefully. Most notably, modes change what certain commands <em>mean</em>. There's a command to move forward by one word, but the meaning of "word" changes between programming languages. (If you're using an s-expression language, for instance, you'll <em>really</em> want the Paredit mode, which lets you sling parens like a master.)</p>

<p>Undo mistakes with <code>C-/</code>. If it really <em>wasn't</em> a mistake after all, you'll still be able to get it back later by undoing some more!</p>

<p>Now that you know the <em>real</em> basics, you're ready to look at all those other Emacs tutorials! Your next steps:</p>

<ol>
  <li>Open and save files</li>
  <li>Keyboard navigation (and why the arrow keys can be trouble)</li>
  <li>Undo, and redoing by undoing</li>
  <li>Selection</li>
  <li>Killing and yanking are not just different words for cutting and pasting</li>
  <li>Understanding, installing, and enabling modes</li>
  <li>How to use the amazing help system (<code>C-h</code>)</li>
</ol>

<p>I'll add to and modify this document as my own understanding progresses.</p>

<p>Oh yeah, and here's some common stuff that isn't mentioned in regular guides:</p>

<ul>
  <li>Trying to save to a new filename that has a space in it, and Emacs isn't letting you? <code>C-q space</code> will put in a literal space.</li>
  <li>Want to put a newline character in a search or replace pattern? <code>C-q C-j</code> inserts a ^J (line-feed character), which is usually what you want. In DOS mode you'll need to insert an ^M (carriage return) before the line feed, otherwise some programs <a href="http://jeremy.zawodny.com/blog/archives/008872.html#comment-35750">might freak out</a>.</li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.brainonfire.net/blog/emacs-n00b-start/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Misbalanced parens + hoisted defn = surprising runtime error in Clojure code</title>
		<link>http://www.brainonfire.net/blog/parens-defn-hoist-runtime-error-clojure/</link>
		<comments>http://www.brainonfire.net/blog/parens-defn-hoist-runtime-error-clojure/#comments</comments>
		<pubDate>Sun, 16 Jan 2011 02:26:30 +0000</pubDate>
		<dc:creator>Tim McCormack</dc:creator>
				<category><![CDATA[Solutions]]></category>

		<guid isPermaLink="false">http://www.brainonfire.net/blog/?p=809</guid>
		<description><![CDATA[Today I ran into a frustrating syntax pitfall in Clojure, which I am attempting to learn using a simple homework assignment as motivation. Below is a simplified testcase containing the same mistake I had in my actual code. The code compiles, but at runtime I receive "java.lang.IllegalStateException: Var selfr is unbound.". (defn magic [] (println [...]]]></description>
			<content:encoded><![CDATA[<p>Today I ran into a frustrating syntax pitfall in Clojure, which I am attempting to learn using a simple homework assignment as motivation. Below is a simplified testcase containing the same mistake I had in my actual code. The code compiles, but at runtime I receive "java.lang.IllegalStateException: Var selfr is unbound.".</p>

<pre class="code" lang="Clojure">(defn magic []
  (println "magic happens") ; one too few closing parens

(defn selfr [i]
  (if (&lt; i 0)
    0
    [(selfr (dec i))
     (selfr (dec i))]))) ; one too many closing parens

(defn selfr-caller []
  (selfr 3))

(defn -main [&#038; args]
;  (magic) ; uncomment to make everything work
  (println (selfr-caller)))</pre>

<p>If you stare at the code for a bit, you'll see that <code>selfr</code> is defined <em>inside</em> the <code>magic</code> function. So why doesn't the compiler complain that <code>selfr-caller</code> can't see it? What I didn't realize until today (with the help of some wonderful people on IRC) was that <code>defn</code> hoists the declaration to the top-level, where everything can see it... but the <em>assignment</em> won't occur until the code block is actually run.</p>

<p>This kind of bug is extraordinarily tricky to find, since it is ultimately a syntax error but may not show symptoms depending on the execution order of the code. I suppose this could have been prevented by having a better editor, such as one with draconian indentation support (e.g. Emacs) or perhaps a matching-paren highlighting feature.</p>]]></content:encoded>
			<wfw:commentRss>http://www.brainonfire.net/blog/parens-defn-hoist-runtime-error-clojure/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>

