If you starting removing features from Lisp, at what point is it no longer Lisp? Some people claim Clojure shouldn't be considered a Lisp. Is it because too much Lisp was removed?
What is at the very heart of Lisp that makes it Lisp?
Name:
What makes Zen...Zen?2009-09-10 2:10
If you starting removing features from Zen, at what point is it no longer Zen? Some people claim peacefulness shouldn't be considered Zen. Is it because too much Zen was removed?
What is at the very heart of Zen that makes it Zen?
Name:
Anonymous2009-09-10 2:29
Lisp is the great ball of mud. By themselves, the features are important, but their true strength is when you can use any of them together.
Name:
Anonymous2009-09-10 4:40
The answer is obvious.
It is no longer lisp when you decide to stop calling it lisp and start calling it something else.
>>7 if the programmer takes full advantage of them
fixed
Name:
Anonymous2009-09-10 6:15
I hate speech impediments.
Name:
Anonymous2009-09-10 8:11
Lisp embodied nine new ideas:
1. Conditionals. A conditional is an if-then-else construct. We take these for granted now. They were invented by McCarthy in the course of developing Lisp. (Fortran at that time only had a conditional goto, closely based on the branch instruction in the underlying hardware.) McCarthy, who was on the Algol committee, got conditionals into Algol, whence they spread to most other languages.
2. A function type. In Lisp, functions are first class objects-- they're a data type just like integers, strings, etc, and have a literal representation, can be stored in variables, can be passed as arguments, and so on.
3. Recursion. Recursion existed as a mathematical concept before Lisp of course, but Lisp was the first programming language to support it. (It's arguably implicit in making functions first class objects.)
4. A new concept of variables. In Lisp, all variables are effectively pointers. Values are what have types, not variables, and assigning or binding variables means copying pointers, not what they point to.
5. Garbage-collection.
6. Programs composed of expressions. Lisp programs are trees of expressions, each of which returns a value. (In some Lisps expressions can return multiple values.) This is in contrast to Fortran and most succeeding languages, which distinguish between expressions and statements.
It was natural to have this distinction in Fortran because (not surprisingly in a language where the input format was punched cards) the language was line-oriented. You could not nest statements. And so while you needed expressions for math to work, there was no point in making anything else return a value, because there could not be anything waiting for it.
This limitation went away with the arrival of block-structured languages, but by then it was too late. The distinction between expressions and statements was entrenched. It spread from Fortran into Algol and thence to both their descendants.
When a language is made entirely of expressions, you can compose expressions however you want. You can say either (using Arc syntax)
(if foo (= x 1) (= x 2))
or
(= x (if foo 1 2))
7. A symbol type. Symbols differ from strings in that you can test equality by comparing a pointer.
8. A notation for code using trees of symbols.
9. The whole language always available. There is no real distinction between read-time, compile-time, and runtime. You can compile or run code while reading, read or run code while compiling, and read or compile code at runtime.
Running code at read-time lets users reprogram Lisp's syntax; running code at compile-time is the basis of macros; compiling at runtime is the basis of Lisp's use as an extension language in programs like Emacs; and reading at runtime enables programs to communicate using s-expressions, an idea recently reinvented as XML.
When Lisp was first invented, all these ideas were far removed from ordinary programming practice, which was dictated largely by the hardware available in the late 1950s.
Over time, the default language, embodied in a succession of popular languages, has gradually evolved toward Lisp. 1-5 are now widespread. 6 is starting to appear in the mainstream. Python has a form of 7, though there doesn't seem to be any syntax for it. 8, which (with 9) is what makes Lisp macros possible, is so far still unique to Lisp, perhaps because (a) it requires those parens, or something just as bad, and (b) if you add that final increment of power, you can no longer claim to have invented a new language, but only to have designed a new dialect of Lisp ; -)
Name:
Anonymous2009-09-10 8:17
Number six there make for some nice top-down design - but I never knew the tree notation was formalized...
Lisp is just another dynamic language. There's really nothing special about it.
Name:
Anonymous2009-09-10 9:44
>>11 A conditional is an if-then-else construct. We take these for granted now. They were invented by McCarthy in the course of developing Lisp. (Fortran at that time only had a conditional goto, closely based on the branch instruction in the underlying hardware.) McCarthy, who was on the Algol committee, got conditionals into Algol, whence they spread to most other languages.
Don't mix if/then/else up with true conditionals. A conditional returns a value, like Lisp's IF or C's ?:.
Name:
Anonymous2009-09-10 10:02
>>11
1-3 were always in C, but only the first is really useful. I don't see why anyone is gushing about 2 and 3. I've never really needed them that badly in C.
4 and 5 are unscientific and ultimately destructive.
6 can also be done in C. In fact, this is why functions have return values, and why we have the ternary operator. I don't see what this aversion to statements is all about, though....Lisp still needs to execute multiple consecutive statements in order to deal with side effects in a sane way, and even Haskell supports monads (which are lists of statements rather than functions). So, whatever.
7 is what enums are for. 8, I don't see the point. It would be nice if that one was actually explained. I think 8 is just an excuse to say that the parentheses are a good idea (which they seriously aren't).
9 is a huge performance hit, and the number one reason why Lisp was always considered a toy language compared to C. Writing dynamic code automatically makes it slower, and time is precious even in this age of egregiously fast desktops. Pretending this isn't true is an exercise in self delusion, which is why Paul Graham (the last "programmer" who actually uses Lisp) is currently in therapy and rehab for heroin/alcohol, and fighting his HIV infection.
Basically, this whole rant does nothing to support Lisp, and everything to support C. 0/10 kill yourself.
Name:
Anonymous2009-09-10 10:26
>>20
There are plenty of small problems that can be solved using dynamic languages and don't need ricer level optimizations. Dynamic languages make things easier to hack together some logic without being bogged down with trivial minutia.
Name:
Anonymous2009-09-10 10:44
>>11
By that definition even newLISP can be considered Lisp
Has the great Paul Graham been wrong this whole time?
>>20
Enjoy writing programs which are hundreds of times longer than they need to be, and a lot less robust. Current CL compilers are pretty damn good, so speed isn't really an issue, and if something is too slow, optimization isn't that hard, in the worst case scenario, you just use the FFI.
>>21
Remember that what's trivial minutia for you may not be trivial minutia for the user.
Name:
Anonymous2009-09-10 10:50
>>23
It's well known (for examples, see the Shootout Benchmarks) that C and Lisp programs solving the same problem are usually about the same length.
Name:
Anonymous2009-09-10 10:55
>>20 >>11 failed to define the variables that define Lisp, so you're battling against a straw man argument. (where the original argument is the presentation of the aforementioned variables).
The reason these are variables is because Lisp is a family of languages; depending on the values of each variable (if present at all), the name of the Lisp language is given. Even then, you're wrong about many things, for instance, #2. I'd like you to design a MAPCAR function, like the one common lisp provides, in C.
A Lisp has to be homoiconic for meta-programming. C doesn't do that at all.
In general, it's C retards that think their language is the most powerful language of all, it's newbies that, once they've done just a bit of reading on something better (ie lisp), start advocating without having any actual experience/knowledge to back up their statements (except citations to citations - meh), and actual experts who waste their time to write posts similar to mine, because they know if they don't do that, nobody will, and that is attractive enough for them to do it.
Name:
Anonymous2009-09-10 11:09
>>26 Shootout Benchmarks
No competent Lisp programmers waste time on the Shootout. The closest they come is complaining about it on c.l.l
Name:
Anonymous2009-09-10 11:13
>>27 #define MAPCAR_INSTANCE(type) type *mapcar(type (*)(type *),type *,size_t)
>>29 MAPCAR is more generic than that, but even assuming you're fine with such a definition, you're going to have to write a lot more specific boilerplate code than you were going to do in Lisp, just look at that size_t.
Let's not forget that the function that is passed to MAPCAR can be a closure, and I can pass them around as I wish. There's so many things that I can think of which are so damn easy to do in Lisp, and yet they're much more tedious to do correctly in C.
Name:
Anonymous2009-09-10 11:25
>>30
How is more generic? Unless I'm read it wrong, all it does is apply a function on each element of a list, put the results on a new list, and return the new list. What sort of specific code would I need to implement something like that?
>>32
First, lists in Lisp are usually linked lists, if you were to write it in C, you'd need to do something like:
struct cons
{
void* car;
void* cdr;
}
A lisp list is made by chaining conses, like:
(cons 'a (cons 'b (cons 'c nil)));=> '(a b c)
[code]
The last element is a NIL, or the empty list '().
NIL is not necessarily conflated with the value of 0.
tl;dr: you don't need the size argument.
The arguments to [code]MAPCAR are:
(mapcar function list &rest more-lists) MAPCAR can take a variable number of arguments(lists).
The function that you can pass to it can be any function object, such as a closure, which can be bound over some values, at the same time it could take dynamic value from the environment, and other fancy things which are just not so easy to implement elegantly in C. Yes, you can do any of them, but it would either look very hacky, or somewhat bloated.
The types of the elements in the list(s) can be anything.
The values returned by calling the function can be anything.
>>32
First, lists in Lisp are usually linked lists, if you were to write it in C, you'd need to do something like:
struct cons
{
void* car;
void* cdr;
}
A lisp list is made by chaining conses, like:
(cons 'a (cons 'b (cons 'c nil)));=> '(a b c)
The last element is a NIL, or the empty list '().
NIL is not necessarily conflated with the value of 0.
tl;dr: you don't need the size argument.
The arguments to MAPCAR are:
(mapcar function list &rest more-lists) MAPCAR can take a variable number of arguments(lists).
The function that you can pass to it can be any function object, such as a closure, which can be bound over some values, at the same time it could take dynamic value from the environment, and other fancy things which are just not so easy to implement elegantly in C. Yes, you can do any of them, but it would either look very hacky, or somewhat bloated.
The types of the elements in the list(s) can be anything.
The values returned by calling the function can be anything.
I could go on, but there's too much too explain. Why don't you try studying this for yourself before you write off Lisp as "easily done in C".
Name:
Anonymous2009-09-10 11:45
>>29
Wrong. Do you realize why? first of all, this works only with one type; secondly, you can't use the macro twice; thirdly, even if the macro seems to do some actual work, it doesn't, simply because you have to enter the type name anyway inside the body of the function (to access data).
Tl;dr it's nearly impossible to write a general mapcar in C.
>>32
It's more generic in this sense: (mapcar #'- '(1 2 3)) works to produce (-1 -2 -3); (mapcar (lambda (x) (cons (cdr x) (car x)) '((a . b))) works to produce ((b . a)). In C, you'd have to use two different specialized mapcars, one for integers, one for cons cells; it's impossible to use one function for both tasks.
>>35
He could implement a generic one by disregarding the type system, implementing some sort of LispObject's with type tags, and do a lot more greenspunning, or he could just use Lisp.
>>36
That's why I said "nearly impossible"; I had Greenspun in mind. Obviously, if a lisp implementation is written in C (and there's such implementations), every lisp feature can be written in C. But things are completely different, and I can't waste much time explaining these things. Those who get it, already get it, those who don't, maybe they will at some point in their life, but I'm not the one to waste time for them.
>>34
By the way, that is incorrect:
(cons 'a (cons 'b (cons 'c nil)))
Evaluates to (a b c), not '(a b c) which is a literal list. CONS provides freshly created cons cells.
>>38
Oh right, my mistake, I guess it's the same as writing:
(list 'a 'b 'c)
Name:
Anonymous2009-09-10 11:57
>>35 this works only with one type
No, it doesn't. you can't use the macro twice
Yes, I can. simply because you have to enter the type name anyway inside the body of the function (to access data).
No, I don't.
Go back to learning C before trying to discuss it.
Hint: MAPCAR_INSTANCE(char);
MAPCAR_INSTANCE(int);
MAPCAR_INSTANCE(void *);
>>40
Never mind. I always forget C doesn't have function overloading.
Name:
Anonymous2009-09-10 12:03
>>40 this works only with one type No, it doesn't.
Yes, it does. That's a consequence of being able to use the macro only once: you can't use the macro twice Yes, I can.
No, you can't. If you use it twice, you have two conflicting prototypes in scope. For instance:
/* MAPCAR_INSTANCE(int);
expands to:
*/
int *mapcar(int (*)(int *), int *, size_t);
As you see, these are two conflicting prototypes. You can solve this problem by adding some C pp tokenizer magic (# or ##), but even then, you'll create mapcar_int, mapcar_char, but you'll be unable to create a mapcar for arrays or pointers (mapcar_char* isn't a valid identifier in C).
simply because you have to enter the type name anyway inside the body of the function (to access data). No, I don't.
Elaborate on that; you haven't demonstrated how you actually implement mapcar without that.
Go back to learning C before trying to discuss it.
There's nothing for me left to learn; I've studied ISO 9899:1999 and I've memorized a fairly big part of it.
Name:
Anonymous2009-09-10 15:08
There's nothing for me left to learn; I've studied ISO 9899:1999 and I've memorized a fairly big part of it.
That is most excellent. When will you be writing your ANSI C compiler?
Name:
Anonymous2011-01-31 21:08
<-- check em dubz
Name:
tray2012-03-14 15:25
you better be
Name:
Anonymous2013-01-19 23:17
/prog/ will be spammed continuously until further notice. we apologize for any inconvenience this may cause.