display | more...
Recently, while doing some low-level programming that involved a lot of binary and hexadecimal math, I became frustrated with my traditional programmer's calculator. Switching from my editor's keyboard driven interface to the calculator's mouse and GUI interface was jarring, and cutting and pasting values between the two was clumsy.

It occurred to me that my editor, the venerable Emacs, certainly had the capability to do this kind of thing. After all, at the heart of Emacs lies a lisp interpreter, a high level language in which the majority of Emacs is coded. While I am by no means a true lisp hacker, I've played around with it a bit, and thought surely it has the tools to do simple hexadecimal math.

As it turns out, Emacs is indeed capable of this task, one might even say well-suited to it. Keeping in mind a few minor limitations, I've switched completely over to Emacs as my programmer's calculator on those rare occasions when one is needed.

Using the Lisp Interpreter

There are two main ways to access Emacs's internal lisp interpreter. The first is lisp interaction mode. Each file opened in Emacs (called buffers in Emacs terminology, since a buffer doesn't always map to a file) has a mode, that provides custom key mappings and behaviors suited for that type of content. There is c-mode for C source code, xml-mode for XML, and so forth. Lisp interaction mode is a special mode for interactive lisp sessions. It can invoked by running the lisp-interaction-mode command, but Emacs automatically creates a buffer called *scratch* for this exact purpose. In this mode, you can type in lisp statements, and have them executed immediately, just like an ancient BASIC interpreter. To execute a statement, press C-j (control-j) at the end of the line. The value to which the statement evaluates will be placed into the buffer immediately after. For example:
You type: nil<C-j>
Result: nil
You type: (concat "foo" "bar")<C-j>
Result: "foobar"

The other way to get Emacs to do lisp is to run the eval-expression command by pressing M-: (escape, :). An interesting aside: this command used to be mapped to escape, escape, but was changed when it was pointed out that most new Emacs uses who hit escape repeatedly probably were not looking for a way to execute lisp. At any rate, pressing M-: will bring up an Eval: prompt, at which you can type a line of lisp. The result will be shown briefly at the bottom of the screen. The result can be pasted into the current buffer by wrapping it with a call to insert, like so:
Eval: (insert (concat "foo" "bar"))

Basic Arithmetic and Hexadecimal Constants in Lisp

Basic arithmetic in lisp is relatively simple, with the one limitation of having to use prefix notation. Anyone who has used a Reverse Polish Notation (RPN) calculator will be somewhat familiar with arithmetic in lisp. Each of the basic operators, +, -, *, /, %, are actually functions in lisp, called using the usual lisp syntax. Adding two numbers in lisp is done like so: (+ 3 4). The expression (((2 + 3) * 4) / 5) would be represented as (/ (* (+ 2 3) 4) 5). This prefix notation is elegant, as the order of operations is always explicit, but is admittedly clumsy for those of us, myself included, used to thinking in the common infix notation.

A few other useful functions: (expt x y) calculates x to the power of y, (sqrt x) calculates the square root of x, (floatp x) and (integerp x) determine if the given number is either a float or an integer, (lsh x count) and (ash x count) do logical and arithmetic shifts of x by count bits to the left (negative counts give right shifts) respectively, and finally (logand x y), (logior x y), (logxor x y) and (lognot) provide the logical and, inclusive or, exclusive or and not functions.

My primary use of a programmer's calculator, though, is conversion to and from hexadecimal, and to a lesser extent, binary. It is surprising easy to do in lisp. To convert to hex, a function called format can be used. format is Emacs lisp's version of printf, and like printf, it accepts a format string and argument list. We can take advantage of the %x format string, which reformats the argument into hexadecimal. A simple conversion: (format "%x" 4096) This returns us the string "1000", which is 4096 in hex.

It is even easier to convert a hex value into decimal. First, the syntax for specifying a hexadecimal constant is to prefix it with #x. This corresponds to the 0x prefix in C/C++/Java/perl. We can simply enter a hex constant into the interpreter and it will be evaluated and returned to us in decimal: #x1000 will evaluated to 4096. We can do the same with binary and octal constants, too; their prefixes are #o and #b, respectively.

A caveat: both GNU Emacs and XEmacs only deal with 28-bit signed integers. In practice, I haven't found this to be a limitation, but be very careful when dealing with 32-bit quantities.

Log in or register to write something here or to contact authors.