alan dipert RSS

github / twitter / resume / email
Mar
18th
Thu
permalink
The complexity of software is an essential property, not an accidental one. Hence, descriptions of a software entity that abstract away its complexity often abstract away its essence. For three centuries, mathematics and the physical sciences made great strides by constructing simplified models of complex phenomena, deriving properties from the models, and verifying those properties by experiment. This paradigm worked because the complexities ignored in the models were not the essential properties of the phenomena. It does not work when the complexities are the essence.
Comments (View)
Mar
13th
Sat
permalink

The S-expression Editor

The other week I was reading about Bard, a new Lisp dialect, and ran into this:

“Historically, and in most other Lisp dialects, source code is explicitly or implicitly not text; it is s-expressions. Text is just a print representation of the s-expressions.

Emphasis added.  This got me thinking.

for lisp, text editors are overkill

Good text editors like vim and Emacs are really good at everything having to do with text editing.  In fact, they’re so good at such a wide variety of things, that their features wildly exceed the sort of operations one really needs to do when working on Lisp programs.

For instance, even the idea of a “newline” (or any other character the average Reader considers whitespace) doesn’t really have any meaning in s-expression land outside of quoted strings.  Everything in the editor about them needn’t be accessible to the programmer.

So, what if instead of accepting text as our source editing medium, we operated directly on data structures?  That is, what if key strokes performed some operation directly on the program’s data, and the editor simply pretty printed a nicely formatted representation of the current program following edits?

This is my idea, and I’m not sure it hasn’t been done before.

some pros

  • Plugins: Plugin functions don’t have to worry at all about dealing with or parsing text.  They’re handed the data structure representing the current program (or arbitrary s-expression), along with a function representing the “point” or cursor location.  They transform it somehow, and return the new data structure.  The point might be stored as a zipper partial.
  • Visualization: By separating editing from representation, it becomes simpler to develop alternative visualizations.  I think there might be a lot of interesting work to be done here, with things like contours, bubbles, and snippets.  For some cool ideas along these lines, check out Michael Weber’s Emacs hackery page.
  • Universal formatting: Since the programmer is no longer dealing directly with shareable, revisionable text, the text visualizer would serve also as the exporter when it came to source control and storage.  In the case of Clojure, this would effectively make the *code-dispatch* dispatch table for clojure.contrib.pprint the gofmt of the language.
  • Evaluation: SLIME-like evaluation for Clojure would be trivial, assuming this editor was written in Clojure.

some cons

  • Comments: Comments, and anything else in source code normally stripped by the Reader, would be completely lost.  This means that any such data would have to be metadata, something which seems cumbersome at best.  Maybe not.
  • Another editor?: Both vim and Emacs, and particularly Emacs with Paredit, have served me exceptionally well when it comes to editing Clojure.  I’m not sure a new editor is warranted; but the idea of an editor written in Clojure that takes advantage of STM (for undo) and zippers (for commands and plugins) sounds pretty appealing.

status

I’ve started playing with SWT in an effort to build a prototype.  I’ll github it soon.  In the meantime, does anyone know if this has this been done before?  Are there unsurmountable pitfalls that make the idea pointless?  Thanks in advance!

Comments (View)
Mar
10th
Wed
permalink
Comments (View)
Mar
8th
Mon
permalink

NCSA Mosaic on Github

NCSA Mosaic 2.7 viewing GitHub.com

In 1994, when I was in fourth grade, my dad brought me along with him to see a friend of his in the CS department at the University of Buffalo.  My dad’s friend, Bill Rapaport, was running NCSA Mosaic on a Sun workstation.  I vividly remember the moment he brought up the Louvre’s website and a beautiful full color image of the Mona Lisa was magically beamed across the ocean from Paris, and onto the screen.

My dad had shown me gopher before, but nothing was ever in color.  In fact, everything I’d seen about computers up to that point seemed pretty boring.

The moment I saw the Mona Lisa in full color on a computer monitor was one of only a handful of moments that led me to where I am now, which is a state of continual curiosity and wonder about these things, these machines, these computers.

Thanks in great part to the work of others, I was able to pretty easily get Mosaic to compile and run on my machine, and to relive for a moment my childhood renaissance.

What is the Mosaic, the Mona Lisa, that we can show children today?

If you’re on GNU/Linux-Ubuntu (or something else, and you know your way around your package manager) you can compile and run NCSA Mosaic yourself: http://github.com/alandipert/ncsa-mosaic

Comments (View)
Feb
13th
Sat
permalink
Comments (View)
Jan
30th
Sat
permalink

Rich Hickey talks about the Clojure in Clojure project

Comments (View)
Jan
17th
Sun
permalink

Passing Methods like Blocks in Ruby

Ruby’s Functions

Ruby has four flavors of function, each with various nuances: methods, blocks, Procs, and lambdas.

A Simple Example

The object Array has a bunch of methods on it that take blocks.  Normally, you write these blocks inline:

[1,2,3].map{|x| x+1} # → [2,3,4]

But what if you have a method you’d like to pass to map?

def addone(n)
  n+1
end
[1,2,3].map(addone) # → Doesn't work

The above example doesn’t work because map is expecting a block.  We’re not passing it one; instead, we’re invoking addone with no arguments and attempting to pass the result of that invocation to map.

To get a value representing the addone method, we can use Object.method, which takes the symbol of the name of the method as an argument:

def addone(n)
  n+1
end
[1,2,3].map(method(:addone)) # → Still doesn't work

That still doesn’t work, but we’re close.  Map expects a block, but we’re passing it a Method. The key to this conversion is the unary ampersand &, which will convert anything to a Proc that has a to_proc method, and then convert any Proc to a block.

Let’s give it another shot:

def addone(n)
  n+1
end
[1,2,3].map(&method(:addone)) # → [2,3,4]

Voila! The point? This is just another way to consolidate and modularize code.  If you find yourself writing the same block over and over, and if it makes sense, you can write a method and reference to it.

Getting Complicated

Here’s a Polish notation calculator that groups operators and arguments as S-expressions, with Arrays:

def evl(exp)
  if exp.is_a? Array
    exp.slice(1..-1).map(&method(:evl)).inject(exp.first)
  else
    exp
  end
end

evl(3) # → 3
evl([:+, 4, 5]) # → 9
evl([:+, 1, 2, [:-, 10, 7]]) # → 6

If the input to evl is an Array, evl maps every element of the Array except the first to itself, and then reduces the resulting Array with the first term, which should be a Symbol representing a binary function.  evl takes advantage of the fact that inject automatically casts Symbols to blocks.

This example is different from the one above, in that &method(:evl) occurs inside of evl, which doesn’t actually work in Ruby 1.8.7.  It seems to work in 1.9.1, though.

Comments (View)
Jan
13th
Wed
permalink

Lazy Sequences in Javascript

I’ve played around a bit more with the Lazy Function Definition pattern I mentioned in my last post, and implemented a Javascript object for creating lazy sequences.  Here’s what the fibonacci sequence looks like, a nearly direct port (minus destructuring) of Christophe Grand’s Clojure version:

function fibo() {
  return new LazySeq(
    function(pair){
      return [pair[1],pair[0]+pair[1]];
    },
    [0,1])
    .map(first);
}

fibo().take(10);
//0,1,1,2,3,5,8,13,21,34

LazySeq.map is itself lazily applied, and values are only actually “realized” with either LazySeq.take or LazySeq.nth.

For the LazySeq code, check out the Gist.  It doesn’t include my crappy Array.prototype.reduce implementation, but you could easily substitute in Underscore.js’s reduce.  Happy Javascripting!

Comments (View)
Jan
12th
Tue
permalink

Lazy Function Definitions and “Undo” in Javascript

Implementing Undo/Redo in Javascript

I’ve been working on a Javascript project for class that includes “undo” functionality.  ”Undo” is a feature I take for granted in many different applications, but it’s a really interesting problem and has been really fun to implement.

My approach uses what I call an “Agent,” an object that wraps some piece of data.

Agents provide undo(), redo(), and apply().  apply() takes an object with two function properties as its argument:

  • .apply(): A function taking one argument, the data, and returning the changed data.  Stored on the “redo” stack inside of the Agent, and run immediately.
  • .unapply(): A function taking one argument, the data, and returning the changed data.  Stored on the “undo” stack inside of the Agent.

So, to change the data inside the Agent you supply the Agent with a function to change it, and a function to change it back.  By storing these two functions on stacks internally, undoing or redoing is as simple as popping previously stored functions from their respective stacks and executing them.

My whole approach here was influenced heavily by Rails migrations, which accomplish basically the same thing.  More generally, what I have going is a memento pattern.

Lazy Function Definitions

Because the state of the application might have changed since .apply() and .unapply() were passed to the Agent for storage, it was important that they contained enough information about the application’s state when they were first run to successfully run again later.

Luckily, there’s a way in Javascript to describe a function that can “cache” values.  The first time these kinds of functions are run, they do something and store it.  The next time they’re run, they use the cached value.  The pattern is called Lazy Function Definitions, and I didn’t invent it.  But here’s an example, courtesy Peter Michaux:

var foo = function() {
  var t = new Date();
   foo = function() {
    return t;
   };
  return foo();
};

“When foo is called the first time, we instantiate a new Date object and reassign foo to a new function which has that Date object in it’s closure. Then before the end of the first call to foo the new function value of foo is called and supplies the return value.”

Lazy Undo/Redo

Instead of creating a new Date(), my application reaches into the DOM API to fetch some user inputted value from a text box.  Because the contents of this particular text box will change over the application’s lifetime, it’s important I only fetch it once.

Here’s what calling Agent.apply() looks like, using a lazy function definition:

agent.apply({
  "apply" : function(node) {
    var cachedValue = document.getElementById('newText').value;
    this.apply = function(node) {
      return node.appendChild(makeElem(cachedValue)).parentNode;
    }
    return this.apply(node);
  },
  "unapply" : function(node) {
    return node.removeChild(node.childNodes[node.childNodes.length-1]);
  }
});

Javascript is Cool

Javascript is a really fun language.  To see this all in action, check out my undo/redo demo.

Comments (View)
Dec
30th
Wed
permalink
Good coders are a special breed of persistent problem-solvers who are addicted to the small victories that come along a long path of trial and error.
Comments (View)