I'm new to Lisp. Would anyone be kind to show me a few short examples that demonstrate the power of Lisp? I'm especially interested about the symbol manipulation features. Are there 'magic' constructs native to Lisp, constructs that would need a lot more coding in languages like C++?
Thanks for any help,
Károly Ladvánszky
___________________________________________________________________________ ___ Posted Via Binaries.net = SPEED+RETENTION+COMPLETION = http://www.binaries.net
"Károly Ladvánszky" <ladvanszkykar...@digicart.hu> writes: > I'm new to Lisp. Would anyone be kind to show me a few short examples that > demonstrate the power of Lisp? I'm especially interested about the symbol > manipulation features. Are there 'magic' constructs native to Lisp, > constructs that would need a lot more coding in languages like C++?
Well, that symbols exist at all and have a notation that you can both type in and see back is important. You can work interactively, which you can't really with C++.
In a vague sense, symbols will feel like an enum type except there are an infinite number of them and you don't have to declare them. You just type their name and they're there.
(setq person1 'fred) => FRED
All expressions will return a value. An assignment returns the value assigned.
person1 => FRED
This assigns the variable person1 a value which is the symbol FRED. That would take more work in C++ already, requiring declarations, etc. In Lisp, the type is in the object, not in the variable. And many datatypes have a type-in/print-out notation such that you can just name them and they will exist. If you want a list of things, you can do that, too.
(defun role-in (company person) (let ((all-jobs (get company 'jobs))) ; get list of company jobs (let ((entry (assoc person all-jobs))) ; get person's entry in jobs (if entry ; when entry exists (second entry) ; return the second element 'customer)))) ; otherwise, return CUSTOMER => ROLE-IN
(role-in 'acme 'mark) => VICE-PRESIDENT
(role-in 'acme person1) ; PERSON1 is a variable we assigned earlier => SECRETARY
(role-in 'acme 'arthur) => CUSTOMER
You can also write things to find out other things from the same data. Consider:
(defun jobs-in (company) (mapcar #'second ; make a list of the first elements from (get company 'jobs))) ; the jobs list for the company => ROLES-IN
(defun employees-of (company) (mapcar #'first ; make a list of the first elements from (get company 'jobs))) ; the jobs list for the company => EMPLOYEES-OF
"Károly Ladvánszky" <ladvanszkykar...@digicart.hu> writes: > I'm new to Lisp. Would anyone be kind to show me a few short examples that > demonstrate the power of Lisp? I'm especially interested about the symbol > manipulation features. Are there 'magic' constructs native to Lisp, > constructs that would need a lot more coding in languages like C++?
Multi Methods. Need I say more? :)
Cheers
-- Marco Antoniotti ======================================================== NYU Courant Bioinformatics Group tel. +1 - 212 - 998 3488 719 Broadway 12th Floor fax +1 - 212 - 995 4122 New York, NY 10003, USA http://bioinformatics.cat.nyu.edu "Hello New York! We'll do what we can!" Bill Murray in `Ghostbusters'.
In article <3bc5544...@corp-goliath.newsgroups.com>, Károly Ladvánszky wrote: >I'm new to Lisp. Would anyone be kind to show me a few short examples that >demonstrate the power of Lisp? I'm especially interested about the symbol >manipulation features. Are there 'magic' constructs native to Lisp, >constructs that would need a lot more coding in languages like C++?
Yes there are such ``magic'' constructs:
- access to the reader (parser) and evaluator from within the program. - treatment of code as data and vice versa - tree-transforming macros for implementing new sublanguages and other uses - programmer control over evaluation - Lisp program can customize the behavior of Lisp's lexical analyzer (read tables which classify input characters, and reader macros, can be altered programmatically). - dynamic typing (values have type, not objects or expressions)---you can't effectively emulate a dynamic language like Lisp within a static language like C++ without writing an interpreter. - built in support for rational numbers and bignum integers - dynamically scoped variables - lexical closures---objects can can be called like functions, which capture (close over) the variables and bindings of the lexical environment in which they were created. - automatic garbage collection---necessary to support all kinds of powerful programming techniques whose usefulness would be drowned by the complexity of explicit storage management. (There are garbage collectors for C++ implementations, but they don't do a complete enough job to be trustworthy, because they have to make conservative guesses about the meaning of raw, untyped memory). - dynamic loading, redefinition of functions (done only in clumsy, fragile, operating-systems-specific ways in C++, like shared libraries on UNIX).
In the object system:
- multiple dispatch - auxiliary methods (before/around/after) - basic types (strings, integers, etc) *are* classes and participate in dynamic polymorphism. In C++ you can't even do *static* polymorphism on non-class types. - changing class of object at run time - overridable data members (called slots in CLOS terminology) (Only functions in C++ classes can be overriden via the virtual function mechanism). - static members (``:allocation class'' slots) inherited properly (In C++, static class members are not inherited). - Class slot in derived class can override instance slot in base and vice versa. - meta object protocol (called MOP, supported by some CLOS implementations) to subtly or radically customize the behavior of the class system.
So really, just about *everything* in Lisp is out of reach of the C++ programmer. Every nontrivial Lisp program you will come across is likely to rely on some of the above elements, which could make the same computation difficult to express in C++.
I am not sure what kind of code you had in mind, but here are some non-trivial files. Shows the power of Lisp to incorporate other languages (like HTML).
> I'm new to Lisp. Would anyone be kind to show me a few short examples that > demonstrate the power of Lisp? I'm especially interested about the symbol > manipulation features. Are there 'magic' constructs native to Lisp, > constructs that would need a lot more coding in languages like C++?
* Károly Ladvánszky | I'm new to Lisp. Would anyone be kind to show me a few short examples | that demonstrate the power of Lisp?
You seem to be a Microsoft user. I am not. Could you show me a few short examples that demonstrate the power of the Windows environment?
| I'm especially interested about the symbol manipulation features. Are | there 'magic' constructs native to Lisp, constructs that would need a lot | more coding in languages like C++?
There are two kinds of constructs in a Common Lisp vs C++ comparison:
1 Those for which C++ uses one- or two-character prefix, infix, and postfix notation, where C++ excels in compactness and expressibility, which leads many people to think that C++ is somehow compact and easy to write and express yourself in, even while the bulk of your code is not using these small and elegant syntactic sugarcubes.
2 Those for which Common Lisp use the same syntax as everything else, where Common Lisp excels in overall compactness and expressibility because of a _much_ higher level of abstraction and much lower number of minor details that needs expressing, meaning that the value of a super-compact syntax for the simplest operators is correspondingly lower.
It should be fairly obvious that comparisons have to be performed at two different levels at once and thus will produce no useful results if you do not already understand what you just compared on their own merits.
/// -- My hero, George W. Bush, has taught me how to deal with people. "Make no mistake", he has said about 2500 times in the past three weeks, and those who make mistakes now feel his infinite wrath, or was that enduring care?
Marco Antoniotti <marc...@cs.nyu.edu> writes: > "Károly Ladvánszky" <ladvanszkykar...@digicart.hu> writes:
> > I'm new to Lisp. Would anyone be kind to show me a few short examples that > > demonstrate the power of Lisp? I'm especially interested about the symbol > > manipulation features. Are there 'magic' constructs native to Lisp, > > constructs that would need a lot more coding in languages like C++?
> Multi Methods. Need I say more? :)
Well, yes, probably.
This isn't exactly the kind of response that is likely to convert someone who is new to Lisp to using it, as it conveys no useful information whatsoever. At the very least you need to say what a multimethod is, give a toy example and say why you can't achieve it with C++ templates.
Thank you for your answer. Yes, I'm a Microsoft user ... with permanent interest about other technologies. I like Microsoft's component architecture. There are a lot of powerful components for reasonable prices. To mention one, we use a image processing component that can read, display, manipulate images of about 60 formats. To produce a component like this requires hundreds of man-hours. I beleive this is a power point. Component technology is of course beyond language issues. Returning to Lisp, my intent is to learn about it and see if there are strong problem solving capabilites - mechanisms like those found in Prolog, CLIPS etc.- built in the language or in the form of libraries.
> * Károly Ladvánszky > | I'm new to Lisp. Would anyone be kind to show me a few short examples > | that demonstrate the power of Lisp?
> You seem to be a Microsoft user. I am not. Could you show me a few > short examples that demonstrate the power of the Windows environment?
> | I'm especially interested about the symbol manipulation features. Are > | there 'magic' constructs native to Lisp, constructs that would need a lot > | more coding in languages like C++?
> There are two kinds of constructs in a Common Lisp vs C++ comparison:
> 1 Those for which C++ uses one- or two-character prefix, infix, and postfix > notation, where C++ excels in compactness and expressibility, which leads > many people to think that C++ is somehow compact and easy to write and > express yourself in, even while the bulk of your code is not using these > small and elegant syntactic sugarcubes.
> 2 Those for which Common Lisp use the same syntax as everything else, where > Common Lisp excels in overall compactness and expressibility because of a > _much_ higher level of abstraction and much lower number of minor details > that needs expressing, meaning that the value of a super-compact syntax > for the simplest operators is correspondingly lower.
> It should be fairly obvious that comparisons have to be performed at two > different levels at once and thus will produce no useful results if you > do not already understand what you just compared on their own merits.
> /// > -- > My hero, George W. Bush, has taught me how to deal with people. "Make no > mistake", he has said about 2500 times in the past three weeks, and those > who make mistakes now feel his infinite wrath, or was that enduring
care?
___________________________________________________________________________ ___ Posted Via Binaries.net = SPEED+RETENTION+COMPLETION = http://www.binaries.net
> > > I'm new to Lisp. Would anyone be kind to show me a few short examples that > > > demonstrate the power of Lisp? I'm especially interested about the symbol > > > manipulation features. Are there 'magic' constructs native to Lisp, > > > constructs that would need a lot more coding in languages like C++?
> > Multi Methods. Need I say more? :)
> Well, yes, probably.
> This isn't exactly the kind of response that is likely to convert > someone who is new to Lisp to using it, as it conveys no useful > information whatsoever. At the very least you need to say what a > multimethod is, give a toy example and say why you can't achieve it > with C++ templates.
Well, you are right. I was in my "troll-prevention" mode. :) An unwarranted assumption in this case.
I'd say other people have answered the questions raised.
Cheers
-- Marco Antoniotti ======================================================== NYU Courant Bioinformatics Group tel. +1 - 212 - 998 3488 719 Broadway 12th Floor fax +1 - 212 - 995 4122 New York, NY 10003, USA http://bioinformatics.cat.nyu.edu "Hello New York! We'll do what we can!" Bill Murray in `Ghostbusters'.
"Károly Ladvánszky" <ladvanszkykar...@digicart.hu> writes: > Thank you for your answer. Yes, I'm a Microsoft user ... with permanent > interest about other technologies. I like Microsoft's component > architecture. > There are a lot of powerful components for reasonable prices. To mention > one, we use a image processing component that can read, display, manipulate > images of about 60 formats. To produce a component like this requires > hundreds of man-hours. I beleive this is a power point. Component technology > is of course beyond language issues.
Yes and no. Microsoft COM architecture leans toward having the C++ environment have the leading role. This goes against the basic Lisper instinct :)
Anyway, the commercial CL implementations running on Windows offer integration with COM. Franz Inc. ACL is the one I have used and I have to say (to Franz Inc.'s merit) it is easy to use. I have not used LW or Corman Lisp in this capacity, so I cannot comment on them.
> Returning to Lisp, my intent is to learn about it and see if there are > strong problem solving capabilites - mechanisms like those found in Prolog, > CLIPS etc.- built in the language or in the form of libraries.
The basic language (Common Lisp) has several advantages over C++. Others have commented on this. As per your requests, the systems you look for are available in the form of libraries. A good source of pointers is the Association of Lisp User (ALU) at <http://www.alu.org>. Another is CLiki <http://ww.telent.net/cliki>.
Cheers
-- Marco Antoniotti ======================================================== NYU Courant Bioinformatics Group tel. +1 - 212 - 998 3488 719 Broadway 12th Floor fax +1 - 212 - 995 4122 New York, NY 10003, USA http://bioinformatics.cat.nyu.edu "Hello New York! We'll do what we can!" Bill Murray in `Ghostbusters'.
> > I'm new to Lisp. Would anyone be kind to show me a few short examples that > > demonstrate the power of Lisp? I'm especially interested about the symbol > > manipulation features. Are there 'magic' constructs native to Lisp, > > constructs that would need a lot more coding in languages like C++?
> Well, that symbols exist at all and have a notation that you can both > type in and see back is important. You can work interactively, which > you can't really with C++.
> In a vague sense, symbols will feel like an enum type except there are an > infinite number of them and you don't have to declare them. You just type > their name and they're there.
> (setq person1 'fred) > => FRED
> All expressions will return a value. An assignment returns the value > assigned.
> person1 > => FRED
> This assigns the variable person1 a value which is the symbol FRED. > That would take more work in C++ already, requiring declarations, etc. > In Lisp, the type is in the object, not in the variable. And many datatypes > have a type-in/print-out notation such that you can just name them and they > will exist. If you want a list of things, you can do that, too.
> (defun role-in (company person) > (let ((all-jobs (get company 'jobs))) ; get list of company jobs > (let ((entry (assoc person all-jobs))) ; get person's entry in jobs > (if entry ; when entry exists > (second entry) ; return the second element > 'customer)))) ; otherwise, return CUSTOMER > => ROLE-IN
> (role-in 'acme 'mark) > => VICE-PRESIDENT
> (role-in 'acme person1) ; PERSON1 is a variable we assigned earlier > => SECRETARY
> (role-in 'acme 'arthur) > => CUSTOMER
> You can also write things to find out other things from the same data. > Consider:
> (defun jobs-in (company) > (mapcar #'second ; make a list of the first elements from > (get company 'jobs))) ; the jobs list for the company > => ROLES-IN
> (defun employees-of (company) > (mapcar #'first ; make a list of the first elements from > (get company 'jobs))) ; the jobs list for the company > => EMPLOYEES-OF
> (employees-of 'acme) > => (SALLY MARK FRED)
> Does this help you?
___________________________________________________________________________ ___ Posted Via Binaries.net = SPEED+RETENTION+COMPLETION = http://www.binaries.net
On Fri, 12 Oct 2001 14:04:48 +0200, "Károly Ladvánszky"
<ladvanszkykar...@digicart.hu> wrote: > Returning to Lisp, my intent is to learn about it and see if there are > strong problem solving capabilites - mechanisms like those found in Prolog, > CLIPS etc.- built in the language or in the form of libraries.
If you are familiar with CLIPS, have a look at LISA:
Erik Naggum wrote: > 2 Those for which Common Lisp use the same syntax as everything else, where > Common Lisp excels in overall compactness and expressibility because of a > _much_ higher level of abstraction and much lower number of minor details > that needs expressing, meaning that the value of a super-compact syntax > for the simplest operators is correspondingly lower.
Could you please give me some examples showing in what respect Lisp has a _much_ higher level of abstraction.
In article <3bc6d88...@corp-goliath.newsgroups.com>, Károly Ladvánszky wrote: >Thank you for your answer. Yes, I'm a Microsoft user ... with permanent >interest about other technologies. I like Microsoft's component >architecture. >There are a lot of powerful components for reasonable prices. To mention >one, we use a image processing component that can read, display, manipulate >images of about 60 formats. To produce a component like this requires >hundreds of man-hours. I beleive this is a power point. Component technology >is of course beyond language issues.
Actually, not it isn't. Microsoft's component technology is based on virtual function calls of its C++ compiler (in-process COM). Distributed COM (DCOM) is based on a remote procedure calling protocol derived from DCE RPC (DCOM), which is a way of remoting C function calls.
Anything that wants to call a COM DLL, or behave like one, has to emulate C++ virtual function calls, to do which it has to understand vtable layout, and the Visual C++ calling conventions for passing parameters and returning values. That is not only language-dependent, but downright compiler-dependent.
DCOM is also language bound, because the kinds of data types passed through its remote calling interface are based on the C language. DCE was written in C and designed primarily for C programming. The protocol itself uses inflexible binary representations on the wire.
Microsoft took the RPC library from DCE, turned it into Microsoft RPC (embrace and extend, like everything else) then added some hacks whereby DCE services become interfaces, represented by C++ objects. The 128 bit GUID of a DCE service is renamed an interface ID and so forth.
If you wanted to use DCOM for, say, communicating between two Lisp components, you'd have to design a way to represent Lisp's types from the ground up. Atoms, cons cells, Lists, bignums, vectors, dynamic type information, you name it. You'd most likely just pass raw character data and parse it on the other side with Lisp's built in reader, using the DCOM connection as a dumb pipe.
``Going beyond language issues'' does not mean that you can call something from Visual C++ and Visual BASIC. :)
In article <3bc6d88...@corp-goliath.newsgroups.com>, Károly Ladvánszky wrote: >Thank you for your answer. Yes, I'm a Microsoft user ... with permanent >interest about other technologies. I like Microsoft's component >architecture. >There are a lot of powerful components for reasonable prices. To mention >one, we use a image processing component that can read, display, manipulate >images of about 60 formats. To produce a component like this requires >hundreds of man-hours. I beleive this is a power point. Component technology >is of course beyond language issues.
Actually, not it isn't. Microsoft's component technology is based on virtual function calls of its C++ compiler (in-process COM). Distributed COM (DCOM) is based on a remote procedure calling protocol derived from DCE RPC (DCOM), which is a way of remoting C function calls.
Anything that wants to call a COM DLL, or behave like one, has to emulate C++ virtual function calls, to do which it has to understand vtable layout, and the Visual C++ calling conventions for passing parameters and returning values. That is not only language-dependent, but downright compiler-dependent.
DCOM is also language bound, because the kinds of data types passed through its remote calling interface are based on the C language. DCE was written in C and designed primarily for C programming. The protocol itself uses inflexible binary representations on the wire.
Microsoft took the RPC library from DCE, turned it into Microsoft RPC (embrace and extend, like everything else) then added some hacks whereby DCE services become interfaces, represented by C++ objects. The 128 bit GUID of a DCE service is renamed an interface ID and so forth.
If you wanted to use DCOM for, say, communicating between two Lisp components, you'd have to design a way to represent Lisp's types from the ground up. Atoms, cons cells, Lists, bignums, vectors, dynamic type information, you name it. You'd most likely just pass raw character data and parse it on the other side with Lisp's built in reader, using the DCOM connection as a dumb pipe.
When you can call something from Visual BASIC and Visual C++, you have necessarily not gone ``beyond language issues''. :)
k...@ashi.footprints.net (Kaz Kylheku) writes: > In article <3bc6d88...@corp-goliath.newsgroups.com>, Károly Ladvánszky wrote: > >Thank you for your answer. Yes, I'm a Microsoft user ... with permanent > >interest about other technologies. I like Microsoft's component > >architecture. > >There are a lot of powerful components for reasonable prices. To mention > >one, we use a image processing component that can read, display, manipulate > >images of about 60 formats. To produce a component like this requires > >hundreds of man-hours. I beleive this is a power point. Component technology > >is of course beyond language issues.
> Actually, not it isn't. Microsoft's component technology is based on > virtual function calls of its C++ compiler (in-process COM). > Distributed COM (DCOM) is based on a remote procedure calling protocol > derived from DCE RPC (DCOM), which is a way of remoting C function > calls.
> Anything that wants to call a COM DLL, or behave like one, has to > emulate C++ virtual function calls, to do which it has to understand > vtable layout, and the Visual C++ calling conventions for passing > parameters and returning values. That is not only language-dependent, > but downright compiler-dependent.
To be fair, even though the COM layout was taken directly from the Visual C++ vtable layout, it is no longer dependent upon the language or the compiler. The spec calls for a COM object to be implemented as a pointer to some storage, the first word of which is a pointer to a dispatch table. The first three functions in the dispatch table are required to be query interface, add reference, and release reference. These three functions will be called using the `STDCALL' convention (callee pops the frame) and the first argument passed will be the pointer to the object.
While it is the case that this is how VC++ lays out its objects and performs virtual function dispatch, the spec is a binary layout and any you don't need to know anything about the internals of the VC++ compiler to create a COM object that anyone can use.
* Rolf Wester | Could you please give me some examples showing in what respect Lisp has a | _much_ higher level of abstraction.
Special variables leaps to mind as the obvious first choice, more obvious than closures, the Lisp object reader and writer, the type hierarchy and dynamic types, the entire condition system, macros, compiler-macros, etc, which I just mention in no particular order. Of course, if your point is to gripe about the choice of "much", you will never be satisifed with any answer I could give you, anyway, so either you accept this or you do not. And if you had had a real argument, it would have been expressed properly, so I am inclined to believe you are just trolling and will not respond to any further trolling-like responses you choose to post, but please feel free to argue your case if you have one.
/// -- My hero, George W. Bush, has taught me how to deal with people. "Make no mistake", he has said about 2500 times in the past three weeks, and those who make mistakes now feel his infinite wrath, or was that enduring care?
Erik Naggum wrote: > * Rolf Wester > | Could you please give me some examples showing in what respect Lisp has a > | _much_ higher level of abstraction.
> Special variables leaps to mind as the obvious first choice, more obvious > than closures, the Lisp object reader and writer, the type hierarchy and > dynamic types, the entire condition system, macros, compiler-macros, etc, > which I just mention in no particular order. Of course, if your point is > to gripe about the choice of "much", you will never be satisifed with any > answer I could give you, anyway, so either you accept this or you do not. > And if you had had a real argument, it would have been expressed properly, > so I am inclined to believe you are just trolling and will not respond to > any further trolling-like responses you choose to post, but please feel > free to argue your case if you have one.
My question was meant seriously, my point was not to gripe about anything. I'm not very familiar with CL but I'm fascinated by it's capabilities as far as I recognized them. As I mostly programmed in Fortran/C++/Java it's not so obvious for me to see in what respect Lisps level of abstraction is much higher compared to other languages. I read this frequently and I have some notion about it's meaning but I don't think that I fully grasped all of it. I'm very interested in Lisp but I have not enough free time to deal with it and try out all of Lisp as much as I liked to. That's why I asked.
Rolf Wester
P.S.: My mother language is not English so misunderstandings may arise because I can't express myself in English as precisely as I could do in German.
* Rolf Wester | My question was meant seriously, my point was not to gripe about anything.
Then you deserve a better answer.
| I'm not very familiar with CL but I'm fascinated by it's capabilities as | far as I recognized them. As I mostly programmed in Fortran/C++/Java | it's not so obvious for me to see in what respect Lisps level of | abstraction is much higher compared to other languages.
This is actually a serious problem for Common Lisp, and you are far from alone in experiencing its effects. For instance, take special variables. People who do now know how they work, tend to dismiss them as some old Lisp concept that should not have survived. Then they write code that uses some global variables and they _set_ their values, they get yelled at for using global variables whose values are hard to track, and they think that global state is a bad thing. However, the bad thing about global variables is that they do _not_ have the infrstructure offered by special binding in Common Lisp. A function may legitimately desire to change the global state for a carefully controlled duration, but in order to do so, you have to guarantee that the old state is restored. This is truly hard if the language does not support it. Exceptions and other non-local control transfers intervene. Storing the variable in some local variable is not always trivial -- you need to replicate an object with the same type as the global variable, and the language does not give you that obvious operation, either -- and then you need to ensure that the stored value is put back into the global variable before you return, which can be foiled by the kind of unconscious programmers that are likely to mess with our code. So C++ people tend to think that special variables are useless, but in fact, they solve a very serious problem that C++ programmers do not generally try to solve because it is too hard and generally too painful in their language. Sticking to the convenient, they use semi-global state variables and are nervous. The abstraction offered by special variables is thus hard to grasp for the programmer who does not even perform the concrete operations the abstraction automates and hides. Even Common Lisp programmers are generally unaware of the concrete mechanisms underlying the abstraction. The impact on threads, for instance, is not quite obvious: One variable may be so global that it should affect all threads, while another may have a thread-local global value. This means that implementationally, a thread context switch needs to re-bind special variables if they share a Lisp image, and involve IPC and shared memory between threads if the variable is thread-global. This is so hairy stuff that even good programmers would shy away from thinking about using such things if they had to do it manually. To a Common Lisp programmer, it is a natural extension to special variables, even though conceptually much more advanced. Other forms of context switches may also be desirable, so it makes sense to expose the control mechanism for rebinding special variables, but this could now be done separately from the bindings because the infrastructure for bindings is already there. Thus the abstraction offered by special binding in Common Lisp spans an enormous amount of otherwise manual work, and they are not only "global variables", which is how some think of them, it is also a mechanism that can be used for variables that are _not_ global, but require the support of binding and unbinding of variables that can be shared only among a few functions that know about them. Therefore, there is a local declaration to request special binding of an otherwise lexical variable in addition to the global declaration to request it of all bindings of a symbols, and the global declaration applies to the symbol regardless of its context, because specialness of a symbol must be pervasive to work at all. This means that the mechanism behind the special binding is very different from the global variable in many other languages, which may be shadowed by a lexical binding (except they do not call it that).
| P.S.: My mother language is not English so misunderstandings may arise | because I can't express myself in English as precisely as I could do in | German.
It is probably OK to include the German if you are uncertain about an expression -- even if people here write in English, the language skills of the community is pretty amazing, and you could get tips and hints that would not get anywhere else. For instance, "Muttersprache" and "mother tongue" and "langue maternelle" have the common Latin etymology "lingua materna", but still it does not really work all that well to translate directly between them in any direction...
/// -- The United Nations before and after the leadership of Kofi Annan are two very different organizations. The "before" United Nations did not deserve much credit and certainly not a Nobel peace prize. The "after" United Nations equally certainly does. I applaud the Nobel committee's choice.
On Sat, 13 Oct 2001 16:43:39 GMT, Erik Naggum <e...@naggum.net> wrote: >* Rolf Wester >| My question was meant seriously, my point was not to gripe about anything.
> Then you deserve a better answer.
>| I'm not very familiar with CL but I'm fascinated by it's capabilities as >| far as I recognized them. As I mostly programmed in Fortran/C++/Java >| it's not so obvious for me to see in what respect Lisps level of >| abstraction is much higher compared to other languages.
> This is actually a serious problem for Common Lisp, and you are far from > alone in experiencing its effects. For instance, take special variables. > People who do now know how they work, tend to dismiss them as some old >... (stuff deleted)
Excellent discussion of global variables, Erik. I completely agree with this--I think special variables are one of the coolest features of Common Lisp. Lisp programmers often take them for granted, but I certainly don't; I have never used any other language which handled state shared between functions so simply and efficiently.
> concrete mechanisms underlying the abstraction. The impact on threads, > for instance, is not quite obvious: One variable may be so global that it > should affect all threads, while another may have a thread-local global > value. This means that implementationally, a thread context switch needs > to re-bind special variables if they share a Lisp image, and involve IPC > and shared memory between threads if the variable is thread-global. This
I just want to make a comment here. Common Lisp does not specify how special variables interact with threads, so this is an area that is debatable. In my opinion an optimal implementation of per-thread special variable bindings does not require any re-binding. They should be bound in a particular thread, and only in a particular thread. And if all those threads are active at once, no problem. No context switching need occur. It also makes sense to have a global binding that is shared between threads, but if a thread re-binds it, that binding is specific to that thread. I can't see a reason for a thread to re-bind it, and then have all other threads see the binding. I think you would have multiple threads trying to undo each others bindings, possibly. eg. (assuming foo is thread-global) thread-1 binds 'foo thread-2 binds 'foo thread-1 exits, unbinding 'foo ???? now what Which binding remains: the one from thread-1 or from thread-2?
Erik Naggum wrote: > * Rolf Wester > | My question was meant seriously, my point was not to gripe about anything.
> Then you deserve a better answer.
Thanks a lot for your detailed answer. It's very interesting. In C++ I avoid to use global variables except when they are constants and will not be changed although there are situations where global variables could be advantegeous. Lisp special variables are abviously different.
k...@ashi.footprints.net (Kaz Kylheku) wrote in message <news:QBlx7.65021$ob.1594780@news1.rdc1.bc.home.com>... > In article <3bc5544...@corp-goliath.newsgroups.com>, Károly Ladvánszky wrote: > >I'm new to Lisp. Would anyone be kind to show me a few short examples that > >demonstrate the power of Lisp? I'm especially interested about the symbol > >manipulation features. Are there 'magic' constructs native to Lisp, > >constructs that would need a lot more coding in languages like C++?
> Yes there are such ``magic'' constructs:
[snip]
I'd put a somewhat different emphasis on them.
lexical closures and functional programming: Functions are first class objects. You can make code or functions which generate function values. There are lots of library functions which accept function values as arguments and do powerful things with them. (DEFUN CUTOFF-FUN (X) "Return a function which tests whether its argument exceeds X." (LAMBDA (Y) (> Y X))) (DEFVAR *CUTOFF-FUN-1* (CUTOFF-FUN 1)) (DEFVAR *CUTOFF-FUN-4* (CUTOFF-FUN 4)) (SOME *CUTOFF-FUN-1* '(1 2 3)) => T (SOME *CUTOFF-FUN-4* '(1 2 3)) => NIL (SOME (LAMBDA (Y) (> Y 2)) '(1 2 3)) => T (FIND-IF #'EVENP '(1 2 3)) => 2 This is shared with other functional programming languages (notably the ML family and Haskell) and some scripting languages, but lots of languages have either weak or no support for it.
garbage collection: This is a nice thing in general, and in particular, functional programming tends to get unreasonably messy if you don't have it.
extremely general, powerful macros: A macro in Lisp is a Lisp program which generates code. Because of this, and the way that the syntax of Lisp makes it trivial to manipulate Lisp source code as Lisp data, there are few unnecessary obstacles to adding complex new behavior to Lisp. (There's only the *necessary* obstacle that this is fairly tricky to think about.) It's hard to give a convincing tiny example of this, especially since typical macro syntax isn't self-explanatory. So I'll refer you to a small example and a medium-sized example instead: writing an object-oriented programming system from scratch (as a demonstration only, since the existing CLOS system is fine) in Paul Graham's book _ANSI Common Lisp_, or adding nondeterminism (choose and fail) to the language, in the free library Screamer. Both of these are nontrivial changes to the language, and adding them to almost any other language would be a major project. In Lisp this kind of thing is relatively routine.
integrated compiler, interpreter, and debugger: This isn't unique to Lisp, of course: many other languages, especially scripting languages and functional languages, have it. But for me C++ is one of the strongest competitors to Lisp, and the lack of this is a major reason why I don't use C++. When I write a complicated program in C++, and I'm trying to understand its behavior -- not just bugs, but e.g. performance problems in a complex problem with no single optimum algorithm -- I end up writing a lot of code to inspect the program. In Lisp I write a lot less of this because it's already there.
good compiled performance: It depends on the compiler, of course, but it's possible to compile Common Lisp efficiently. This isn't unique to Common Lisp, of course, but it's an important distinction from some scripting languages (e.g. tcl has some real problems with being compiled efficiently). Also, reasonably efficient implementations do exist, which distinguishes it from various nifty but too-small-a-niche languages.
smaller but still significant advantages: * a powerful object system (CLOS), including multiple inheritance and multiple dispatch. Multiple dispatch is an unusual feature, and sometimes you don't need it, but sometimes you really want it. If you're from a C++ background, check out Scott Meyers' _More Effective C++_ for a discussion of ways you can sort of mock it up in C++. * powerful support for object identity and i/o, with things like reader/writer support for circular data structures and the MAKE-LOAD-FORM stuff to give you the hooks you need to set up object identity correctly at load time
features which can be either advantages and disadvantages, depending: * A Common Lisp program is itself a dynamic object, and there are many standard ways to change it radically while it's running. This can be useful, but it makes it a lot harder to write various kinds of software which depends on understanding the build process of your program, e.g. to do the kind of incremental rebuilding done by Unix "make". * Common Lisp uses dynamic typing by default. This helps a lot when writing some kinds of code. But more typically, it lets you write normal code concisely and quickly, but the compiler can't understand it well enough to perform some basic sanity checks or make some useful optimizations. (You can override this to a large extent by adding type declarations, which are supported, just not required.)
Unfortunately, it's pretty hard to show the point of a lot of this in a few dozen lines of code. So I'd suggest looking at the examples mentioned earlier (the roll-your-own OOP system in Paul Graham's _ANSI Common Lisp_, or the Screamer library). Or, later I plan to write another post about memoization, and you can take a look at that.
> > 2 Those for which Common Lisp use the same syntax as everything else, where > > Common Lisp excels in overall compactness and expressibility because of a > > _much_ higher level of abstraction and much lower number of minor details > > that needs expressing, meaning that the value of a super-compact syntax > > for the simplest operators is correspondingly lower.
> Could you please give me some examples showing in what respect Lisp has a > _much_ > higher level of abstraction.
How about memoization? In Lisp, it's easy to express the abstraction "memoize this function" or "a memoized version of the given function". In most languages it's substantially harder, or simply impossible.
Here's a trivial implementation of memoization in Common Lisp. You can use it to memoize any function that's not too bizarre (so e.g. the function should return only one value, and EQUAL should be an appropriate test for equality of the function's arguments). ;; private, bare memoization function (defun %memoized (fun) (let ((memos (make-hash-table :test #'equal))) (lambda (&rest rest) (multiple-value-bind (value foundp) (gethash rest memos) (if foundp value (setf (gethash rest memos) (apply fun rest))))))) ;; public version: Make all attempts to memoize the same FUN share ;; the same closed-over hash table. (setf (symbol-function 'memoized) (%memoized #'%memoized)) Hopefully this will illustrate the point that it's simpler to express this abstraction in Lisp than in most other languages. Unfortunately, I'm too hurried to test it right now, so if you need something which actually works, see the comparably simple example on p. 65 of Paul Graham's _On Lisp_, which is what this is loosely based on.
This implementation is nice and simple because it uses lexical closures and dynamic typing. So I think you could do it in modern Perl, since it's supposed to do lexical closures. And you could maybe sorta kinda in Java, since I've heard that Java sorta kinda supports dynamic typing. In C++ you might be able to do something with templates and the STL map classes, although I'd be surprised if it'd be nearly as simple and usable as this. In the other languages I'm familiar with it might be impossible to express this abstraction at all. (You can express a memoized function in any reasonable language, of course, but can you express "memoize this function" in the language?)
I don't know whether this is a *much* higher level of abstraction -- sometimes I don't agree with every nuance of everything Erik says:-| -- but it does seem to be a distinctly higher level of abstraction, anyway.