Minimalism Versus Simplicity

A couple of people, cwebber and Rodrigo have (comparatively recently) switched to using StumpWM as their primary window managers. Perhaps there are more outside of the circle of people I watch but it's happened enough to get me to think about what constitutes software minimalism.

While StumpWM is a minimal program in terms of design and function; however, in terms of ram usage or binary size, it's not particularly lightweight. Because of the way Common Lisp works, "binaries" and RAM footprint is in the range of 30-40 megs. Not big by contemporary standards, but the really lightweight window managers can get by with far less RAM.

In some senses this is entirely theoretical: even a few years ago, it wasn't uncommon for desktop systems to have only a gig of ram, so the differences would hardly have been noticeable. Now? Much less so. Until 2006 or so, RAM was the most performance effecting limited resource on desktop system, since then, even laptops have more than enough for all uses. Although Firefox challenges this daily.

Regardless, while there may be some link between binary size and minimalism, I think it's probably harmful to reduce minimalism and simplicity to what amounts to an implementation detail. Let's think about minimalism more complexly. For example:

Write a simple (enough) script in Python/Perl and C. It should scan a file system and change the permissions of files such that they match the permissions of the enclosing folder, but not change the permissions of a folder if it's different from it's parent. Think of it as "chmod -R" except from the bottom up. This is a conceptually simple task and it wouldn't be too hard to implement, but I'm not aware of any tool that does this and it's not exactly trivial (to implement or in terms of its resource requirements.)

While the C program will be much more "lightweight," and use less RAM during while running, the chances are that the Python/Perl version will be easier to understand and use much more straightforward logic. The Python/Perl version will probably take longer to run and there will be some greater overhead for the Python/Perl runtime. Is the C version more minimal because it uses more RAM? Is the Perl/Python program more minimal because it's interface and design is more streamlined, simple and easier to use?

I'm not sure what the answer is, but lets add the following factor to our analysis: does the "internal" design and architecture of software affect the minimalism or maximalism of the software?

I think the answer is clearly yes, qualified by "it depends" and "probably not as much as you'd think initially." As a corollary as computing power increases the importance of minimalist implementations matters less generally, but more in cases of extremely large scale which are always already edge cases.

Returning for a moment to the question of the window manager, in this case I think it's pretty clear: StumpWM is among the most minimal window managers around, even though it's RAM footprint is pretty big. But I'd love to hear your thoughts on this specifically, or technological minimalism generally.

Managing Emacs Configuration

This document outlines the use of emacs' require and provide functions to help new users understand how to better configure the text editor. While there are a number of different strategies for organizing emacs configuration files and lisp systems and there is no single dominant best practice, consider this document if you find your .emacs or init.el` file growing out of control.

Background and Overview

After using emacs for any period of time, one begins to develop a rather extensive emacs configuration. Emacs comes with very little default configuration and large number of configuration possibilities. Because writers, programmers, and researchers of all persuasions and backgrounds use emacs for a larger array of tasks and work profiles, the need for customization is often quite high. n Rather than have a massive emacs configuration with thousands of lines, I've broken the configuration into a number of files that are easier to manage, easier to troubleshoot, and easier to make sense of. These files are then linked together and loaded using emacs' native require function. This document explains that organizational principal and provides the code needed to duplicate my configuration.

I store all of my emacs configuration in a folder that I will refer to as ~/emacs/, in actuality this is a sub-folder within a git repository that I use to store all of my configuration folders, and you should modify this location to suit your own needs. Additionally, I have the habit of prepending the characters tycho- to every function and emacs file name that are my own writing. This namespace trick helps keep my customization separate from emacs' own functions or the functions of loaded packages and prevents unintended consequences in most cases. You might want to consider a similar practice.

Configuring .emacs

My .emacs file is really a symbolic link to the ~/emacs/config/$HOSTNAME.el file. This allows the contents of .emacs to be in version control and if you have your emacs configuration on multiple machines to use the same basic configuration on multiple machines with whatever machine specific configuration you require. To create this symlink, issue the following command:

ln -s ~/emacs/config/$HOSTNAME.el ~/.emacs

Make sure that all required files and directories exist. My .emacs file is, regardless of it's actual location, is very minimal because the meat of the configuration is in ~/emacs/tycho-init.el. Take the following skeleton for ~/.emacs:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Startup and Behavior Controls
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(setq load-path (cons "~/emacs" load-path))

(setq custom-file "~/emacs/custom.el")
(add-to-list 'load-path "~/emacs/snippet/")
(add-to-list 'load-path "/usr/share/emacs/site-lisp/slime/")

(require 'tycho-display)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Machine Specific Configuration Section
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(tycho-font-medium)
(setq bookmark-default-file "~/garen/emacs/bookmarks/arendt"
      w3m-session-file "~/garen/emacs/bookmarks/w3m-session-arendt"
      bookmark-save-flag 1)

(if (file-directory-p "~/garen/emacs/backup")
    (setq backup-directory-alist '(("." . "~/garen/emacs/backup")))
  (message "Directory does not exist: ~/garen/emacs/backup"))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Load the real init
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(require 'tycho-init)

(menu-bar-mode -1)

The first seq defines the load path. Like other configuration paths, this is the directory that emacs will look for files to load when you use require later. load-path does not crawl a directory hierarchy, so if you store emacs lisp within ~/emacs/, you'll need to add those directories here. To see the value of the load-path use "C-h v" in emacs. I then define "custom.el" as it's own file to prevent customize from saving configuration in my init file. Then I use require to load a number of display-related functions (from the file ~/emacs/tycho-display.el,) including the tycho-font-medium function.

Then I have a number of machine-specific configuration opens set, mostly to keep multiple machines from overwriting state files.

Finally, I load the file with the real configuration with the (require 'tycho-init) sexp. The configuration is located in the ~/emacs/tycho-init.el file. The file closes with the (menu-bar-mode -1) sexp, which is the last part of the configuration to evaluate and ensures that there isn't a menu-bar at all.

Require and Provide

require, however, does not simply load .el files in the load path. Rather, the file needs to be announced to emacs. Accomplish this with provide functions in the file. For ~/emacs/tycho-display.el the relevant parts are as follows:

(provide 'tycho-display)

(defun tycho-font-medium ()
  (interactive)
  (setq default-frame-alist '((font-backend . "xft")
                              (font . "Inconsolata-13")
                              (vertical-scroll-bars . 0)
                              (menu-bar-lines . 0)
                              (tool-bar-lines . 0)
                              (alpha 86 84)))
  (tool-bar-mode -1)
  (scroll-bar-mode -1))

(global-set-key (kbd "C-c f m") 'tychoish-font-medium)

(setq-default inhibit-startup-message 't
              initial-scratch-message 'nil
              save-place t
              scroll-bar-mode nil
              tool-bar-mode nil
              menu-bar-mode nil
              scroll-margin 0
              indent-tabs-mode nil
              flyspell-issue-message-flag 'nil
              size-indication-mode t
              scroll-conservatively 25
              scroll-preserve-screen-position 1
              cursor-in-non-selected-windows nil)

The provide call, identifies this file as the location of the tycho-display functionality. tycho-font-medium describes the font and display parameters that I called in the .emacs file. And the file ends with a keybiding to call that function and a number of default settings.

Init and Conclusion

While the tycho-init.el file holds all of the interesting configuration options, functions and settings, it's mostly beyond the scope of this file. When you download contributed emacs.lisp files from emacswiki, put them in ~/emacs/ and put the require call in tycho-init.el. By convention provide names map to file names but be sure to check files to ensure that this is the case.

Using this setup as a framework, you can create--without confusion--a number of configuration files to properly collect and organize your settings, emacs modes, and other emacs code and functions that you've gotten from other users. Good luck!

You may also be interested in a couple other tutorials I've collected on emacs, notably:

Common Lisp, Using ASDF Install With SBCL

So I, like any self respecting geek trying to learn Common Lisp started to read the cliki, which is a wiki that supports Common Lisp projects. Nifty right? Right. It's full of stuff, and between it and Common-Lisp.net, you can be pretty sure that if it exists in the common Lisp world it'll appear on one of those two sites. And for every cool lisp thing, rather than usable instructions for installing the software it would just say "use asdf install and have fun." Which is good if you know what asdf is or what it's supposed to, and how to use it.

But, there's a decent chance that you're like me, and were completely clueless.

Turns out asdf-install is the common lisp equivalent of the CPAN shell or Ruby gems, or the Debian project's dpkg, with some lisp-centric variations. This post provides an overview and a "quick start guide" in case you want to get started. The directions I provide are in line with "the way I like to keep my file system organized (e.g. ~/) and center around the Arch Linux and SBCL system that I use. However, this should hold true (more or less) for any distribution of Linux with SBCL and possibly to other lisps. Feel free to add your own modifications in comments or in the lisp page on wikish.


Begin by getting to a CL REPL. If you have emacs and "slime" installed get to a REPL using "M-x slime" otherwise just type sbcl at a system prompt. Installing slime, emacs, and sbcl are beyond the scope of this post, but in general use the packages designed for your platform and you should be good. MacPorts for OS X users and the package managers for most prevalent Linux-based operating systems should have what you need.

At the REPL do the following:

(require 'asdf)
(require 'asdf-install)

(asdf-install:install '[package-name])

Remember to replace the [package-name] with the dependency or package that you want to install. asdf will ask you if you want to install the package system wide, or in a user-specific user directory. I tend to install things in the user-specific directories because it gives me a bit more control over things. The user specific directory is located in ~/.sbcl if you want to poke around the files yourself. Done. That's pretty straight forward. Lets get to the awesome parts.

Make a ~/lisp directory. I keep mine stored in a git repository. I've also kept my .sbcl directory inside ~/lisp and then created a symbolic link so that the computer is none the wiser. Issue the following commands to accomplish this:

cd ~/
mkdir -p ~/lisp/systems
mv .sbcl ~/lisp/
ln -s ~/lisp/.sbcl

Adjust the path as necessary. Additionally You will also want to create a ~/.sbclrc file with some code for asdf to initialize itself when SBCL runs. Do the following:

cd ~/
touch ~/lisp/.sbclrc
ln -s ~/lisp/.sbclrc

In your .sbclrc file you'll probably want something like the following:

(require 'asdf)

(pushnew #p"/usr/share/common-lisp/systems/" asdf:*central-registry* :test #'equal)
(push #p"/usr/share/common-lisp/systems/" asdf:*central-registry*)

(pushnew #P"/home/[username]/lisp/systems/" asdf:*central-registry* :test #'equal)
(push #P"/home/[username]/lisp/systems/" asdf:*central-registry*)

This tells SBCL and asdf where all of the required lisp code is located. Alter path's as needed. We've not talked very much about the ~/lisp/ directory yet. Basically it's a directory that serves as a playground for all things lisp related. Each "project" or package should have it's own directory, which will contain lisp code and an .asd file. To make a package accessible via asdf on your system create a symbolic link for these .asd files in your ~/lisp/system folder. Done.

So let's set up a basic "hello world" package that we'll call "reject," just for grins. File one, ~/lisp/reject/reject.asd:

(defsystem "reject"
  :description "a reject program
  :version "0.1"
  :author "tycho garen"
  :licence "ISC License"
  :depends-on ("cl-ppcre")
  :components ((:file "reject")
               (:file "package")))

The dependency on cl-ppcre isn't required, but that's how it would work if you needed a regex engine for a reject hello world application. File two, ~/lisp/reject/package.lisp:

(defpackage reject (:use :common-lisp))

File three, ~/lisp/reject/reject.lisp:

(in-package :reject)

(defun hello-world () ()
(print "Hello World, tycho"))

(hello-world)

Once those fils are saved, issue the following commands to create the needed symbolic link:

cd ~/lisp/system/
ln -s ~/lisp/reject/reject.asd

Now, from the REPL issue the following expression to load the package:

(asdf:operate 'asdf:load-op 'reject)

And then the following expression to test that it works:

(hello-world)

And you're set to go. As to how you'd write or package up something that might actually have value? That's a problem I'm still wrapping my head around. But that can all happen later.

If I've overlooked something or you think my understanding of something here isn't incredibly clear, do be in touch. I hope this helps!

Why Bother With Lisp?

I'm quite fond of saying "I'm not a programmer or software developer," on this blog, and while I don't think that there's a great chance that I'll be employed as a developer, it's becoming more apparent that the real difference between me and a "real developer" is vanishingly small. Stealth Developer, or something. In any case, my ongoing tooling around with common lisp and more recently the tumble manager project have given me opportunities to think about lisp and to think about why I enjoy it.

This post started when a friend asked me "so should I learn common lisp." And my first response was something to the effect of "no, are you crazy?" or, alternately "well if you really want to." And then I came to my senses and offered a more reasonable answer that I think some of you might find useful.

Let us start by asking "Should You Study Common Lisp?"

Yes! There are a number of great reasons to use Common Lisp:

  • There are a number of good open source implementations of the common lisp language including a couple of very interesting and viable options. They're also stable: SBCL which is among the more recent entrants to this field is more than a decade old.
  • There are sophisticated development tools, notably SLIME (for emacs) which connects and integrates emacs with the lisp process, as well as advanced REPLs (i.e. interactive mode). So getting started isn't difficult.
  • Common Lisp supports many different approaches to programming. Indeed, contemporary "advanced" languages like Ruby and Python borrow a lot from Lisp. So it's not an "archaic" language by any means. Dynamic typing, garbage collection, macros, and so forth.
  • CL is capable of very high performance, so the chance of saying "damn, I wish I wrote this in a faster language," down the road isn't terribly likely. Most implementations run on most platforms of any consequence, which is nice.
  • You're probably tired of hearing that "Learning Lisp will make your a better programmer in any language," but it's probably true on some level.

The reasons to not learn Lisp or to avoid using it are also multiple:

  • "Compiled" Lisp binaries are large compared to similarly functional programs in other languages. While most CL implementations will compile native binaries, they also have to compile in most of themselves.
  • Lisp is totally a small niche language, and we'd be dumb to assume that it's ever going to take off. It's "real" by most measurements, but it's never really going to be popular or widely deployed in the way that other contemporary languages are.
  • Other programmers will think you're weird.

Having said that all of I think we should still start projects in CL, and expand the amount of software that's written in the language. Here's why my next programing project is going to be written in lisp:

  • I enjoy it. I suspect this project like many projects you may be considering is something of an undertaking. Given that I don't want to have to work in an environment that I don't enjoy, simply because it's popular or ubiquitous.
  • Although Lisp isn't very popular, it's popular enough that all of the things that you might want to do in your project have library support. So it's not exactly a wasteland.
  • The Common Lisp community is small, but it's dedicated and fairly close knit. Which means you may be able to get some exposure for your application in the CL community, simply because your app is written in CL. This is a question of scale, but it's easier to stand out in a smaller niche.

Of course there are some advantages to "sticking with the crowd" and choosing a different platform to develop your application in:

  • If you want other people to contribute to your project, it's probably best to pick a language that the people who might be contributing to your application already know.
  • While there are libraries for most common things that you might want to do with Common Lisp, there might not be libraries for very new or very esoteric tasks or interfaces. Which isn't always a problem, but can be depending on your domain.
  • The binary size problem will be an issue if you plan to deploy in limited conditions (we're talking like a 15 meg base size for SBCL, which is a non issue in most cases, but might become an issue.)
  • If you run into a problem, you might have a hard time finding an answer. This is often not the case, but it's a risk.

Onward and Upward!

The Blog, Next in Lisp

Here's a crazy idea: in addition to posting an RSS feed, say I start posting the content of the blog as Common Lisp code. Not, to replace any format that I currently publish in, but as an additional output option. Entries might look something like this:

(tychoish:blog-post
   (tychoish:meta-data
      :title "The Blog, Next in Lisp"
      :author "tycho garen"
      :pubtime #'(format () time-t)
      (tychoish:blog-tags '(lisp cyborg crazy))
      (tychoish:archive-collection '(programing)))
  (tychoish:blog-content (markdown)
    "Here's a crazy idea: in addition to posting an RSS feed, say I start
    posting the content of the blog as Common Lisp code. Not, to replace
    any format that I currently publish in, but as an additional output
    option. Entries might look something like this: [...]"))

That's pretty. In a lispy story of way. I'm not sure that it's actually correct, and it makes calls to functions that don't exist, of course. But I hope you can get the gist enough to see where I'm going with this, and maybe enough to correct my newbish mistakes.

By my count there needs to be functions for: blog-post, meta-data, blog-tags, blog-content, and markdown. And of course it's missing some notion of what these functions might do. I'm not terribly sure what they could do, build a better indexing system for the site (lord knows I need it), or more easily create a Lisp-based content reader/browser thatls like a feed reader but more in some way that I haven't envisioned.

In a lot of ways, this isn't any different from RSS. And it is RSS, basically, except you don't have to parse it into some format that your programing language can understand, (assuming you're programing with Lisp, of course, but you are, aren't you?) because it is your programing language. At least in my mind this has a lot in common with the Sygn Project in that both projects focus on providing some sort of loose standard that allow us to share and use data openly and freely, using formats that are easy (enough) to construct by hand, are human readable, and easy to process and use programatically.

In any case, it shouldn't be terribly hard to generate this format, the question is: does seeing the data like this present possiblities to anyone? And, while we're at it, if anyone wants to help define some of the more basic functions, that might be awesome. I look forward to hearing from you all?

Common Lisp, Practically

So in the emacs session running on my laptop (13 days plus) I have a number of buffers open, a great many of which include the entirety of Practical Common Lisp thanks to emacs-w3m, which I've been working through slowly. I've written here about how I find Lisp to be intriguing and grok-able in a way that other programing languages aren't really.

My exposure to lisp isn't great. I hack about with my emacs code, and I do a little bit of tweaking with the window manager that I use (written in common lisp), StumpWM, but other than that I don't actually have much experience. What follows are a series of reflections that I have with regards to lisp:

Although there's a lot of really amazing capabilities in Common Lisp, and a lot of open source energies behind Lisp... Lisp isn't flourishing.

This shouldn't be a great surprise to anyone, lisp is sort of the epitome of "Programing Languages that don't get enough respect." Having said that there are a lot of lisp projects that aren't really well maintained at all. Even things that would just be standard and maintained for other languages (various common libraries and the like) haven't been touched in a few years. While it's not a huge worry, it does make it a bit worrying. Having said that, I don't think lisp is ever really going to go anywhere, and Common Lisp seems like a pretty darn good spec. But I don't have any real exposure to Scheme, and Arc isn't really real yet, I guess.

Lisp works funny, particularly for people who only have a passing familiarity with programming.

We're used to programming languages that either pass the source code through an interpreter (e.g. Python, Ruby, PHP, Perl, and I suppose Java and C#) compile into some sort of intermediate bytecode and then run that code on a virtual machine, then output stuff; conversely there are languages which compile down to some sort of native binary and then execute directly on the hardware. Examples of this second class of languages include: C, C++, and Haskell. Sorry if my examples or descriptions of the execution model aren't particularly precise.

When you run lisp code, you define stuff and load it into the memory of a lisp process, and then stuff happens as the program runs. It's compiled to native code (I'm pretty sure at least,) but there aren't binaries, in the conventional sense. To get a "binary," you have to dump the memory of the program, and pretty much the entire lisp process into a blob. So the base size for executables is way bigger than one might expect. I've also had some success at running scripts with sbcl shebangs from the terminal. That's pretty nifty, not that I've really done very much of that, but its nice to know that it's possible.

Web programing in Lisp. I'm not so sure about that.

So you might see lisp code, and think: "So. Many. God. Damn. Parentheses." and you'd be right. But even well formatted HTML is considerably less "human readable" than Lisp, and I don't think there's a lot of room for debate there. But when you think about it, Lisp actually makes a fair amount of sense for the web.

I've actually done a little bit of poking around and from what I can see, the actual architecture and deployments of lisp aren't terribly bad. There are Apache modules that will pass requests back to a single lisp process (mod_lisp similar to how fastcgi works,) and there's always the option of running performance CL specific web-application servers and just proxying requests to those servers from Apache. Lisp is, or can be, pretty damn fast by contemporary standards, and although there's a lot of under-maintained lisp infrastructure, the basics are covered, including database connectors and java script facilities which might not be incredibly enticing, but all the parts are there.

I mean, having said that, I'm not a web developer, or really much of a developer in general, but it's fun to think about, and even if I only use Lisp to hack on various things here and there, I'm still learning a bunch from the book and that seems more than worthwhile.

The Odd Cyborg Out

I said to my office mate this week, "I'm switching to zsh," and I believe he said something to the effect of "oh dear, what's next."

I should back up. I'm something of an odd duck when it comes to the way I use computers. I'm a geek, even in the context of my coworkers who are (also) huge geeks. I'm the only one who uses emacs. We're an OS X shop (for the desktop, at least) but I run Arch Linux inside of a virtual machine. Because I'm like that. And now, I'm switching away from the by-now unix standard "bash" shell to "zsh." I'm a bit weird. I'm ok with this.

So zsh. Why should you care? Well...

I'm not expert, having only really used it for a few days but there are a few things that have won me over:

  • It's mostly backwards compatible with bash. So, except for the stuff that configured my prompt, I was able to copy over my old .bashrc file pretty much as is. There's been no real "brain adjustment" from all my old bash habits.
  • It's faster. You know, this is the kind of thing taht you don't believe, "my terminal is faster than your terminal" is kinda lame because bash is pretty peppy compared to GUI stuff. I mean what, bash is a 300-400 kb, how slow can it be? The answer is, zsh just feels faster. This seems to be a quasi universal experience.
  • It does tab-completion within commands. This is seriously amazing, because while command completion and path completion is awesome in bash, you still have to remember all of the sub-commands. This is particularly rough for big commands like "git" and "apt-get" or "apt-cache". Very awesome.

Getting up the courage to switch and to rewrite my prompt was something that took a little bit of doing, but now I'm happy, and I strongly recommend it. If you like me live in the terminal, or have thought about using the command line more, give zsh a try, it's good stuff.


The other thing, almost certain to provoke an "Oh dear" reaction on the part of my geeky friends is the fact that I'm strongly considering switching from the Awesome Window Manager to the Stump Window Manager, or more practically StumpWM or just Stump. Here's some background on my adventures with tiling window managers:

When I started using Awesome every thing I did with the computer lived in it's own little window. I was coming from the mac, so I lived with ten or fifteen open TextMate windows, a like number of open tabs in my terminal emulator, and a browser with a gazillion open tabs. I thought that this was sort of "the way I worked," and so I replicated this kind of workflow in Awesome.

And here's the thing. Awesome is great for managing a huge number of windows. With 9 workspaces/tags (or more!) it was possible to keep twenty or thirty windows afloat... a few browsers, a few chat windows, a dozen terminals, a few emacs frames, and the like all happening at once. And the window manager made it possible for me to only have to look at 2 or three windows at a time.

Then I progressed. With emacs' server/daemon mode, I only have one instance of emacs and 20 or so buffers, and in an extreme moment I sometimes have as many as 4 frames open at once, but more often I just have 2 or three (org-mode, writing, and a spare for something.) And terminals? I've taken to using screen which multiplexes an untabbed terminal, so I typically have a single screen session with 8 screen-windows, and I keep a couple of instances of that open at once for different contexts, so lets say another three windows. I have a remote screen session for IM and chat now that I connect to, and a single web browser.

Frankly, it's sort of gotten to the point where I don't really need to manage very many windows, and I probably never use more than 4-5 tags/workspaces. My needs for a window manager changed, and one of the core problems that problem that Awesome solves, is one that I've solved by using multiplexed applications. And that leads me to Stump.

I see that I probably need to spend a little more time talking about this tiling window manager stuff again. Stay tuned!