Thursday, April 17, 2008

ruby > ( code == data )

In his Code Generation: The Safety Scissors Of Metaprogramming talk, Giles Bowkett talks about the power of Lisp and how Ruby approaches it. One of the Giles’ comparisons is that in Lisp (eq code data) which he translates into ruby as code == data. At the time, I just sort of went with the flow, but then I had a discussion with Mike Moore about SICP and I realized there’s a bit more to it than just that.

Mike pointed out a number of juicy quotes in the preface:

“Underlying our approach to this subject is our conviction that “computer science” is not a science and that its significance has little to do with computers.”

”... The computer revolution is a revolution in the way we think and in the way we express what we think.”

”... we want to establish the idea that a computer language is not just a way of getting a computer to perform operations but rather that it is a novel formal medium for expressing ideas about methodology. Thus, programs must be written for people to read, and only incidentally for machines to execute.”

”... we believe that the essential material to be addressed by a subject at this level is not the syntax of particular programming-language constructs, nor clever algorithms for computing particular functions efficiently, nor even the mathematical analysis of algorithms and the foundations of computing, but rather the techniques used to control the intellectual complexity of large software systems.”

so we should focus on “the techniques used to control the intellectual complexity of large software systems.”

The more I read these, the more I thought that these quotes read a lot like a Ruby Manifesto. I don’t want to take anything away from Lisp (and Scheme), it’s an incredibly powerful family of languages, and it lets Lisp hackers do amazing things. The thing is though, I don’t think this (think_about people things) is an accurate representation of how people.think.

One of the things that I’ve always loved about Ruby is that it combines a very powerful language with a very expressive language—it allows me to write code that maps very well to the way I think, and the way other programmers I know seem to think.

Is Ruby code beautiful, even poetic as some people claim? Sure, sometimes—but that’s not the point. Ruby makes it easy for me to express ideas in code, and to understand the ideas expressed in other people’s code. It helps me “control the intellectual complexity” of problems, it supports the revolution “in the way we express what we think.” So maybe that’s what it all boils down to.

Viva la Revolution! Viva la Ruby!

7 comments:

Sean said...

The thing is though, I don’t think this (think_about people things) is an accurate representation of how people.think.

There is so much cultural and linguistic bias here. Closest to the surface, people.think seems to conform to the OO, imperative programming approach that most of us have been exposed to. But, lets be honest, since when did the full stop of a period indicate the subject, verb relationship. I know I never grew up writing "He.went(home)". On another level, there is bias towards English in people.think. Not all languages precede the verb with the subject. Quite a few modern languages have a syntax that is closer to (think people).

Ruby is convenient to the schooled thoughts of the English speaking, C++, Java trained programmer. It is also quite expressive and powerful. But, please, lets not confuse Ruby's ability to get things done with a comfort level instilled by cultural bias.

pate said...

Sean, good points. I am certainly influenced by a number of biases, but I'm not sure they a) can be avoided or b) matter (at least for my view of Ruby).

It's interesting that matz (who's first language isn't english) also thinks that Ruby is expressive and close to natural language.

Thanks for the better title by the way ... it's a gem.

Giles Bowkett said...

Ramon Leon (from the Seaside world) told me about an amazing conference where (IIRC) Sussman, or one of the SICP guys, went into detail on this part:

a computer language is not just a way of getting a computer to perform operations but rather that it is a novel formal medium for expressing ideas about methodology

He said that the logical consequence of this is that teaching kids to program would make them better able to learn any other subject thereafter, and then went into some examples of practical success with this theory at schools somewhere. Couldn't find a podcast, unfortunately, but it sounded like the amazing talk to end all amazing talks (or rather, to begin them).

Phil said...

I'm with sean here; I don't think there's anything more intrinsically natural about object.message vs (verb object). I don't even really think it has that much to do with English; I think it's tied in more with biases instilled by formal training or informal exposure.

But if you do want to go down the whole English road, you could say that (verb object) mirrors the way imperative sentences work in English with the implied "you".

Really in the end it comes down to this: is your AST first-class and accessible at runtime as a core part of the language, or is it tacked on as an afterthought? The ordering of things is of secondary importance. (http://blog.fyndo.com/2008/02/kenny-mccarthy-lisp-and-future.html)

Levi Pearson said...

The main difference between Ruby and Scheme syntax is that Ruby has a rich, complex syntax; while Scheme has a simple, regular, mutable syntax. Ruby is set up by default to work well with a certain programmer culture, but its syntax is ultimately fixed. Scheme seems alien at first, but is so simple that it can be easily understood and then altered.

Speaking of the quotes from SICP (which is indeed a wonderful book), Scheme is a far superior language for the role of "novel formal medium for expressing ideas about methodology" precisely because it is so simple and flexible. Ruby, with its complex and fixed grammar, is wonderful for writing programs, but not as good as Scheme as a language for Computer Science.

I don't necessarily think that Scheme/Lisp is the end all/be all language, but saying that Ruby > Scheme in the context of SICP borders on blasphemy. ;)

Anyway, on the topic of rich, flexible syntax, the Viewpoints Research Institute has created a bunch of really interesting research over the last year. Check out http://www.vpri.org/html/writings.htm and especially http://www.vpri.org/pdf/steps_TR-2007-008.pdf and what they've done with the OMeta language.

blowmage said...

@Sean I don't think Pat was saying that Ruby is expressive because it can look like English, I think he was saying Ruby is expressive because it feels more natural to him. Matz has basically said the same thing here.

And while it isn't necessarily related to Ruby, I believe OO done right transcends the naive nound.verb(noun) approach. I find that criticism of Ruby to be misplaced.

Bob said...

Hi,

I happen to like both Ruby and Common Lisp. I use both in my work. I'm just going to try to illustrate a small thing with lisp's syntax.

Now to be a bit pedantic... lisp's

(think_about people things)

is closer to Ruby's

people.think(things)

or if you're feeling lucky,

people.think things

And to be even more pedantic (bear with me)...

(think-about person things) ; loose the underscore, use a hyphen

vs

person.think_about(things) # remember the 'about'

Now, how would we write that people think about more than one thing?

In lisp,

(think-about person things stuff nonsense)

In Ruby?? Maybe:

person.think_about things
person.think_about stuff
person.think_about nonsense

but that's not really the same, since the lisp may well indicate simultaneous consideration. Then maybe:

person.think_about([things, stuff, nonsense])

The only thing to point out here is that lisp's syntax doesn't really change a lot, while Ruby's does. Not only that, the 'intuitiveness' of Ruby evaporates.

----

The code == data stuff isn't really talking about this, as I'm sure you know. Even so, I'll make what I'm afraid will be a poor attempt at trying to illustrate... Imagine a scenario where you have a programming environment where you could execute a program that accepted another program as data -- both programs are written in the same language and have access to the same libraries etc. What would the syntax of the language look like? You'd probably like to reduce incidental complexity to a minimum. Where's that minimum? When the data structures that are natural to the programming language would be used to write the program, i.e. provide the syntax of (both) programs. The key insight (in this regard) that lisp brings is the list data structure and syntax. This has been *very* successful for lisp. This is why lisp programmers won't shut-up about 'uniformity of syntax' and 'macros' (and they aren't talking about the 'macros' of the C languages).

If you think that 'simple' isn't so important here... think about those experiments that tried to use XML as the syntax of a programming language. They are trying to achieve something similar to what lisp has achieved but using XML rather than lisp's simple and regular syntax, and using -- if you can imagine -- XML processing tools (e.g. schemas, and, if you can keep your food down, this is cruel sorry, the DOM) to manipulate the 'program'.