tags:

views:

1190

answers:

22

I've read The Nature of Lisp. The only thing I really got out of that was "code is data." But without defining what these terms mean and why they are usually thought to be separate, I gain no insight. My initial reaction to "code is data" is, so what?

+24  A: 

Write Lisp code. The only way to really 'get' Lisp (or any language, for that matter) is to roll up your sleeves and implement some things in it. Like anything else, you can read all you want, but if you want to really get a firm grasp on what's going on, you've got to step outside the theoretical and start working with the practical.

McWafflestix
Yes, writing is good, but it will not do much good if it is just trying to write C code with Lisp syntax.
Svante
It actually is just fine to write C code with Lisp syntax as a first step. Nobody changes languages and instantly grasps the new paradigm in its entirety - you have to learn to understand the basic structure of what you're looking at first, and then you can focus on resolving finer details and completely new concepts. But until you've written some code in the language, learning all of the constructs isn't going to help much.
Mike Burton
Indeed. Patterns are called patterns because they emerge by themselves, they are not prescribed. Start coding; if something feels good, you're probably doing it right. If something feels bad, you're probably doing it wrong (or using PHP).
jrockway
Yup, if all you know is C, writing C code in Lisp isn't necessarily bad. In fact, it's better than grabbing some generic "lists and recursion" text that has little applicability to what the developer wants to do. Pick an application, write it however you want. When you're done, you can come back and write it again to make it "more lispy" if you like. Always easier to learn a language applying it to a domain you know.
Will Hartung
+6  A: 

I think you have to have more empathy for compiler writers to understand how fundamental the code is data thing is. I'll admit, I've never taken a compilers course, but converting any sufficiently high-level language into machine code is a hard problem, and LISP, in many ways, resembles an intermediate step in this process. In the same way that C is "close to the metal", LISP is close to the compiler.

Alex Gartrell
+2  A: 

Data is code is an interesting paradigm that supports treating a data structure as a command. Treating data in this way allows you to process and manipulate the structure in various ways - e.g. traversal - by evaluating it. Moreover, the 'data is code' paradigm obviates the need in many cases to develop custom parsers for data structures; the language parser itself can be used to parse the structures.

Brandon E Taylor
A: 

The way I think about it is that the best part of "code is data" is the face that function are, well, functionally no different than another variable. The fact that you can write code that writes code is one of the single most powerful (and often overlooked) features of Lisp. Functions can accept other functions as parameters, and even return functions as a result.

This lets one code at a much higher level of abstraction than, say, Java. It makes many tasks elegant and concise, and therefore, makes the code easier to modify, maintain, and read, or at least in theory.

I would say that the only way to truly "get" Lisp is to spend a lot of time with it -- once you get the hang of it, you'll wish you had some of the features of Lisp in your other programming languages.

Zachary Murray
First-class functions are nice, but that's not what "code is data" means.
Luís Oliveira
I completely agree with you that that isn't _entirely_ what it means. What I was going for is that the list data structure and the function are one in Lisp; the merging of the two idioms grants the programmer certain abilities not available in other languages. The list is the data.
Zachary Murray
A: 
Ben Hughes
A: 

I'd suggest that is a horrible introduction to the language. There are better places to start and better people/articles/books than the one you cited.

Are you a programmer? What language(s)?

To help you with your question more background might be helpful.

Tim
+1  A: 

One of the reasons that some university computer science programs use Lisp for their intro courses is that it's generally true that a novice can learn functional, procedural, or object-oriented programming more or less equally well. However, it's much harder for someone who already thinks in procedural statements to begin thinking like a functional programmer than to do the inverse.

When I tried to pick up Lisp, I did it "with a C accent." set! amd begin were my friends and constant companions. It is surprisingly easy to write Lisp code without ever writing any functional code, which isn't the point.

You may notice that I'm not answering your question, which is true. I merely wanted to let you know that it's awfully hard to get your mind thinking in a functional style, and it'll be an exciting practice that will make you a stronger programmer in the long run.

Kampai!

P.S. Also, you'll finally understand that "my other car is a cdr" bumper sticker.

CaptainAwesomePants
+15  A: 

The way you "get" any language is by trying to write some code in it.

About the "data is code" thing, in most languages there is a clear separation between the code that gets executed, and the data that is processed.

For example, the following simple C-like function:

void foo(int i){
  int j;

  if (i % 42 == 0){
    bar(i-2);
  }

  for (j = 0; j < i; ++j){
    baz();
  }
}

the actual control flow is determined once, statically, while writing the code. The function bar isn't going to change, and the if statement at the beginning of the function isn't going to disappear. This code is not data, it can not be manipulated by the program.

All that can be manipulated is the initial value of i. And on the other hand, that value can not be executed the way code can. You can call the function foo, but you can't call the variable i. So i is data, but it is not code.

Lisp does not have this distinction. The program code is data that can be manipulated too. Your code can, at runtime, take the function foo, and perhaps add another if statement, perhaps change the condition in the for-loop, perhaps replace the call to baz with another function call. All your code is data that can be inspected and manipulated as simply as the above function can inspect and manipulate the integer i.

jalf
+1, best answer so far.
Tim Post
That's it? How is this different from self-modifying code - which my professor called "an abomination" :)
MGOwen
self-modifying code is usually indirect. You create a binary blob which just so happens to correspond to machine instructions, then you store that at a known location in memory, and then you jump to that pointer. You get no type-checking or anything. In particular, there's no way for you to ask for "the source code for function f". Sure, you can get a pointer to the function, and read the machine code generated for it, but you have no way in the language to work with this. It doesn't let you manipulate the actual program code, the stuff you wrote, in the language you wrote it.
jalf
In Lisp, the syntax is the same whether it is source code or the abstract syntax tree being evaluated by the interpreter. So you can switch between these views at will. You can take a piece of data and turn it into an expression which the interpreter can evaluate, or you can take an expression and 'quote' it, to get the syntax tree in data form so you can manipulate it. Unlike "normal" self-modifying code, there's no distinction between "the code you write", and "the code that gets executed".
jalf
+2  A: 

By watching legendary Structure and Interpretation of Computer Programs?

Piotr Dobrogost
+13  A: 

I would highly recommend Structure and Interpretation of Computer Programs, which actually uses scheme, but that is a dialect of lisp. It will help you "get" lisp by having you do many different exercises and goes on to show some of the ways that lisp is so usefull.

Craig
+1  A: 

About the whole "code is data" thing:

Isn't that due to the "von Neumann architecture"? If code and data were located in physically separate memory locations, the bits in the data memory could not be executed whereas the bits in the program memory could not be interpreted as anything but instructions to the CPU.

Do I understand this correctly?

Kage
Partly. In most languages, the only way to programatically manipulate or generate source code is via opaque strings of plaintext and some form of `eval`, or as a big string of bytes. In Lisp, source code is stored (and accessible to you) as lists of objects. You can use list manipulation functions to traverse and transform and generate source code very easily. You can write macros that take some source code and return different source code for the compiler/interpreter. You can do magic this way.
Brian Carper
Makes me want to try that out myself. Thanks Brian! :-)
Kage
Brian is right. I would add that anyone can write an interpreter, which reads data and performs actions, so the distinction between data and program is something you can ponder. It's just that this happens very nicely in Lisp.
Mike Dunlavey
+5  A: 

This worked for me:

  1. Read "The Little Schemer". It's the shortest path to get you thinking in Lisp mode (minus the macros). As a bonus, it's relatively short/fun/inexpensive.

  2. Find a good book/tutorial to get you started with macros. I found chapter 8 of "The Scheme Programming Language" to be a good starting point for Scheme.

http://www.ccs.neu.edu/home/matthias/BTLS/

http://www.scheme.com/tspl3/syntax.html

z5h
+1  A: 

To truly grok lisp, you need to write it.

Learn to love car, cdr, and cons. Don't iterate when you can recurse. Start out writing some simple programs (factorial, list reversal, dictionary lookup), and work your way up to more complex ones (sorting sets of items, pattern matching).

On the code is data and data is code thing, I wouldn't worry about it at this point. You'll understand it eventually, and its not critical to learning lisp.

Curtis Tasker
I like iteration and CL has excellent facilities for it. Plus it doesn't blow the stack like deep recursion (remember that TC elimination is not required in CL).Of course for a Schemer all that is different.
skypher
When I did Lisp in college, I used to get handed back all my iterative solutions with giant red REDO WITH TAIL RECURSION written all over them :) Making that leap from iteration to recursion really did help me understand the basics of lisp better.
Curtis Tasker
+1  A: 

The first step is forgetting everything you have learned with all the C and Pascal-like languages. Empty your mind. This is the hardest step.

Then, take a good introduction to programming that uses Lisp. Don't try to correlate what you see with anything that you know beforehand (when you catch yourself doing that, repeat step 1). I liked Structure and Interpretation of Computer Programs (uses Scheme), Practical Common Lisp, Paradigms of Artificial Intelligence Programming, Casting Spels in Lisp, among others. Be sure to write out the examples. Also try the exercises, but limit yourself to the constructs you have learned in that book. If you find yourself trying to find, for example, some function to set a variable or some statement that resembles a for loop, repeat step 1, then revisit the chapters before to find out how it is done in Lisp.

Svante
A: 

This may be helpful: http://www.defmacro.org/ramblings/fp.html (isn't about LISP but about functional programming as a paradigm)

adrians
This is not at all related to "code is data".
Luís Oliveira
+1  A: 

Read On Lisp and Paradigms in Artificial Intelligence Programming. Both of these have excellent coverage of Lisp macros - which really make the code is data concept real.

Also, when writing Lisp, don't iterate when you can recurse or map (learn to love mapcar).

Technical Bard
Good suggestions, but probably not as a first foray into Lisp.
Steve Rowe
Bah, iterate when that's the best solution to the problem...
Luís Oliveira
+19  A: 

The old fashioned view: 'it' is interactive computation with symbolic expressions.

Lisp enables easy representation of all kinds of expressions:

english sentence

(the man saw the moon)

math

(2 * x ** 3 + 4 * x ** 2 - 3 * x + 3)

rules

(<- (likes Kim ?x) (likes ?x Lee) (likes ?x Kim))

and also Lisp itself

(mapcar (function sqr) (quote (1 2 3 4 5)))

and many many many more.

Lisp now allows to write programs that compute with such expressions:

(translate (quote (the man saw the moon)) (quote german))

(solve (quote (2 * x ** 3 + 4 * x ** 2 - 3 * x + 3)) (quote (x . 3)))

(show-all (quote (<- (likes Kim ?x) (likes ?x Lee) (likes ?x Kim))))

(eval (quote (mapcar (function sqr) (quote (1 2 3 4 5)))))

Interactive means that programming is a dialog with Lisp. You enter an expression and Lisp computes the side effects (for example output) and the value.

So your programming session is like 'talking' with the Lisp system. You work with it until you get the right answers.

What are these expressions? They are sentences in some language. They are part descriptions of turbines. They are theorems describing a floating point engine of an AMD processor. They are computer algebra expressions in physics. They are descriptions of circuits. They are rules in a game. They are descriptions of behavior of actors in games. They are rules in a medical diagnosis system.

Lisp allows you to write down facts, rules, formulas as symbolic expressions. It allows you to write programs that work with these expressions. You can compute the value of a formula. But you can equally easy write programs that compute new formulas from formulas (symbolic math: integrate, derive, ...). That was Lisp designed for.

As a side effect Lisp programs are represented as such expressions too. Then there is also a Lisp program that evaluates or compiles other Lisp programs. So the very idea of Lisp, the computation with symbolic expressions, has been applied to Lisp itself. Lisp programs are symbolic expressions and the computation is a Lisp expression.

Alan Kay (of Smalltalk fame) calls the original definition of Lisp evaluation in Lisp the Maxwell's equations of programming.

Rainer Joswig
Your posts continue to amaze me. You have a great ability to communicate Lisp fundamentals to newbies.
skypher
+1  A: 

I would suggest checking out some of the newer variants of Lisp like Arc or Clojure. They clean up the syntax a little and are smaller and thus easier to understand than Common Lisp. Clojure would be my choice. It is written on the JVM and so you don't have the issues with various platform implementations and library support that exist with some Lisp implementations like SBCL.

Steve Rowe
+2  A: 

In Common Lisp, "code is data" boils down to this. When you write, for example:

(add 1 2)

your Lisp system will parse that text and generate a list with three elements: the symbol ADD, and the numbers 1 and 2. So now they're data. You can do whatever you want with them, replace elements, insert other stuff, etc.

The fun part is that you can pass this data on to the compiler and, because you can manipulate these data structures using Lisp itself, this means you can write programs that write other programs. This is not as complicated as it sounds, and Lispers do it all the time using macros. So, just get a book about Lisp, and try it out.

Luís Oliveira
+1  A: 

Read and understand the legendary page 13 of the Lisp 1.5 Programmer's Manual

According to Alan Kay, at least.

David Plumpton
A: 

I think to learn anything you have to have a purpose for it, such as a simple project.

For Lisp, a good simple project is a symbolic differentiator, so for example

(diff 'x 'x) -> 1
(diff 'a 'x) -> 0
(diff `(+ ,xx ,yy) 'x) where xx and yy are subexpressions
 -> `(+ ,(diff xx 'x),(diff yy 'x))
etc. etc.

and then you need a simplifier, such as

(simp `(+ ,x 0)) -> x
(simp `(* ,x 0)) -> 0
etc. etc.

so if you start with a math expression, you can eval it to get its value, and you can eval its derivative to get its derivative.

I hope this illustrates what can happen when program code manipulates program code.

As Marvin Minsky observed, computer math is always worried about accuracy and roundoff error, right? Well, this is either exactly right or completely wrong!

Mike Dunlavey
A: 

You can get LISP in many ways, the most common is by using Emacs or working next to somebody who has developed LISP already.

Sadly, once you get LISP, it's hard to get rid of it, antibiotics won't work.

BTW: I also recommend The Adventures of a Pythonista in Schemeland.

Marco Mariani