Saturday, October 08, 2011
code-imports
As opposed to the earlier incarnation, I've extracted as much as the logic as possible into purely functional functions, which makes it easy to test. In my experience, import management is complicated enough that manual testing is just not enough to ensure a stable product. Testing the code thoroughly is one way to solve this problem. I've also simplified the number of concepts in the code, and the number of variable to tweak to the bare minimum.
I'm going to refine this a bit, then announce it more broadly shortly.
Saturday, April 09, 2011
A brief demonstration of emacs new lexical bindings
To enable it, you need to set lexical-binding to t. This is buffer local, so you need to set it for every buffer that you want to have lexical binding in.
Here's a demonstration in an ielm session (M-x ielm).
ELISP> (setq lexical-binding t)Without lexical binding, the variable x would be a dynamic variable, and so when we set it to 100 later in the session, the 1-adder would change to a 100-adder inadvertently. In fact, if we try, we can't even get to that point. Here's the same session without lexical binding:
t
ELISP> (defun make-adder (base) (lambda (num) (+ num base)))
make-adder
ELISP> (setq x 1)
1
ELISP> (setq 1-adder (make-adder x))
(closure
((base . 1)
t)
(num)
(+ num base))
ELISP> (funcall 1-adder 10)
11
ELISP> (funcall 1-adder 100)
101
ELISP> (setq x 100)
100
ELISP> (funcall 1-adder 100)
101
ELISP> lexical-bindingWhat's going on here? Notice that when we make the 1-adder without lexical binding, we don't get a closure. Instead, we just get a function that references num and base. num is passed into the function, but base is a dynamic variable, so it is interpreted in the emacs global context, as opposed to a context inside a closure. The variable base is not bound to a value in the global context, and when we execute the lambda, which refers to base, emacs looks for the base variable, cannot find it, and throws an error.
nil
ELISP> (defun make-adder (base) (lambda (num) (+ num base)))
make-adder
ELISP> (setq x 1)
1
ELISP> (setq 1-adder (make-adder x))
(lambda
(num)
(+ num base))
ELISP> (funcall 1-adder 10)
*** Eval error *** Symbol's value as variable is void: base
This doesn't happen with lexical binding. In that case, we can actually see the closure itself being returned when there is lexical binding:
(closureThe closure here shows a structure in which we can interpret to mean that base is being bound to 1. You can also see num is the argument (since it is not in the same s-expression as the binding of base), and then it proceeds with the simple addition function.
((base . 1)
t)
(num)
(+ num base))
I haven't yet made use of closures in my emacs code. I don't really need it in my initialization files, and if I writes modules that assume it then almost no one can yet use it. So I'll give it time, but it's a huge step in making elisp a better lisp. Read more about lexical bindings Paul Graham's wonderful free book On Lisp.
Lexical bindings are not only a good feature in themselves, they are also is an important step on the way to multithreading. Having nothing but global variables makes threading quite challenging, and lexical bindings in the standard elisp packages can help make multithreading easier.
Monday, March 21, 2011
Data
Humans are not very good at remembering event frequency statistics. We tend to only remember the unusual, and forget about the common case. There are plenty of other cognitive errors we make, but this seems to me one of the most troublesome.
An example: Every day I take the subway from Forest Hills in Queens to Manhattan. Either the E or F train will arrive first, and I need the E train. I was noticing, though, that it always seemed to be the F train arriving first, making me wait for an extra few minutes.
Why would that be? Could it be a situation like Feynman's girlfriend puzzle, where the E train closely follows the F? I decided to keep some statistics to find out.
Every day, I'd record which train came first. After a few days, I noticed the E had been coming first lately. Surely a fluke.
I kept at it, and before long the trend was clear. The E comes first almost twice as often! I counted 18 E firsts, and only 10 F firsts.
Obviously, I was completely wrong about even the most basic statistics for my morning commute, and that's about something I experience every single workday morning. Think how wrong I can be about everything else!
I take this as a warning about not trusting experiences when making decisions. Get data instead. Even just some data will be better than opinion or memories.
Wednesday, January 05, 2011
Does everything have to be social?
All I wanted to do was to download a document. To do that, I had to sign up for Scribd via my Facebook account. Next thing I know, I am getting follower notifications emails from some of my Facebook friends.
I just wanted to download a document. Now I'm connected to all sorts of friends. What do they want from me? Did they even explicitly choose to friend me or was it automatically done by Scribd?
For the time being, I'm just going to ignore it all and hope it goes away.