I'm using Atom and Atom-Slime for Common Lisp. In the REPL I'm finding that I can't read user input. The line
(read-line *query-io*)
just hangs. The REPL doesn't register any key presses.
As I tried to debug, I'm finding that I can output to *query-io* just fine:
(format *query-io* "hello")
prints as one expects.
Also, the problem doesn't seem to be with (read-line), I can read from a file with no problems:
(let ((infile (open <some-file>)))
(format t "~a%" (read-line infile))
(close infile))
Does anyone know what's going on?
As said by Coredump, you should use the SLIMA extension instead. It is a fork of Atom-Slime, the maintainer of which unfortunately didn't share push rights for other maintainers to relay him.
But how could you know?
By having a look at the GitHub repository, you would have seen this mention:
Note: It's been hard to find the time to actively maintain this project. For a more recently-maintained version, please see the SLIMA Project, which builds off the code here. Good luck!
Unfortunately, the Atom package was not updated, so we don't see it on the Atom extensions page. But that's not my poit.
Since a few years some online resources have been thoroughly improved [1] and can help, I hope, as a goto reference for future questions and recommendations:
The Common Lisp Cookbook: https://lispcookbook.github.io/cl-cookbook/
with an Editors page: https://lispcookbook.github.io/cl-cookbook/editor-support.html where we see plugins for several popular editors (Atom, VSCode, Sublime Text, Eclipse, Geany… not counting Emacs and Vim), links to other editors (Lem, built in CL), custom REPLs (cl-repl, sbcli), and notebooks (Jupyter notebook).
the Awesome-CL list: https://github.com/CodyReichert/awesome-cl
with an Editors section too
which we can find also on https://common-lisp.net/libraries#header1-526
The historical resource is Cliki. It is a mess sometimes, but it can be useful. In the case of Atom-Slime, it is up-to-date and refers to SLIMA: https://www.cliki.net/atom-slime
And while I'm at it, there is also lisp-lang.org: https://lisp-lang.org/wiki/article/editors This site was the most beautiful one before common-lisp.net saw a rewrite, and is now less useful. It still has a beautiful showcase of Lisp success stories. And for more Lisp companies using CL, see awesome-lisp-companies (but don't assume it's complete!).
I hope that now, when you ask yourself "what can I use for … in Common Lisp", you'll find answers there, before using a search engine.
Best,
[1] disclaimer: often by myself
Short version:
Is there a way to allow other programs to call Lisp functions of a Lisp program?
Long version:
I'm contemplating a graph database project :) Not to be started immediately, I'm only probing the ground so far. I've tried couple of graph databases, and my biggest gripe about them is they all are written in Java, (some are in C++, which isn't going to cut it either...). Java has no good way of communicating outwards. It may only be embedded inside another Java program. C++ is just hard to embed / I'm dubious that embedding was even planned.
So, I would obviously want to write it in CL, but I'm considering other options too. So, if you believe that CL simply won't do it, but you have reasons to believe that some other language will, then that's an interesting answer! My requirements to the "other language" would be that it must support parallel computing in some way. Obviously, high performance. And, as mentioned, extensibility.
I see multiple ways to call Lisp from other languages:
The simplest way that should work with all implementations would be to just maintain a bidirectional stream to the REPL. So you could send commands to the REPL and receive the REPL's response. One drawback of this would of course be that everything would be converted to strings.
You could mirror the way SLIME communicates with SWANK. In that case, you either use SWANK directly on the Lisp side and communicate through the same protocol SLIME uses, or write your own version of such a library.
Finally, there are Lisp implementations designed with embeddability in mind. I'm thinking particularly of Embeddabble Common Lisp (ECL) here which has a C API. For example, this section in the manual explains how to call functions, by getting hold of the function's symbol with ecl_make_symbol and then calling it with cl_funcall or cl_apply.
As alternatives to Common Lisp, other Lisp languages might be worthwhile to consider. Various Scheme implementations are designed to be embeddable, this is for example the documentation of Racket's C API. It seems you prefer the native code side of the runtime world over the JVM, but otherwise, Clojure is also interesting for being embeddable within Java.
For the host language there are few limits because most languages should support "pipes" (i.e. streams to other processes) or have a C FFI to call some Lisp's C API.
Can (or should) a macro expansion have side effects? For example, here is a macro which actually goes and grabs the contents of a webpage at compile time:
#lang racket
(require (for-syntax net/url))
(require (for-syntax racket/port))
(define-syntax foo
(lambda (syntx)
(datum->syntax #'lex
(port->string
(get-pure-port
(string->url
(car (cdr (syntax->datum syntx)))))))))
Then, I can do (foo "http://www.pointlesssites.com/") and it will be replaced with "\r\n<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\"\r\n\t <and so on>"
Is this good practice, or not? Am I garunteed that Racket will only run this code once? If I add a (display "running...") line to the macro, it only prints once, but I would hate to generalize from one example ...
PS - the reason I'm asking is because I actually think this could be really useful sometimes. For example this is a library which allows you to load (at compile-time) a discovery document from the Google API Discovery service and automatically create wrappers for it. I think it would be really cool if the library actually fetched the discovery document from the web, instead of from a local file.
Also, to give an example of a macro with a different kind of side effects: I once built a macro which translated a small subset of Racket into (eta-expanded) lambda calculus (which is, of course, still runnable in Racket). Whenever the macro finished translating a function, it would store the result in a dictionary so that later invocations of the macro could make use of that function definition in their own translations.
The short answer
It's fine for macros to have side effects, but you should make sure that your program doesn't change behavior when it's compiled ahead of time.
The longer answer
Macros with side effects are a powerful tool, and can let you do things that make programs much easier to write, or enable things that wouldn't be possible at all. But there are pitfalls to be aware of when you use side effects in macros. Fortunately, Racket provides all the tools to make sure that you can do this correctly.
The simplest kind of macro side effect is where you use some external state to find the code you want to generate. The examples you list in the question (reading Google API description) are of this kind. An even simpler example is the include macro:
#lang racket
(include "my-file.rktl")
This reads the contents of myfile.rktl and drops it in place right where the include form is used.
Now, include isn't a good way to structure your program, but this is a quite benign sort of side effect in the macro. It works the same if you compile the file ahead of time as if you don't, since the result of the include is part of the file.
Another simple example that's not good is something like this:
#lang racket
(define-syntax (show-file stx)
(printf "using file ~a\n" (syntax-source stx))
#'(void))
(show-file)
That's because the printf gets executed only at compile time, so if you compile your program that uses show-file ahead of time (as with raco make) then the printf will happen then, and won't happen when the program is run, which probably isn't the intention.
Fortunately, Racket has a technique for letting you write macros like show-file effectively. The basic idea is to leave residual code that actually performs the side effect. In particular, you can use Racket's begin-for-syntax form for this purpose. Here's how I would write show-file:
#lang racket
(define-syntax (show-file stx)
#`(begin-for-syntax
(printf "using file ~a\n" #,(syntax-source stx))))
(show-file)
Now, instead of happening when the show-file macro is expanded, the printf happens in the code that show-file generates, with the source embedded in the expanded syntax. That way your program keeps working correctly in the presence of ahead-of-time compilation.
There are other uses of macros with side effects, too. One of the most prominent in Racket is for inter-module communication -- because require doesn't produce values that the requiring module can get, to communicate between modules the most effective way is to use side effects. To make this work in the presence of compilation requires almost exactly the same trick with begin-for-syntax.
This is a topic that the Racket community, and I in particular, have thought a lot about, and there are several academic papers talking about how this works:
Composable and Compilable Macros: You want it when?, Matthew Flatt, ICFP 2002
Advanced Macrology and the Implementation of Typed Scheme, Ryan Culpepper, Sam Tobin-Hochstadt, and Matthew Flatt, Scheme Workshop 2007
Languages as Libraries, Sam Tobin-Hochstadt, Ryan Culpepper, Vincent St-Amour, Matthew Flatt, and Matthias Felleisen, PLDI 2011
In common Lisp the function eval-when allows you to decide when the macro will be expanded.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
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?
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.
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.
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.
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.
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.
This worked for me:
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.
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
By watching legendary Structure and Interpretation of Computer Programs?
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.
Okay, I'm going to take a crack at this. I'm new to Lisp myself, just having arrived from the world of python. I haven't experienced that sudden moment of enlightenment that all the old Lispers talk about, but I'll tell you what I am seeing so far.
First, look at this random bit of python code:
def is_palindrome(st):
l = len(st)/2
return True if st[:l] == st[:-l-1:-1] else False
Now look at this:
"""
def is_palindrome(st):
l = len(st)/2
return True if st[:l] == st[:-l-1:-1] else False
"""
What do you, as a programmer, see? The code is identical, FYI.
If you are like me, you'll tend to think of the first as active code. It consists of a number of syntactic elements.
The second, despite its similarity, is a single syntactic item. It's a string. You interact with it as a single entity. To deal with it as code - to handle it comfortably along its syntactic boundaries - you will have to do some parsing. To execute it, you need to invoke an interpreter. It's not the same thing at all as the first.
So when we do code generation in most languages what are we dealing with? Strings. When I generate HTML or SQL with python I use python strings as the interface between the two languages. Even if I generate python with python, strings are the tool.*
Doesn't the thought of that just... make you want to dance with joy? There's always this grotesque mismatch between that which you are working with and that which you are working on. I sensed that the first time that I generated SQL with perl. Differences in escaping. Differences in formatting: think about trying to get a generated html document to look tidy. Stuff isn't easy to reuse. Etc.
To solve the problem we serially create templating libraries. Scads of them. Why so many? My guess is that they're never quite satisfactory. By the time they start getting powerful enough they've turned into monstrosities. Granted, some of them - such as SQLAlchemy and Genshi in the python world - are very beautiful and admirable monstrosities. Let's... um... avoid mention of PHP.
Because strings make an awkward interface between the worked-on language and the worked-with, we create a third language - templates - to avoid them. ** This also tends to be a little awkward.
Now let's look at a block of quoted Lisp code:
'(loop for i from 1 to 8 do (print i))
What do you see? As a new Lisp coder, I've caught myself looking at that as a string. It isn't. It is inactive Lisp code. You are looking at a bunch of lists and symbols. Try to evaluate it after turning one of the parentheses around. The language won't let you do it: syntax is enforced.
Using quasiquote, we can shoehorn our own values into this inactive Lisp code:
`(loop for i from 1 to ,whatever do (print i))
Note the nature of the shoehorning: one item has been replaced with another. We aren't formatting our value into a string. We're sliding it into a slot in the code. It's all neat and tidy.
In fact if you want to directly edit the text of the code, you are in for a hassle. For example if you are inserting a name <varname> into the code, and you also want to use <varname>-tmp in the same code you can't do it directly like you can with a template string: "%s-tmp = %s". You have to extract the name into a string, rewrite the string, then turn it into a symbol again and finally insert.
If you want to grasp the essence of Lisp, I think that you might gain more by ignoring defmacro and gensyms and all that window dressing for the moment. Spend some time exploring the potential of the quasiquote, including the ,# thing. It's pretty accessible. Defmacro itself only provides an easy way to execute the result of quasiquotes. ***
What you should notice is that the hermetic string/template barrier between the worked-on and the worked-with is all but eliminated in Lisp. As you use it, you'll find that your sense of two distinct layers - active and passive - tends to dissipate. Functions call macros which call macros or functions which have functions (or macros!) passed in with their arguments. It's kind of a big soup - a little shocking for the newcomer. That said, I don't find that the distinction between macros and functions is as seamless as some Lisp people say. Mostly it's ok, but every so often as I wander in the soup I find myself bumping up against the ghost of that old barrier - and it really creeps me out!
I'll get over it, I'm sure. No matter. The convenience pays for the scare.
Now that's Lisp working on Lisp. What about working on other languages? I'm not quite there yet, personally, but I think I see the light at the end of the tunnel. You know how Lisp people keep going on about S-expressions being the same thing as a parse tree? I think the idea is to parse the foreign language into S-expressions, work on them in the amazing comfort of the Lisp environment, then send them back to native code. In theory, every language out there could be turned into S-expressions, or even executable lisp code. You're not working in a first language combined with a third language to produce code in a second language. It is all - while you are working on it - Lisp, and you can generate it all with quasiquotes.
Have a look at this (borrowed from PCL):
(define-html-macro :mp3-browser-page ((&key title (header title)) &body body)
`(:html
(:head
(:title ,title)
(:link :rel "stylesheet" :type "text/css" :href "mp3-browser.css"))
(:body
(standard-header)
(when ,header (html (:h1 :class "title" ,header)))
,#body
(standard-footer))))
Looks like an S-expression version of HTML, doesn't it? I have a feeling that Lisp works just fine as its own templating library.
I've started to wonder about an S-expression version of python. Would it qualify as a Lisp? It certainly wouldn't be Common Lisp. Maybe it would be nicer - for python programmers at least. Hey, and what about P-expressions?
* Python now has something called AST, which I haven't explored. Also a person could use python lists to represent other languages. Relative to Lisp, I suspect that both are a bit of a hack.
** SQLAlchemy is kind of an exception. It's done a nice job of turning SQL directly into python. That said, it appears to have involved significant effort.
*** Take it from a newbie. I'm sure I'm glossing over something here. Also, I realize that quasiquote is not the only way to generate code for macros. It's certainly a nice one, though.
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.
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.
Read and understand the legendary page 13 of the Lisp 1.5 Programmer's Manual
According to Alan Kay, at least.
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.
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.
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.
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).
it's important to see that data is code AND code is data. This feeds the eval/apply loop. Recursion is also fun.
(This link is broken:
![Eval/Apply][1]
[1]: http://ely.ath.cx/~piranha/random_images/lolcode-eval_apply-2.jpg
)
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.
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?
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!
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.
This may be helpful: http://www.defmacro.org/ramblings/fp.html (isn't about LISP but about functional programming as a paradigm)
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.
I've been wanting to teach myself Lisp for a while. However, all the interpreters of which I've heard involve some flavor of emacs.
Are there any command line interpreters, such that I could type this into the command line:
lispinterpret sourcefile.lisp
just like I can run perl or python.
While I'd also like to become more familiar with Emacs (if only not to be frustrated when I work with somebody who uses Emacs), I'd rather decouple learning Emacs from learning Lisp.
Edit: I actually want to follow SICP which uses Scheme, so an answer about Scheme would be more useful. I'm just not that familiar with the differences.
You could also try DrScheme, which whilst not exactly a standalone interpreter, isn't emacs :)
It's basically a simple IDE that has an area to type in code that can be executed as a file, and then another area that is the running interpreter that you can interact with.
(Also, find the UC Berkeley CS61A podcasts and listen to them, as well as reading SICP)
It looks like Steel Bank Common Lisp (SBCL) also caters to what you want:
http://www.sbcl.org/manual/#Shebang-Scripts
SBCL is both top rate and open source.
Checkout CLISP wiki-link that ie. was used by Paul Graham
Direct link
I often write lisp shell scripts which start with this line:
#!/usr/bin/clisp
Then you don't even need to type "lispinterpret" on the command-line. Just mark the script executable and run it directly.
Most scheme interpreters that I am familiar with can be run from the command line. (Much of the list below is extracted from the comparative table at Alexey Radul's Scheme Implementation Choices page. There is a more extensive list at schemewiki but that page does not immediately provide command-line invocation syntax.)
Here's how you run a number of implementations at the command line:
Chez Scheme: scheme, petite
MIT Scheme: mit-scheme
Scheme 48: scheme48
RScheme: rs
Racket: racket (But I recommend trying the DrRacket IDE, especially for beginners.)
Guile: guile
Bigloo: bigloo
Chicken: csi
Gambit: gsi
Gauche: gosh
IronScheme: IronScheme.Console
Kawa: kawa, java kawa.repl
Larceny: larceny
SCM: scm
If you are looking for Scheme to work with the SICP, take a look at MIT/GNU Scheme
http://groups.csail.mit.edu/mac/projects/scheme/
http://www.gnu.org/software/mit-scheme/index.html
The most widely used IDE for Common Lisp, particularly in the free software subset of the community, is in fact SLIME, which runs on Emacs. You can use whatever CL compiler you prefer and invoke Lisp source files the way you describe, but if you do that, you won't be taking advantage of many of Lisps dynamic features that are so incredibly useful while developing your application.
I suggest you take a look at this SLIME demonstration video to see what I mean, even though it might be a bit outdated at this point.
If the problem is that you (think you) don't like Emacs, I seriously suggest you try to learn it. Seriously. No, really, I mean that. However, there are alternatives, such as the IDEs provided by commercial Lisp implementations such as Allegro and Lispworks (free trials available), or an Eclipse plug-in called Cusp.
Did you try Allegro CL from http://www.franz.com/?
#Nathan: I've upmodded the Common Lisp links, because you asked about Lisp (especially with reference to Emacs Lisp). However, Common Lisp is very different from Scheme. A program written for one is unlikely to run on the other.
As you mentioned, SICP is for learning Scheme, not Lisp (or at least, not Common Lisp and not Emacs Lisp). There are some overlap in principles, however you can't simply cut and paste code from SICP and expect it to run on any Common Lisp or Emacs Lisp system. :-)
No "interpreter" requires emacs.
Also, emacs can run elisp in a headless manner.
It seems like scheme shell is suitable for your purpose.
Take a look at http://www.scsh.net/index.html
Another good dialect of lisp is cmucl. They used to love to brag about being the "fastest" lisp.