Is Lisp the only language with REPL? - lisp

There are languages other than Lisp (ruby, scala) that say they use REPL (Read, Eval, Print, Loop), but it is unclear whether what is meant by REPL is the same as in Lisp. How is Lisp REPL different from non-Lisp REPL?

The idea of a REPL comes from the Lisp community. There are other forms of textual interactive interfaces, for example the command line interface. Some textual interfaces also allow a subset of some kind of programming language to be executed.
REPL stands for READ EVAL PRINT LOOP: (loop (print (eval (read)))).
Each of the four above functions are primitive Lisp functions.
In Lisp the REPL is not a command line interpreter (CLI). READ does not read commands and the REPL does not execute commands. READ reads input data in s-expression format and converts it to internal data. Thus the READ function can read all kinds of s-expressions - not just Lisp code.
READ reads a s-expression. This is a data-format that also supports encoding source code. READ returns Lisp data.
EVAL takes Lisp source code in the form of Lisp data and evaluates it. Side effects can happen and EVAL returns one or more values. How EVAL is implemented, with an interpreter or a compiler, is not defined. Implementations use different strategies.
PRINT takes Lisp data and prints it to the output stream as s-expressions.
LOOP just loops around this. In real-life a REPL is more complicated and includes error handling and sub-loops, so-called break loops. In case of an error one gets just another REPL, with added debug commands, in the context of the error. The value produced in one iteration also can be reused as input for the next evaluation.
Since Lisp is both using code-as-data and functional elements, there are slight differences to other programming languages.
Languages that are similar, those will provide also similar interactive interfaces. Smalltalk for example also allows interactive execution, but it does not use a data-format for I/O like Lisp does. Same for any Ruby/Python/... interactive interface.
Question:
So how significant is the original idea of READing EXPRESSIONS, EVALuating them and PRINTing their values? Is that important in relation to what other languages do: reading text, parsing it, executing it, optionally print something and optionally printing a return value? Often the return value is not really used.
So there are two possible answers:
a Lisp REPL is different to most other textual interactive interfaces, because it is based on the idea of data I/O of s-expressions and evaluating these.
a REPL is a general term describing textual interactive interfaces to programming language implementations or subsets of those.
REPLs in Lisp
In real implementations Lisp REPLs have a complex implementation and provide a lot of services, up to clickable presentations (Symbolics, CLIM, SLIME) of input and output objects. Advanced REPL implementations are for example available in SLIME (a popular Emacs-based IDE for Common Lisp), McCLIM, LispWorks and Allegro CL.
Example for a Lisp REPL interaction:
a list of products and prices:
CL-USER 1 > (setf *products* '((shoe (100 euro))
(shirt (20 euro))
(cap (10 euro))))
((SHOE (100 EURO)) (SHIRT (20 EURO)) (CAP (10 EURO)))
an order, a list of product and amount:
CL-USER 2 > '((3 shoe) (4 cap))
((3 SHOE) (4 CAP))
The price for the order, * is a variable containing the last REPL value. It does not contain this value as a string, but the real actual data.
CL-USER 3 > (loop for (n product) in *
sum (* n (first (second (find product *products*
:key 'first)))))
340
But you can also compute Lisp code:
Let's take a function which adds the squares of its two args:
CL-USER 4 > '(defun foo (a b) (+ (* a a) (* b b)))
(DEFUN FOO (A B) (+ (* A A) (* B B)))
The fourth element is just the arithmetic expression. * refers to the last value:
CL-USER 5 > (fourth *)
(+ (* A A) (* B B))
Now we add some code around it to bind the variables a and b to some numbers. We are using the Lisp function LIST to create a new list.
CL-USER 6 > (list 'let '((a 12) (b 10)) *)
(LET ((A 12) (B 10)) (+ (* A A) (* B B)))
Then we evaluate the above expression. Again, * refers to the last value.
CL-USER 7 > (eval *)
244
There are several variables which are updated with each REPL interaction. Examples are *, ** and *** for the previous values. There is also + for the previous input. These variables have as values not strings, but data objects. + will contain the last result of the read operation of the REPL. Example:
What is the value of the variable *print-length*?
CL-USER 8 > *print-length*
NIL
Let's see how a list gets read and printed:
CL-USER 9 > '(1 2 3 4 5)
(1 2 3 4 5)
Now let's set the above symbol *print-length* to 3. ++ refers to the second previous input read, as data. SET sets a symbols value.
CL-USER 10 > (set ++ 3)
3
Then above list prints differently. ** refers to the second previous result - data, not text.
CL-USER 11 > **
(1 2 3 ...)

Seeing as the concept of a REPL is to just Read, Eval, Print & Loop it's not too suprising that there are REPLs for many languages:
C/C++
C#/LINQ
Erlang
Haskell (on windows)
Java
Javascript
Julia
Perl
Python
Ruby
Scala
Smalltalk -- I learned it on a REPL!

I think it is interesting to compare two approaches. A bare bones REPL loop in a Lisp system would look like this:
(loop (print (eval (read))))
Here are two actual Forth implementations of a REPL loop. I'm leaving nothing out here -- this is the full code to these loops.
: DO-QUIT ( -- ) ( R: i*x -- )
EMPTYR
0 >IN CELL+ ! \ set SOURCE-ID to 0
POSTPONE [
BEGIN \ The loop starts here
REFILL \ READ from standard input
WHILE
INTERPRET \ EVALUATE what was read
STATE # 0= IF ." OK" THEN \ PRINT
CR
REPEAT
;
: quit
sp0 # 'tib !
blk off
[compile] [
begin
rp0 # rp!
status
query \ READ
run \ EVALUATE
state # not
if ." ok" then \ PRINT
again \ LOOP
;
Lisp and Forth do completely different things, particularly in the EVAL part, but also in the PRINT part. Yet, they share the fact that a program in both languages is run by feeding its source code to their respective loops, and in both cases code is just data (though in Forth case it is more like data is also code).
I suspect what anyone saying only LISP has a REPL is that the READ loop reads DATA, which is parsed by EVAL, and a program is created because CODE is also DATA. This distinction is interesting in many respects about the difference between Lisp and other languages, but as far as REPL goes, it doesn't matter at all.
Let's consider this from the outside:
READ -- returns input from stdin
EVAL -- process said input as an expression in the language
PRINT -- print EVAL's result
LOOP -- go back to READ
Without going into implementation details, one can't distinguish a Lisp REPL from, for example, a Ruby REPL. As functions, they are the same.

I guess you could say that Scala's "REPL" is an "RCRPL": Read, Compile, Run, Print. But since the compiler is kept "hot" in memory, it's pretty fast for ongoing interactions--it just takes a few seconds to start up.

There are a number of people that consider a REPL to needs to behave exactly like it does in LISP, or it's not a true REPL. Rather, they consider it something different, like a CLI (command line interpreter). Honestly, I tend to think that if it follows the basic flow of:
read input from the user
evaluate that input
print the output
loop back to the read
then it's a REPL. As noted, there are a lot of languages that have the above capability.
See this reddit thread for an example of such a discussion.

How is Lisp REPL different from non-Lisp REPL?
Let's compare Common Lisp's REPL with Python's IPython.
The main two points are:
Lisp is an image-based language. There is no need to restart the process/the REPL/the whole app after a change. We compile our code function by function (with compiler warnings etc).
we don't loose state. Even more, when we update class definitions, our objects in the REPL are also updated, following rules we have control upon. That way we can hot-reload code in a running system.
In Python, typically, you start IPython or you are dropped into ipdb. You define some data until you try out your new function. You edit your source, and you want to try again, so you quit IPython and you start the whole process again. In Lisp (Common Lisp mainly), not at all, it's all more interactive.

There's a nice project called multi-repl which exposes various REPLs via Node.JS:
https://github.com/evilhackerdude/multi-repl
If you look at the list of supported languages, it's quite clear that not only Lisp has the concept of a REPL.
clj (clojure)
ghci (ghc)
ipython
irb (ruby)
js (spidermonkey)
node
python
sbcl
v8
In fact implementing a trivial one in Ruby is fairly easy:
repl = -> prompt { print prompt; puts(" => %s" % eval(gets.chomp!)) }
loop { repl[">> "] }

Related

Why is Common Lisp's print output preceeded by a newline and followed by a space?

The Common Lisp Hyperspec page for print mentions this:
print is just like prin1 except that the printed representation of object is preceded by a newline and followed by a space.
This is the first time I've seen a function like this, and it threw me off the first time I used it, because I never expected that a function with such a common name might include an uncommon feature.
I'm looking for the original reason. I know it might simply be because that's how another then-common lisp might have done it, and common-lisp simply adopted it, but if that's the case I'm looking for the design reason in that other lisp.
I imagine it might have something to do with ensuring that the output is always readable with read straight out of print. Though I would've preferred a newline for this, I can guess that the trailing space might be so that in a stream, read can know that it's the end of an object and return it immediately without having to wait for the rest of the stream (the following prints). However, I still can't figure out the purpose behind the preceeding newline.
I've been looking through the HyperSpec, but I can't find a reason mentioned.
EDIT:
I looked into Common-Lisp's predecessors, specifically InterLisp, MacLisp, and MacLisp's predecessor Lisp 1.5.
Interlisp's (page 145 in this pdf) and Lisp 1.5's (page 140 in this pdf) print function print the object followed by a newline.
It seems it was MacLisp that introduced this difference. I didn't find a reason in the original reference manual, and I only found the following on this revised reference manual:
Like PRIN1, PRINT outputs object to file in a form that can be understood by READ. However, object is output preceded by newline and followed by a space so that repeated calls to PRINT can be done without having the end of one object run into the begining of the next.
Of course, the trailing newline in the original definition would've sufficed for that purpose, so this reason doesn't seem valid.
EDIT 2:
As shown by Rainer Joswig's answer, it seems that this change appeared in Lisp 1.6 before MacLisp.
See for example: PDP-6 LISP (LISP 1.6) Revised. (January 1967)
My guess would be that this variant of PRINT (which writes a newline, then the s-expression in readable format and then a space) entered the MIT branch of Lisp because of its use in the Read Eval Print Loop. See page 1 and 17 of above. From PDP-6 Lisp 1.6 it moved into what was then called Maclisp and beyond.
Jon L White would know it.
Look at the example for the REPL, the read eval PRINT loop, on page 1.
Here I use a LispWorks Lisp listener, where the last closing parenthesis already makes READ accept the s-expression and no further enter is necessary:
CL-USER 25 > (PROG NIL
A
(TERPRI)
(PRINT (EVAL (READ)))
(GO A))
(+ 12 12)
24
(+ 45 (*
34
12
12))
4941
Each result is on its own line. This is btw. also like the interaction on a MIT Lisp Machine - the last closing parenthesis enters the s-expression, the expression is evaluated and the value(s) printed.
Now imagine that it is defined to not print a newline first:
CL-USER 27 > (PROG NIL
A
(TERPRI)
(PRIN1 (EVAL (READ)))
(terpri)
(GO A))
(+ 1 2)3
(* 23 (+ 1
1
3))115
The result would be printed directly after the last closing parenthesis.
Peter Norvig gives the same reasoning in his book Paradigms of Artificial Intelligence Programming, page 231/232 (as noted by user dkim):
In Lisp, however, the function print puts in a newline before the object to be printed, and a space after. ... In UNIX there was only one reasonable policy, because all input to the UNIX interpreter (the shell) is terminated by newlines, so there is no need for a newline-before. In some Lisp interpreters, however, input can be terminated by a matching right parenthesis. In that case, a newline-before is needed, lest the output appear on the same line as the input.
Basically this is a REPL-only function, something along the lines of "poor man's trace or debug".
It's use case is something like
(map nil #'print list)
or, more generally,
(complex-traversal-map #'print weird-structure)
It inserts whitespace around the printed object to avoid interference
with the output of other print calls.
What kind of whitespace is emitted has evolved over the decades.
It should have been called print-on-a-separate-line but it had to be
short and easily guessable.
It's essentially "legacy" functionality, like rplaca and rplacd.

LISP lists and normal form

Some LISP expressions evaluate to themselves (examples are MIT-Scheme REPL, though GNU Common Lisp agrees):
1 ]=> 3
;Value: 3
And are in normal form. Evaluation of an expression (such as (+ 2 1)) thus can properly be said to be conversion to normal form. That's nice, because that's how I've always understood evaluation formally.
But with lists we're in trouble:
1 ]=> (list 3 2)
; Value 16: (3 2)
1 ]=> (3 2)
;The object 3 is not applicable.
;To continue, call RESTART with an option number:
; (RESTART 2) => Specify a procedure to use in its place.
; (RESTART 1) => Return to read-eval-print level 1.
Am I right in thinking that:
(many[0]) LISPs don't have normal forms for (non-empty) lists, and
(many) LISPs do not have the property that evaluation is reduction to normal form?
If so, isn't this somewhat at odds with formalisms in PLT such as abstract rewriting systems? What alternative formalisms do capture evaluation in LISPs?
[0] Or perhaps more accurately, "most of the prominent LISPs", such as CL, Clojure, and Scheme. But I'd be interested in less well-known counter-examples!
Lisp can be defined in terms of only a few primitive operators. How many primitives does it take to build a LISP machine? Ten, seven or five? So you could consider there to be a normal form for what you get from expanding to them.
But Lisp isn't the lambda calculus. What type of lambda calculus would Lisp loosely be an example of?
And Lisp wasn't designed to be like the lambda calculus:
To use functions as arguments, one needs a notation for functions, and it seems natural to use the lambda-notation of Church. I didn’t understand the rest of the book, so I wasn’t tempted to try to implement his more general mechanism for defining functions.
-- History of Lisp, Stanford AI Laboratory memo 1979 by J. McCarthy, page 6

Is a macro that puts the contents of a form into a string possible?

I'd like to write a macro that treats its arguments as a string.
(defmacro args->string (&rest args)
"Change all arguments into strings and combine them."
(nlp/auto-generate-code-based-on-doc))
Then I could write code like:
(python> import numpy as np) ;= nil
(python> np.array([1, 2, 3])) ;= [1 2 3]
(R> rnorm(100)) ;= [0.234223 0.44234 ...]
(hy> (+ 1 1)) ;= 2
that does inter-process communication through the already existing inferior-process framework.
Is this even possible in Emacs lisp?
Short answer: no, this is not possible without hacking the Emacs Lisp reader.
Lisp evaluation proceeds in three steps: first, the characters are converted into list structure — this is called reading. Then, all macros are expanded. Finally, the resulting list structure is evaluated.
By the time a macro is called, the input has already been converted into list structure, and a fair amount of information about the original input has been lost; it is impossible in general to recover the original input at this stage.
As mentioned by Jon O., what you need is to hook earlier, at the reading stage. This is possible in Common Lisp using reader macros, but is not supported by Emacs Lisp.

Good examples of Clojure macros usage which demonstrate advantages of the language over the mainstream?

I am thinking about learning Clojure, but coming from the c-syntax based (java, php, c#) world of imperative languages that's going to be a challenge, so one naturally asks oneself, is it really worth it? And while such question statement can be very subjective and hard to manage, there is one specific trait of Clojure (and more generally, the lisps) that I keep reading about, that is supposed to make it the most flexipowerful language ever: the macros.
Do you have any good examples of macro usage in Clojure, for purposes which in other mainstream languages (consider any of C++, PHP, Perl, Python, Groovy/Java, C#, JavaScript) would require much less elegant solutions/a lot of unnecessary abstraction/hacks/etc.
I find macros pretty useful for defining new language features. In most languages you would need to wait for a new release of the language to get new syntax - in Lisp you can just extend the core language with macros and add the features yourself.
For example, Clojure doesn't have a imperative C-style for(i=0 ;i<10; i++) loop but you can easily add one with a macro:
(defmacro for-loop [[sym init check change :as params] & steps]
(cond
(not (vector? params))
(throw (Error. "Binding form must be a vector for for-loop"))
(not= 4 (count params))
(throw (Error. "Binding form must have exactly 4 arguments in for-loop"))
:default
`(loop [~sym ~init value# nil]
(if ~check
(let [new-value# (do ~#steps)]
(recur ~change new-value#))
value#))))
Usage as follows:
(for-loop [i 0, (< i 10), (inc i)]
(println i))
Whether it is a good idea to add an imperative loop to a functional language is a debate we should probably avoid here :-)
there are a lot of macros in the base of clojure that you don't think about... Which is a sign of a good macro, they let you extend the language in ways that make life easier. With out macros life would be much less exciting. for instance if we didn't have
(with-out-str (somebody else's code that prints to screen))
then you would need to modify their code in ways that you may not have access to.
another great example is
(with-open-file [fh (open-a-file-code ...)]
(do (stuff assured that the file won't leak)))
the whole with-something-do pattern of macros have really added to the clojure eco system.
the other side of the proverbial macro coin is that I spend essentially all of my (current) professional Clojure time using a very macro heavy library and thus i spend a lot of time working around the fact that macros don't compose well and are not first class. The authors of this library are going to great lengths in the next version to make all the functionality available with out going through the macros to allow people like me to use them in higher order functions like map and reduce.
macros improve the world when they make life easier. They can have the opposite effect when they are the only interface to a library. please don't use macros as interfaces
It is hard in general to get the shape of your data truly correct. If as a library author, you have the data structured well for how you envision your library being used it may very well be that there is a way to re-structure things to allow users to employ your library in new and unimaginable ways. In this case the structure of the fantastic library in question was really quite good, it allowed for things the authors had not intended. Unfortunatly a great library was restricted because it's interface was a set of macros not a set of functions. the library was better than it's macros, so they held it back. This is not to say that macros are in any way to blame, just that programming is hard and they are another tool that can have many effects and all the pieces must be used together to work well.
There's also a more esoteric use case for macros that I sometimes use: writing concise, readable code that is also fully optimized. Here's a trivial example:
(defmacro str* [& ss] (apply str (map eval ss)))
What this does is concatenate strings at compile time (they have to be compile-time constants, of course). The regular string concatenation function in Clojure is str so wherever in a tight-loop code I have a long string that I would like to break up into several string literals, I just add the star to str and change runtime concatenation to compile-time. Usage:
(str* "I want to write some very lenghty string, most often it will be a complex"
" SQL query. I'd hate if it meant allocating the string all over every time"
" this is executed.")
Another, less trivial example:
(defmacro jprint [& xs] `(doto *out* ~#(for [x xs] `(.append ~x))))
The & means it accepts a variable number of arguments (varargs, variadic function). In Clojure a variadic function call makes use of a heap-allocated collection to transfer the arguments (like in Java, which uses an array). This is not very optimal, but if I use a macro like above, then there's no function call. I use it like this:
(jprint \" (json-escape item) \")
It compiles into three invocations of PrintWriter.append (basically an unrolled loop).
Finally, I would like to show you something even more radically different. You can use a macro to assist you in defining a clas of similar functions, eliminating vast amounts of boilerplate. Take this familiar example: in an HTTP-client library we want a separate function for each of the HTTP methods. Every function definition is quite complex as it has four overloaded signatures. Also, each function involves a different request class from the Apache HttpClient library, but everything else is exactly the same for all HTTP methods. Look how much code I need to handle this.
(defmacro- def-http-method [name]
`(defn ~name
([~'url ~'headers ~'opts ~'body]
(handle (~(symbol (str "Http" (s/capitalize name) ".")) ~'url) ~'headers ~'opts ~'body))
([~'url ~'headers ~'opts] (~name ~'url ~'headers ~'opts nil))
([~'url ~'headers] (~name ~'url ~'headers nil nil))
([~'url] (~name ~'url nil nil nil))))
(doseq [m ['GET 'POST 'PUT 'DELETE 'OPTIONS 'HEAD]]
(eval `(def-http-method ~m)))
Some actual code from a project I was working on -- I wanted nested for-esque loops using unboxed ints.
(defmacro dofor
[[i begin end step & rest] & body]
(when step
`(let [end# (long ~end)
step# (long ~step)
comp# (if (< step# 0)
>
<)]
(loop [~i ~begin]
(when (comp# ~i end#)
~#(if rest
`((dofor ~rest ~#body))
body)
(recur (unchecked-add ~i step#)))))))
Used like
(dofor [i 2 6 2
j i 6 1]
(println i j))
Which prints out
2 2
2 3
2 4
2 5
4 4
4 5
It compiles to something very close to the raw loop/recurs that I was originally writing out by hand, so there is basically no runtime performance penalty, unlike the equivalent
(doseq [i (range 2 6 2)
j (range i 6 1)]
(println i j))
I think that the resulting code compares rather favorably to the java equivalent:
for (int i = 2; i < 6; i+=2) {
for (int j = i; j < 6; j++) {
System.out.println(i+" "+j);
}
}
A simple example of a useful macro that is rather hard to re-create without macros is doto. It evaluates its first argument and then evaluates the following forms, inserting the result of the evaluation as their first argument. This might not sound like much, but...
With doto this:
(let [tmpObject (produceObject)]
(do
(.setBackground tmpObject GREEN)
(.setThis tmpObject foo)
(.setThat tmpObject bar)
(.outputTo tmpObject objectSink)))
Becomes that:
(doto (produceObject)
(.setBackground GREEN)
(.setThis foo)
(.setThat bar)
(.outputTo objectSink))
The important thing is that doto is not magic - you can (re-)build it yourself using the standard features of the language.
Macros are part of Clojure but IMHO do not believe they are why you should or should not learn Clojure. Data immutability, good constructs to handle concurrent state, and the fact it's a JVM language and can harness Java code are three reasons. If you can find no other reason to learn Clojure, consider the fact that a functional programming language probably should positively affect how you approach problems in any language.
To look at macros, I suggest you start with Clojure's threading macros: thread-first and thread-last -> and ->> respectively; visit this page, and many of the various blogs that discuss Clojure .
Good luck, and have fun.

What makes Lisp macros so special?

Reading Paul Graham's essays on programming languages one would think that Lisp macros are the only way to go. As a busy developer, working on other platforms, I have not had the privilege of using Lisp macros. As someone who wants to understand the buzz, please explain what makes this feature so powerful.
Please also relate this to something I would understand from the worlds of Python, Java, C# or C development.
To give the short answer, macros are used for defining language syntax extensions to Common Lisp or Domain Specific Languages (DSLs). These languages are embedded right into the existing Lisp code. Now, the DSLs can have syntax similar to Lisp (like Peter Norvig's Prolog Interpreter for Common Lisp) or completely different (e.g. Infix Notation Math for Clojure).
Here is a more concrete example:Python has list comprehensions built into the language. This gives a simple syntax for a common case. The line
divisibleByTwo = [x for x in range(10) if x % 2 == 0]
yields a list containing all even numbers between 0 and 9. Back in the Python 1.5 days there was no such syntax; you'd use something more like this:
divisibleByTwo = []
for x in range( 10 ):
if x % 2 == 0:
divisibleByTwo.append( x )
These are both functionally equivalent. Let's invoke our suspension of disbelief and pretend Lisp has a very limited loop macro that just does iteration and no easy way to do the equivalent of list comprehensions.
In Lisp you could write the following. I should note this contrived example is picked to be identical to the Python code not a good example of Lisp code.
;; the following two functions just make equivalent of Python's range function
;; you can safely ignore them unless you are running this code
(defun range-helper (x)
(if (= x 0)
(list x)
(cons x (range-helper (- x 1)))))
(defun range (x)
(reverse (range-helper (- x 1))))
;; equivalent to the python example:
;; define a variable
(defvar divisibleByTwo nil)
;; loop from 0 upto and including 9
(loop for x in (range 10)
;; test for divisibility by two
if (= (mod x 2) 0)
;; append to the list
do (setq divisibleByTwo (append divisibleByTwo (list x))))
Before I go further, I should better explain what a macro is. It is a transformation performed on code by code. That is, a piece of code, read by the interpreter (or compiler), which takes in code as an argument, manipulates and the returns the result, which is then run in-place.
Of course that's a lot of typing and programmers are lazy. So we could define DSL for doing list comprehensions. In fact, we're using one macro already (the loop macro).
Lisp defines a couple of special syntax forms. The quote (') indicates the next token is a literal. The quasiquote or backtick (`) indicates the next token is a literal with escapes. Escapes are indicated by the comma operator. The literal '(1 2 3) is the equivalent of Python's [1, 2, 3]. You can assign it to another variable or use it in place. You can think of `(1 2 ,x) as the equivalent of Python's [1, 2, x] where x is a variable previously defined. This list notation is part of the magic that goes into macros. The second part is the Lisp reader which intelligently substitutes macros for code but that is best illustrated below:
So we can define a macro called lcomp (short for list comprehension). Its syntax will be exactly like the python that we used in the example [x for x in range(10) if x % 2 == 0] - (lcomp x for x in (range 10) if (= (% x 2) 0))
(defmacro lcomp (expression for var in list conditional conditional-test)
;; create a unique variable name for the result
(let ((result (gensym)))
;; the arguments are really code so we can substitute them
;; store nil in the unique variable name generated above
`(let ((,result nil))
;; var is a variable name
;; list is the list literal we are suppose to iterate over
(loop for ,var in ,list
;; conditional is if or unless
;; conditional-test is (= (mod x 2) 0) in our examples
,conditional ,conditional-test
;; and this is the action from the earlier lisp example
;; result = result + [x] in python
do (setq ,result (append ,result (list ,expression))))
;; return the result
,result)))
Now we can execute at the command line:
CL-USER> (lcomp x for x in (range 10) if (= (mod x 2) 0))
(0 2 4 6 8)
Pretty neat, huh? Now it doesn't stop there. You have a mechanism, or a paintbrush, if you like. You can have any syntax you could possibly want. Like Python or C#'s with syntax. Or .NET's LINQ syntax. In end, this is what attracts people to Lisp - ultimate flexibility.
You will find a comprehensive debate around lisp macro here.
An interesting subset of that article:
In most programming languages, syntax is complex. Macros have to take apart program syntax, analyze it, and reassemble it. They do not have access to the program's parser, so they have to depend on heuristics and best-guesses. Sometimes their cut-rate analysis is wrong, and then they break.
But Lisp is different. Lisp macros do have access to the parser, and it is a really simple parser. A Lisp macro is not handed a string, but a preparsed piece of source code in the form of a list, because the source of a Lisp program is not a string; it is a list. And Lisp programs are really good at taking apart lists and putting them back together. They do this reliably, every day.
Here is an extended example. Lisp has a macro, called "setf", that performs assignment. The simplest form of setf is
(setf x whatever)
which sets the value of the symbol "x" to the value of the expression "whatever".
Lisp also has lists; you can use the "car" and "cdr" functions to get the first element of a list or the rest of the list, respectively.
Now what if you want to replace the first element of a list with a new value? There is a standard function for doing that, and incredibly, its name is even worse than "car". It is "rplaca". But you do not have to remember "rplaca", because you can write
(setf (car somelist) whatever)
to set the car of somelist.
What is really happening here is that "setf" is a macro. At compile time, it examines its arguments, and it sees that the first one has the form (car SOMETHING). It says to itself "Oh, the programmer is trying to set the car of somthing. The function to use for that is 'rplaca'." And it quietly rewrites the code in place to:
(rplaca somelist whatever)
Common Lisp macros essentially extend the "syntactic primitives" of your code.
For example, in C, the switch/case construct only works with integral types and if you want to use it for floats or strings, you are left with nested if statements and explicit comparisons. There's also no way you can write a C macro to do the job for you.
But, since a lisp macro is (essentially) a lisp program that takes snippets of code as input and returns code to replace the "invocation" of the macro, you can extend your "primitives" repertoire as far as you want, usually ending up with a more readable program.
To do the same in C, you would have to write a custom pre-processor that eats your initial (not-quite-C) source and spits out something that a C compiler can understand. It's not a wrong way to go about it, but it's not necessarily the easiest.
Lisp macros allow you to decide when (if at all) any part or expression will be evaluated. To put a simple example, think of C's:
expr1 && expr2 && expr3 ...
What this says is: Evaluate expr1, and, should it be true, evaluate expr2, etc.
Now try to make this && into a function... thats right, you can't. Calling something like:
and(expr1, expr2, expr3)
Will evaluate all three exprs before yielding an answer regardless of whether expr1 was false!
With lisp macros you can code something like:
(defmacro && (expr1 &rest exprs)
`(if ,expr1 ;` Warning: I have not tested
(&& ,#exprs) ; this and might be wrong!
nil))
now you have an &&, which you can call just like a function and it won't evaluate any forms you pass to it unless they are all true.
To see how this is useful, contrast:
(&& (very-cheap-operation)
(very-expensive-operation)
(operation-with-serious-side-effects))
and:
and(very_cheap_operation(),
very_expensive_operation(),
operation_with_serious_side_effects());
Other things you can do with macros are creating new keywords and/or mini-languages (check out the (loop ...) macro for an example), integrating other languages into lisp, for example, you could write a macro that lets you say something like:
(setvar *rows* (sql select count(*)
from some-table
where column1 = "Yes"
and column2 like "some%string%")
And thats not even getting into Reader macros.
Hope this helps.
I don't think I've ever seen Lisp macros explained better than by this fellow: http://www.defmacro.org/ramblings/lisp.html
A lisp macro takes a program fragment as input. This program fragment is represented a data structure which can be manipulated and transformed any way you like. In the end the macro outputs another program fragment, and this fragment is what is executed at runtime.
C# does not have a macro facility, however an equivalent would be if the compiler parsed the code into a CodeDOM-tree, and passed that to a method, which transformed this into another CodeDOM, which is then compiled into IL.
This could be used to implement "sugar" syntax like the for each-statement using-clause, linq select-expressions and so on, as macros that transforms into the underlying code.
If Java had macros, you could implement Linq syntax in Java, without needing Sun to change the base language.
Here is pseudo-code for how a lisp-style macro in C# for implementing using could look:
define macro "using":
using ($type $varname = $expression) $block
into:
$type $varname;
try {
$varname = $expression;
$block;
} finally {
$varname.Dispose();
}
Since the existing answers give good concrete examples explaining what macros achieve and how, perhaps it'd help to collect together some of the thoughts on why the macro facility is a significant gain in relation to other languages; first from these answers, then a great one from elsewhere:
... in C, you would have to write a custom pre-processor [which would probably qualify as a sufficiently complicated C program] ...
—Vatine
Talk to anyone that's mastered C++ and ask them how long they spent learning all the template fudgery they need to do template metaprogramming [which is still not as powerful].
—Matt Curtis
... in Java you have to hack your way with bytecode weaving, although some frameworks like AspectJ allows you to do this using a different approach, it's fundamentally a hack.
—Miguel Ping
DOLIST is similar to Perl's foreach or Python's for. Java added a similar kind of loop construct with the "enhanced" for loop in Java 1.5, as part of JSR-201. Notice what a difference macros make. A Lisp programmer who notices a common pattern in their code can write a macro to give themselves a source-level abstraction of that pattern. A Java programmer who notices the same pattern has to convince Sun that this particular abstraction is worth adding to the language. Then Sun has to publish a JSR and convene an industry-wide "expert group" to hash everything out. That process--according to Sun--takes an average of 18 months. After that, the compiler writers all have to go upgrade their compilers to support the new feature. And even once the Java programmer's favorite compiler supports the new version of Java, they probably ''still'' can't use the new feature until they're allowed to break source compatibility with older versions of Java. So an annoyance that Common Lisp programmers can resolve for themselves within five minutes plagues Java programmers for years.
—Peter Seibel, in "Practical Common Lisp"
Think of what you can do in C or C++ with macros and templates. They're very useful tools for managing repetitive code, but they're limited in quite severe ways.
Limited macro/template syntax restricts their use. For example, you can't write a template which expands to something other than a class or a function. Macros and templates can't easily maintain internal data.
The complex, very irregular syntax of C and C++ makes it difficult to write very general macros.
Lisp and Lisp macros solve these problems.
Lisp macros are written in Lisp. You have the full power of Lisp to write the macro.
Lisp has a very regular syntax.
Talk to anyone that's mastered C++ and ask them how long they spent learning all the template fudgery they need to do template metaprogramming. Or all the crazy tricks in (excellent) books like Modern C++ Design, which are still tough to debug and (in practice) non-portable between real-world compilers even though the language has been standardised for a decade. All of that melts away if the langauge you use for metaprogramming is the same language you use for programming!
I'm not sure I can add some insight to everyone's (excellent) posts, but...
Lisp macros work great because of the Lisp syntax nature.
Lisp is an extremely regular language (think of everything is a list); macros enables you to treat data and code as the same (no string parsing or other hacks are needed to modify lisp expressions). You combine these two features and you have a very clean way to modify code.
Edit: What I was trying to say is that Lisp is homoiconic, which means that the data structure for a lisp program is written in lisp itself.
So, you end up with a way of creating your own code generator on top of the language using the language itself with all its power (eg. in Java you have to hack your way with bytecode weaving, although some frameworks like AspectJ allows you to do this using a different approach, it's fundamentally a hack).
In practice, with macros you end up building your own mini-language on top of lisp, without the need to learn additional languages or tooling, and with using the full power of the language itself.
Lisp macros represents a pattern that occurs in almost any sizeable programming project. Eventually in a large program you have a certain section of code where you realize it would be simpler and less error prone for you to write a program that outputs source code as text which you can then just paste in.
In Python objects have two methods __repr__ and __str__. __str__ is simply the human readable representation. __repr__ returns a representation that is valid Python code, which is to say, something that can be entered into the interpreter as valid Python. This way you can create little snippets of Python that generate valid code that can be pasted into your actually source.
In Lisp this whole process has been formalized by the macro system. Sure it enables you to create extensions to the syntax and do all sorts of fancy things, but it's actual usefulness is summed up by the above. Of course it helps that the Lisp macro system allows you to manipulate these "snippets" with the full power of the entire language.
In short, macros are transformations of code. They allow to introduce many new syntax constructs. E.g., consider LINQ in C#. In lisp, there are similar language extensions that are implemented by macros (e.g., built-in loop construct, iterate). Macros significantly decrease code duplication. Macros allow embedding «little languages» (e.g., where in c#/java one would use xml to configure, in lisp the same thing can be achieved with macros). Macros may hide difficulties of using libraries usage.
E.g., in lisp you can write
(iter (for (id name) in-clsql-query "select id, name from users" on-database *users-database*)
(format t "User with ID of ~A has name ~A.~%" id name))
and this hides all the database stuff (transactions, proper connection closing, fetching data, etc.) whereas in C# this requires creating SqlConnections, SqlCommands, adding SqlParameters to SqlCommands, looping on SqlDataReaders, properly closing them.
While the above all explains what macros are and even have cool examples, I think the key difference between a macro and a normal function is that LISP evaluates all the parameters first before calling the function. With a macro it's the reverse, LISP passes the parameters unevaluated to the macro. For example, if you pass (+ 1 2) to a function, the function will receive the value 3. If you pass this to a macro, it will receive a List( + 1 2). This can be used to do all kinds of incredibly useful stuff.
Adding a new control structure, e.g. loop or the deconstruction of a list
Measure the time it takes to execute a function passed in. With a function the parameter would be evaluated before control is passed to the function. With the macro, you can splice your code between the start and stop of your stopwatch. The below has the exact same code in a macro and a function and the output is very different. Note: This is a contrived example and the implementation was chosen so that it is identical to better highlight the difference.
(defmacro working-timer (b)
(let (
(start (get-universal-time))
(result (eval b))) ;; not splicing here to keep stuff simple
((- (get-universal-time) start))))
(defun my-broken-timer (b)
(let (
(start (get-universal-time))
(result (eval b))) ;; doesn't even need eval
((- (get-universal-time) start))))
(working-timer (sleep 10)) => 10
(broken-timer (sleep 10)) => 0
One-liner answer:
Minimal syntax => Macros over Expressions => Conciseness => Abstraction => Power
Lisp macros do nothing more than writing codes programmatically. That is, after expanding the macros, you got nothing more than Lisp code without macros. So, in principle, they achieve nothing new.
However, they differ from macros in other programming languages in that they write codes on the level of expressions, whereas others' macros write codes on the level of strings. This is unique to lisp thanks to their parenthesis; or put more precisely, their minimal syntax which is possible thanks to their parentheses.
As shown in many examples in this thread, and also Paul Graham's On Lisp, lisp macros can then be a tool to make your code much more concise. When conciseness reaches a point, it offers new levels of abstractions for codes to be much cleaner. Going back to the first point again, in principle they do not offer anything new, but that's like saying since paper and pencils (almost) form a Turing machine, we do not need an actual computer.
If one knows some math, think about why functors and natural transformations are useful ideas. In principle, they do not offer anything new. However by expanding what they are into lower-level math you'll see that a combination of a few simple ideas (in terms of category theory) could take 10 pages to be written down. Which one do you prefer?
I got this from the common lisp cookbook and I think it explained why lisp macros are useful.
"A macro is an ordinary piece of Lisp code that operates on another piece of putative Lisp code, translating it into (a version closer to) executable Lisp. That may sound a bit complicated, so let's give a simple example. Suppose you want a version of setq that sets two variables to the same value. So if you write
(setq2 x y (+ z 3))
when z=8 both x and y are set to 11. (I can't think of any use for this, but it's just an example.)
It should be obvious that we can't define setq2 as a function. If x=50 and y=-5, this function would receive the values 50, -5, and 11; it would have no knowledge of what variables were supposed to be set. What we really want to say is, When you (the Lisp system) see (setq2 v1 v2 e), treat it as equivalent to (progn (setq v1 e) (setq v2 e)). Actually, this isn't quite right, but it will do for now. A macro allows us to do precisely this, by specifying a program for transforming the input pattern (setq2 v1 v2 e)" into the output pattern (progn ...)."
If you thought this was nice you can keep on reading here:
http://cl-cookbook.sourceforge.net/macros.html
In python you have decorators, you basically have a function that takes another function as input. You can do what ever you want: call the function, do something else, wrap the function call in a resource acquire release, etc. but you don't get to peek inside that function. Say we wanted to make it more powerful, say your decorator received the code of the function as a list then you could not only execute the function as is but you can now execute parts of it, reorder lines of the function etc.