Only in Lisp

Discussion of Common Lisp
August
Posts: 17
Joined: Fri Oct 03, 2008 1:41 pm
Location: Los Alamos, New Mexico USA
Contact:

Re: Only in Lisp

Post by August » Tue May 18, 2010 1:37 pm

Gerenuk wrote: I'd highly appreciate real, short examples in this thread. I hardly know enough Lisp to make up my own, but I can guess what example code means. Can you write out an example, which cannot easily be replicated with Python?
I'm learning Lisp at the moment and use Python fairly regularly but am certainly not an expert. This question is for my own edification as much as anything. Before Python introduced the "with" statement in 2.5, could you have implemented "with" yourself with the same level of integration into the language?

Code: Select all

with open("hello.txt") as f:
    for line in f:
        ---arbitrary code in here----
        print line
In Lisp, this kind of thing is easy.
---------
DarklingX, LLC
http://www.darklingx.com

Suroy
Posts: 46
Joined: Sat Dec 19, 2009 11:20 am

Re: Only in Lisp

Post by Suroy » Tue May 18, 2010 9:01 pm

Heres an example of something in lisp you cant do in python.
Lets say you want to abstract this pattern away (ok, so this is more in common with java language, dont know python):
if (item.equals("HI")) {

} else if (item.equals("HHH")) {

} else if (item.equals("BB")) {

}

etc. Same function, 'equals'

In lisp, it would be
(cond
((equal item "HHH") ...)
((equal item "BB") ...)
)
etc.


New way to do it:
(condp equal item
("HHH" ...)
("BB" ...))

Boom! Bet u cant do that in python :lol:

Code: Select all

(defmacro condp (func item &rest args)
  (let ((gen-item (gensym)))
    `(let ((,gen-item ,item))
       (cond
	 ,@(loop
	      for arg in args
	      collecting `((,func ,gen-item ,(car arg))
			   ,@(cdr arg)))))))


Think of it this way. Lets say we stripped do,while,and for loops from your language and then i just told you you could rewrite it using gotos. But look, you say, i can just write do loops using this idiom of goto statement, for loops using this idiom, .... But if you had lisp without those loops and just gotos, you could just write it in a macro which expands into that 'repetitive idiom.' and thus create your own loops! After all, we should abstract away all common code. The key thing is that macros do not evaluate their arguments, like functions, so anything which shouldn't evaluate their arguments are not possible using functions (thus not possible in python).

Also to note is the syntax. How much harder would it be to create macros which produce code if we were using anything but parantheses? i think it would be much harder which explains why lisp is unique in this macro aspect.

Jasper
Posts: 209
Joined: Fri Oct 10, 2008 8:22 am
Location: Eindhoven, The Netherlands
Contact:

Re: Only in Lisp

Post by Jasper » Wed May 19, 2010 1:10 am

For some reason Python doesn't allow the conditionals to be returned either.. if ... : ... else ... must be toplevel because the indentation requirement at least.

Seems to me like a completely arbitrary restriction. Even C has ... ? ... : ...

Destruct1
Posts: 20
Joined: Wed Jan 20, 2010 1:40 am

Re: Only in Lisp

Post by Destruct1 » Fri May 21, 2010 12:00 pm

Jasper wrote:For some reason Python doesn't allow the conditionals to be returned either.. if ... : ... else ... must be toplevel because the indentation requirement at least.

Seems to me like a completely arbitrary restriction. Even C has ... ? ... : ...
Python has a new ternary operator (if this is what you mean):
true-clause if testclaus else false-clause

Destruct1
Posts: 20
Joined: Wed Jan 20, 2010 1:40 am

Re: Only in Lisp

Post by Destruct1 » Fri May 21, 2010 12:22 pm

I learned Lisp for 4 weeks and then switched to Python.
This is a fairly long comparison.

Syntax:

Lisp syntax is very regular. It is basically a repetition of
open_parens_( function_name/macro_name arg0_name arg1_name ... )_closing_parens
Each argument is either a direct variable or another subexpression which starts with a opening parens.

Python has a more complicated "construct-tree". First it devides in compound statements that execute a body,
like
if (cond):
body
and in simple statements like
a = 2
myfunc (2,4)
raise ValueError

The statements are not regular. While the function calls use a prefix style like lisp, mathematical operations and assignments use a infix style.

So which is actually better?
Lisp is regular and systematic, therefore requiring very little time to learn. Macros are only possible (/useful) if you have direct access to the syntax tree and are therefore hard to do in python.

Python is often more intuitive, because real life math is using infix notation. Python code makes program structure easily visible, while in Lisp you always have to parse the program in your head.
Consider this example:
for x in range (10):
print ("\n")
for y in range (10):
print (my_array[x][y])

(dotimes (x 10) (format t "\n") (dotimes (y 10) (format t (aref my_array x y))))

The Python code makes the structure of the program clear: The print array command is inside the double loop and a new line is printed in the outer loop. While experienced Lisp users may read their code easily I needed to count the parenthesis and mentally model the parse tree which I found daunting. YMMW

Destruct1
Posts: 20
Joined: Wed Jan 20, 2010 1:40 am

Re: Only in Lisp

Post by Destruct1 » Fri May 21, 2010 1:09 pm

Macros:

Macros are to this day still unique to lisp (there are languages which employ macros, but there are either simple textreplacing macros like in C
or in languages that are even more underground than Lisp).

In Paul Grahams book "On Lisp" he desribes 3 things macros do that are impossible with functions:
1) Conditional Evaluation
2) Lexical Context
3) Setf Accessor
I might add
4) Compiler macros

Compiler macros are a good way to shift runtme.-computations to compile-time computations and therefore increase speed.
Setf-accessors are important for Lisp but Python provides the variable = expression assignment and good control over objects with the magic __setattr__ methods.

That leaves the main point about macros: Conditional evaluation and lexical context. The main thing to remember about macros is that they can execute a (code) body. In Python you have to use the builtin compound statements like if, for and with. In Lisp you can create new control flow instruments that execute a given body n-times, depending on condition y and other magic stuff. Take the "conditional jump" example earlier this thread. It is easy for python to keep up when only short expression are involved.
But lets construct a more detailed example: You are given a list of points which represent geometrical figures. If the list include only 2 points, it is a line, if it includes 3 point it represents a triangle and four point represent a rectangle. You want to write a function that calculates the area of these figures. In Python you have to use the "native" control structures

Code: Select all

def area (*args): # &rest arg in Lisp
    if (len(args) == 2):
        return (0)
    if (len (args) == 3):
        return (0.5 * dist (args[0], args[1]) * calc_height (args[0], args[1], args[2]))
 ......
In lisp you can make a specific control structure that takes a list argument and 3 different code bodies and completly abstracts the python if... if.. clauses.

Code: Select all

(my_macro input 0 (* 0.5 (dist (first input) (second input)) (height_calc (first input) (second input) (third input))) rectangle_calc)
Another thing are the lexical enviroment macros, which bind certain variables while the code body is evaluated. I think this is easily replicated in Python by using a function that takes a object and returns a dictionary with certain properties of the object. It is useful if combined with the conditional evaluations macros and can create for example an anaphoric-if.

The big question is "Is it worth it?". My answer is no, I choose Python over Lisp. Macros arent compelling enough to make a difference for me, because they are difficult to write and I dont need additional control structures beyond a well designed core. You often hear the following arguments from lisp coders: "What if they take away your if and with statement tomorrow and you only have AND and OR left? What would you do then without macros?". That is a pointless argument. Because python has no possibilities to create basic structures from scratch it ships with the (well rounded) builtins.

Suroy
Posts: 46
Joined: Sat Dec 19, 2009 11:20 am

Re: Only in Lisp

Post by Suroy » Fri May 21, 2010 9:52 pm

I never use dotimes. I like to use iterate

for x in range (10):
print ("\n")
for y in range (10):
print (my_array[x][y])

equal in lisp

(iter (for x to 10) (print "\\n")
(iter (for y to 10) (print (aref my-array x y))))

. And i disagree with your usage of macros. The point of macros is to substitute patterns. Why would you rewrite that 'if' code as a macro? Is it common to test if the length of something is equal to 2 or if it is equal to 3?

nuntius
Posts: 538
Joined: Sat Aug 09, 2008 10:44 am
Location: Newton, MA

Re: Only in Lisp

Post by nuntius » Fri May 21, 2010 9:53 pm

At least have the decency to list the lisp code as it would be indented by any decent editor. :)

Code: Select all

(dotimes (x 10)
  (format t "\n")
  (dotimes (y 10)
    (format t (aref my_array x y))))
You showed the python code on four lines, with the lisp on 1. When lisp is on 4, I would argue it is as least as clear as the python. No paren counting is required -- editors do that easily, and its not particularly important in hand-written pseudocode.

I also believe a properly-formatted polynomials are clearer in lisp than in "algebraic" languages (*). Here's a crude example; it carries more weight when the coefficients are large expressions rather than single terms.

Code: Select all

(+ (* (expt x 3) a)
   (* (expt x 2) b)
   (* x c)
   d))
(*) These languages don't even allow for proper 2D math layout, with superscripts, subscripts, different division notations, etc. They require learning how to convert a graphical language into something less than ASCII art.

Warren Wilkinson
Posts: 117
Joined: Tue Aug 10, 2010 11:24 pm
Location: Calgary, Alberta
Contact:

Re: Only in Lisp

Post by Warren Wilkinson » Wed Aug 11, 2010 10:22 am

This thread is getting old, but I figured I'd chip in. You seem like a knowledgable fellow, so I'll get right to the good stuff.
  • Dynamic Variables: This is like a global variable, but bound with let. All subsequent functions see the most-recently-bound value. After the let the variable holds its old value. I use them to record the current HTTP request, current DB socket, etc.
  • Few Reserved Characters: I have function names with !, @, /, etc. My names are smaller because I don't have to write '-set', '-access', or '-varient'.
  • Macros.
    • With-open-file: it looks like python borrowed this from Lisp, which is good because this is so useful.
    • Continuatons: Paul Graham has some simple macros to simulate these in his book 'On Lisp', which is all about things you can ONLY do in Lisp.
    • Generalized setf: setf is a macro that looks at the expression its setting and compiles to the correct setter. Thats why (setf (gethash :n *ht*) new-value) works.
    • Compile time computation: Macros can run lisp code at compile time. I've used macros to embed CSS and images directly into my program. This way I avoid the OS+file roundtrip for commonly requested files.
  • unwind-protect: Specify a cleanup form that will be run when the block exits. It'll run if you leave, or error out. Used to ensure connections and files get closed, macros use it a lot.
  • Signal Handling: Lisp error handling is a low level stack unwinder/message passing system, with the high level error trapping built from macros. You can do cool things with it. And the debugger is top-notch.
  • Lisp tries to be functional. Most Lisp primitives are functional which makes the whole thing a lot easier to use.
Infix math feels natural because its been taught over 12 years of school. BEDMAS (Brackets, Exponents, Division, Multiplication, Addition, Subtraction) is not natural.
Need an online wiki database? My Lisp startup http://www.formlis.com combines a wiki with forms and reports.

udzinari
Posts: 1
Joined: Tue Nov 10, 2009 8:32 pm

Re: Only in Lisp

Post by udzinari » Fri Aug 27, 2010 2:46 pm

Although this thread is pretty old as mentioned, I want to post a pointer to an excellent blog post describing various features of Common Lisp quite well, http://abhishek.geek.nz/docs/features-of-common-lisp. It is a really good resource to refer beginners to, I wish more people would use it instead of coming up with weak arguments over and over again. It's left to the reader to determine whether this features are unique or not, but be advised that the beauty lies in combining them. You can not tell how good a language is just by hearing about it, only by learning and using it can you be a good judge, as Peter Norvig kind-of points out in his famous article.
Last edited by udzinari on Sun Oct 31, 2010 6:30 am, edited 1 time in total.

Post Reply