Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Question: Lisp's power points

16 views
Skip to first unread message

Károly Ladvánszky

unread,
Oct 11, 2001, 4:28:01 AM10/11/01
to
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

Kent M Pitman

unread,
Oct 11, 2001, 6:12:00 AM10/11/01
to
"Károly Ladvánszky" <ladvansz...@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.

(setf (get 'fred 'favorite-sports) '(boxing tennis archery))
=> (BOXING TENNIS ARCHERY)

You can write a function to inquire whether something is in such a list:

(defun likes? (person sport)
(if (member sport (get person sport))
'yes 'no))
=> LIKES?

Then you can ask

(likes? person1 'boxing)
=> YES

Another common thing is to associate one symbol with another in a list.
For example:

(setf (get 'acme 'jobs)
'((sally president)
(mark vice-president)
(fred secretary)))
=> ((SALLY PRESIDENT) (MARK VICE-PRESIDENT) (FRED SECRETARY))

Then you can say:

(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

(jobs-in 'acme)
=> (PRESIDENT VICE-PRESIDENT SECRETARY)

(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?

Marco Antoniotti

unread,
Oct 11, 2001, 10:55:04 AM10/11/01
to

"Károly Ladvánszky" <ladvansz...@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'.

Kaz Kylheku

unread,
Oct 11, 2001, 2:33:20 PM10/11/01
to
In article <3bc55...@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++.

Wade Humeniuk

unread,
Oct 11, 2001, 3:21:57 PM10/11/01
to
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).

Primitive HTML tools

http://www.cadvision.com/humeniuw/primitive-html.lisp

and an example of using Primitive HTML Report Generation

http://www.cadvision.com/humeniuw/html-report.lisp

Wade

"Károly Ladvánszky" <ladvansz...@digicart.hu> wrote in message
news:3bc55...@corp-goliath.newsgroups.com...

Erik Naggum

unread,
Oct 11, 2001, 5:26:30 PM10/11/01
to
* 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?

Christophe Rhodes

unread,
Oct 12, 2001, 4:33:02 AM10/12/01
to
Marco Antoniotti <mar...@cs.nyu.edu> writes:

> "Károly Ladvánszky" <ladvansz...@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.

Christophe
--
Jesus College, Cambridge, CB5 8BL +44 1223 510 299
http://www-jcsu.jesus.cam.ac.uk/~csr21/ (defun pling-dollar
(str schar arg) (first (last +))) (make-dispatch-macro-character #\! t)
(set-dispatch-macro-character #\! #\$ #'pling-dollar)

Károly Ladvánszky

unread,
Oct 12, 2001, 8:04:48 AM10/12/01
to
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.

"Erik Naggum" <er...@naggum.net> az alábbiakat írta a következo üzenetben:
news:32118243...@naggum.net...

Marco Antoniotti

unread,
Oct 12, 2001, 9:38:51 AM10/12/01
to

Christophe Rhodes <cs...@cam.ac.uk> writes:

> Marco Antoniotti <mar...@cs.nyu.edu> writes:
>
> > "Károly Ladvánszky" <ladvansz...@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.

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.

Marco Antoniotti

unread,
Oct 12, 2001, 9:46:43 AM10/12/01
to

"Károly Ladvánszky" <ladvansz...@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>.

Károly Ladvánszky

unread,
Oct 12, 2001, 10:01:15 AM10/12/01
to
Thanks Kent for your quick reply. It has helped me a lot indeed.

Károly

"Kent M Pitman" <pit...@world.std.com> az alábbiakat írta a következő
üzenetben: news:sfwvghm...@world.std.com...

Paolo Amoroso

unread,
Oct 12, 2001, 11:52:14 AM10/12/01
to
On Fri, 12 Oct 2001 14:04:48 +0200, "Károly Ladvánszky"
<ladvansz...@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:

http://lisa.sourceforge.net


Paolo
--
EncyCMUCLopedia * Extensive collection of CMU Common Lisp documentation
http://web.mclink.it/amoroso/ency/README
[http://cvs2.cons.org:8000/cmucl/doc/EncyCMUCLopedia/]

Rolf Wester

unread,
Oct 12, 2001, 12:08:12 PM10/12/01
to

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.

Thanks

Rolf


Kenny Tilton

unread,
Oct 12, 2001, 1:54:27 PM10/12/01
to

Rolf Wester wrote:

> Could you please give me some examples showing in what respect Lisp has a
> _much_
> higher level of abstraction.
>

yippee! a debate on degrees of "higher". this should be a beaut!

kenny
clinisys

Kaz Kylheku

unread,
Oct 12, 2001, 2:42:20 PM10/12/01
to
In article <3bc6d...@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. :)

Kaz Kylheku

unread,
Oct 12, 2001, 2:44:09 PM10/12/01
to
In article <3bc6d...@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''. :)

j...@itasoftware.com

unread,
Oct 12, 2001, 3:29:41 PM10/12/01
to
k...@ashi.footprints.net (Kaz Kylheku) writes:

> In article <3bc6d...@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.

Erik Naggum

unread,
Oct 12, 2001, 6:16:28 PM10/12/01
to
* 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.

Rolf Wester

unread,
Oct 13, 2001, 7:29:10 AM10/13/01
to

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.

Erik Naggum

unread,
Oct 13, 2001, 12:43:39 PM10/13/01
to
* 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.

Roger Corman

unread,
Oct 14, 2001, 3:43:18 AM10/14/01
to
On Sat, 13 Oct 2001 16:43:39 GMT, Erik Naggum <er...@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?

Rolf Wester

unread,
Oct 14, 2001, 6:55:30 AM10/14/01
to

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.

Rolf Wester


William Newman

unread,
Oct 14, 2001, 11:59:30 AM10/14/01
to
k...@ashi.footprints.net (Kaz Kylheku) wrote in message news:<QBlx7.65021$ob.15...@news1.rdc1.bc.home.com>...

> In article <3bc55...@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.

William Newman

unread,
Oct 14, 2001, 12:39:05 PM10/14/01
to
Rolf Wester <wes...@ilt.fhg.de> wrote in message news:<3BC7156C...@ilt.fhg.de>...

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.

Paolo Amoroso

unread,
Oct 14, 2001, 3:58:57 PM10/14/01
to
On 14 Oct 2001 08:59:30 -0700, william...@airmail.net (William Newman)
wrote:

> Common Lisp_, or the Screamer library). Or, later I plan to write another
> post about memoization, and you can take a look at that.

This is a useful note on memoization:

http://ww.telent.net/cliki/Ask%20Uncle%20Peter

cbbr...@acm.org

unread,
Oct 14, 2001, 5:22:42 PM10/14/01
to
Erik Naggum <er...@naggum.net> writes:
> * 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.

What would be nice to have would be "pithy" examples of code to
exemplify these sorts of things.

The newcomer (whether troll or real) could easily walk away from this
saying:
"Hmm... Special variables. I wonder what those are?"

A quick look at the HyperSpec certainly does _not_ cause the
implications of them to leap out at one; the quick browse raises a lot
more questions than it answers:

- Why did you say "special variable," when all the glossary indicates
is "see dynamic variable"?

- Then there's these other terms, "dynamic extent," "indefinite
extent," "dynamic scope," and "dynamic environment." They all seem
somewhat relevant, but how does it go together?

It definitely isn't a "pithy" explanation.

The section in CLTL2 on "Scope and Extent" explains it a little more
clearly, I think, but it doesn't get to the point of explaining why it
would be considered _important_.

A reasonably "pithy" example is shown here:
<http://www.n-a-n-o.com/lisp/cmucl-tutorials/LISP-tutorial-12.html>

It doesn't say anything that would cause Special Variable to "leap to
mind as the obvious first choice."

Note that I'm not disagreeing with the notion that SV's are useful or
important; I _would_ disagree with the notion that this is either
obvious, or even a represents a notion readily accessible to a novice.

I don't think _any_ of the items you list are "obviously obvious;" I
just did a quick review of the set of introductory documents on CL,
and few give much, if any treatment of them.

That could mean (at least :-)) two things:

1. Perhaps you're wrong.

I don't think you're particularly wrong. There could be quibbling
over "who's on first," but the features you describe do appear
like good candidates for "_much_ higher level of abstraction."

2. The literature is doing a bad job of communicating these sorts of
features.

This seems to me to be a _whole_ lot more likely.

There are two books on CLOS (one of which I have seen) which describe
its merits.

"On Lisp" sells hard the power of macros.

Various references do describe the importance of closures.

But the "You really need to know and understand and use special
variables, the type hierarchy, and custom readers" parts are _not_
"evangelized" in the literature in similar manner to [say] CLOS.

Note that I am _not_ being critical about either CLTL2 or CLHS on
this; they do not have, in their proper scope of intent, the mission
of explaining: "Here are techniques that you should use!"

I think the world could use an "essay" or "book" that describes 7
different applications of readtables, for instance, sort of
paralleling Keene's book on CLOS.
--
(reverse (concatenate 'string "gro.mca@" "enworbbc"))
http://www.ntlug.org/~cbbrowne/lisp.html
"It is easier to optimize correct code, than correct optimized code"
-- Yves Deville

Erik Naggum

unread,
Oct 14, 2001, 5:46:28 PM10/14/01
to
* cbbr...@acm.org

| What would be nice to have would be "pithy" examples of code to
| exemplify these sorts of things.

Then you go write them. In my experience, examples illustrating an
unknown concept usually mislead people. Besides, writing examples that
actually work to illustrate _concepts_ takes a lot of time and effort.
May I tell you that publication here is not exactly _rewarded_ when you
only complain about people not doing enough to satisfy you? Why not just
write and publish the stuff you missed yourself if it would be so nice?

| I think the world could use an "essay" or "book" that describes 7
| different applications of readtables, for instance, sort of paralleling
| Keene's book on CLOS.

Again, feel free to write it yourself. It is quite enjoyable until you
get complaints from people who _demand_ more without any encouragement.

Erik Naggum

unread,
Oct 14, 2001, 5:55:46 PM10/14/01
to
* Roger Corman

| 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.

This is true, but extending the concept of special binding to threads is
not a conceptual hurdle, it is more of an implementational hurdle.

| In my opinion an optimal implementation of per-thread special variable
| bindings does not require any re-binding.

I was unspecific. The design I had mind was threads managed by a single,
monolithic process, but I did cover the case of separate processes, as
well, those needing IPC and shared memory. I.e., the process scheduler
in the Common Lisp system, not the kernel, would have to do a context
switch that would include saving and restoring the binding stack of the
new context. This is one of the drawbacks of having your own scheduler,
but there are also serious drawbacks to using operating system threads
and processes, especially when using shared memory for all the global
_objects_, and that includes code.

| And if all those threads are active at once, no problem. No context
| switching need occur.

Well, context switching between threads at the operating system level is
different from context switching between threads when privately managed.

| I can't see a reason for a thread to re-bind it, and then have all other
| threads see the binding.

That was clearly not what I wanted to say, either.

| I think you would have multiple threads trying to undo each others
| bindings, possibly.

Only if you assume a globally shared memory and operating system threads.
I find it fascinating that you only consider those kinds of threads and
not the well-known technique of managing multiprocessing privately.

Tim Bradshaw

unread,
Oct 15, 2001, 5:27:57 AM10/15/01
to
Erik Naggum <er...@naggum.net> writes:

>
> Well, context switching between threads at the operating system level is
> different from context switching between threads when privately managed.
>

But on a more-than-one-processor machine there may be no context switching,
either at OS or Lisp level.

--tim

David Boles

unread,
Oct 15, 2001, 8:40:36 PM10/15/01
to
Kaz Kylheku wrote:

> In article <3bc6d...@corp-goliath.newsgroups.com>, Károly Ladvánszky wrote:

>>...


>>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).

> ...

>
> 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

> ...

My apologies for straying just a teensy bit, but the truth about
COM/DCOM is so poorly understood by non-Windows people that it
bears pointing out.

In both RPC and CORBA IDL's, one can write:

struct Point {
int x;
int y;
}

and then define functions that took items with type "Point" as
arguments. You can write this in COM, but you could not use such
a function across the various COM languages until, at best,
recently, *unless you write you own code to marshal a Point*.
How any company could have shipped a cross-language RPC mechanism
in the 90's that couldn't support basic struct's without being
laughed at is beyond me.

Various service packs and releases of language runtimes were
supposed to make all of this go away at some point. As a company
we escaped the whole COM/DCOM/COM+ debacle and discovered that
underneath all that cruft is a fairly reliable and capable OS.

- db

0 new messages