From: Robert Posey
Subject: What is LISP?
Date: 
Message-ID: <38A1BF22.B22BB9E1@raytheon.com>
Dear Gentle Persons,

Question 1:

As I understand it nothing in CL standard requires an Interpreter, does it 
even require an interactive mode?  Every LISP system I have looked has an
Interactive Mode where at least complied functions can be run, and many have
an interpreter in this mode.  What is actually required?  I far as I can see
there in nothing keeping LISP from being compile and run like most C
systems.  While I certainly love incremental compilers in any language is
this a requirement of LISP systems, or simply a custom.

Question 2:

What should LISP typing method be called?  I have heard several variations, but
all the more advanced code I have seen makes use of typing for at least some
of the symbols.


Question 3:

Is it true that you can overload(in C++ Terms) built in operators in LISP? 
While
I wholeheartedly agree with this, I wanted to make sure.  I haven't seen it
mentioned
in any of the books I have, but they didn't state it wasn't possible which also
seemed strange.  BTW I know that many of the built in functions and procedures
allow
the use of &key, and user defined functions can be overloaded as much as you
want, I
am talking about (+ X Y) and similar functions.  If LISP doesn't have this, its 
a good thing, if you don't believe me try reading VHDL code where the '+' sign  
overload 15 different ways for basically the same input.

Question 4:

What does the :ntest (I think) key do for applicable functions?


Muddy

From: Erik Naggum
Subject: Re: What is LISP?
Date: 
Message-ID: <3159120191728291@naggum.no>
* Robert Posey <·····@raytheon.com>
| Question 1:
| 
| As I understand it nothing in CL standard requires an Interpreter, does
| it even require an interactive mode?

  standards always have explicitly and very strictly limited scope.  the
  way users interact with a Common Lisp system is outside the scope of the
  Common Lisp standard.

| Question 2:
| 
| What should LISP typing method be called?

  it is already called "dynamic typing", "manifest typing", etc.

| I have heard several variations, but all the more advanced code I have
| seen makes use of typing for at least some of the symbols.

  you're applying static typing terminology to dynamic typing phenomena.
  this will hurt your understanding.  in Common Lisp, _values_ have type,
  and variables can (normally) hold values of any type.  therefore, you
  don't talk about the type of symbols (variables), but about the types of
  values that a variable can hold.  in statically typed languages, the type
  affects the layout and size of the memory allocated to a variable.  in
  Common Lisp, a variable is always allocated the same size memory, and
  what it holds is a pointer to the value, stored elsewhere, except in some
  obvious optimizations like (small) integers and characters, which fit in
  the space of such a pointer.  to make things work efficiently in this
  model, pointers carry type information.  this is very much unlike what
  you do in statically typed languages, where pointers are just machine
  addresses which the compiler hopes will point to values it knows, and
  then it tries to make sure its hopes come true by barfing on code that it
  can see will or does violate its hopes.  it can never actually be 100%
  certain, however.  using typed pointers, one doesn't have to deal with
  such silly hopes, and can instead work with whatever is there.

  put it another way, in a statically typed language, you may sometimes
  need to lie to your compiler to do the right thing, like you sometimes
  have to lie to officials who are anal-retentive about stupid laws and
  regulations, while in dynamically typed languages, you don't have to lie,
  because the laws and regulations can't be stupid.

| Question 3:
| 
| Is it true that you can overload(in C++ Terms) built in operators in LISP? 

  no.  C++-style overloading is fundamentally evil, and is therefore not
  supported by good languages.  (note: this is not an opinion.)

| Question 4:
| 
| What does the :ntest (I think) key do for applicable functions?

  whatever the function documents it to do.  the meaning of keywords
  arguments is not added vertically to functions in Common Lisp.

  :NTEST is unknown to me.  however, if you refer to the :TEST-NOT keyword,
  common to functions which also sport a :TEST keyword, for functions that
  support this semantics, it's a way to specify a test function to whose
  value NOT is applied before it is used.  another way to do the same thing
  is :TEST (COMPLEMENT <function>).

#:Erik
From: Vladimir Nesterovsky
Subject: Re: What is LISP?
Date: 
Message-ID: <38a47d9a.40618064@news.netvision.net.il>
Erik, ---

could you please explain this a little? :-)

On 09 Feb 2000 21:23:11 +0000, Erik Naggum <····@naggum.no> wrote:

>* Robert Posey <·····@raytheon.com>
>| Question 3:
>| 
>| Is it true that you can overload(in C++ Terms) built in operators in LISP? 
>
>  no.  C++-style overloading is fundamentally evil, and is therefore not
>  supported by good languages.  (note: this is not an opinion.)
> ...
>#:Erik

So far it's the only C++ feature as I know of,
that has no correspondence in Common LISP.
That's the only argument of the C++ people
that I don't know how to answer to.

While I'll take your word for it, could you
please just provide me with some explanation,
so that whenever that argument comes, I'd
have an answer. 

TIA
From: Christopher C Stacy
Subject: Re: What is LISP?
Date: 
Message-ID: <x8lr9ekcmgv.fsf@world.std.com>
Operator overloading is a way to assign new meanings to primitive elements
of the language.  But doing so tends to defeat the language -- it makes
it impossible to understand a piece of code that you are looking at.
When you see a code fragment like  a+b+c   you know that it is adding
numbers together using some known arithmetic.   But in the preseence of
operator overloading you no longer know what "+"  means.  This is especially
true since "+" is in a single namespace.  This makes the code difficult to
understand, thereby defeating the purpose of having something that you
would call a "language".  The seeming convenience or flexibility or
expressiveness of being able to recyle the basic words in the language
(such as "+") results in practice to only lead to confusion.  

A similar bad idea is available without operator overloading (that is, with
just "polymorphism").  When you make up the name of a new function, there
is nothing that forces you to implement methods that have any kind of shared
meaning.  But if the same function name means to do various unrelated things
depending on the object, that would be terribly confusing code to read.

A more sensible idea would be to choose different function names for
different functionality, or if you wanted to recycle a words to mean
something different (or for use in a new domain) you ought to put it
in another namespace (package).

The point of a language is that the words have meaning.  The "operator
overloading" in C++ is just a way to thwart the most basic vocabulary.
That's why people say it's a bad idea.

In Lisp, you can do something similar to operator overloading,
by creating your own package, not importing some of the Lisp symbols,
and replacing them with your own symbols.    You could thereby define
your own CAR as a generic function and implement methods that have
something to do with automobiles.   Or you could do something even
more confusing: define a function named CAR that operated on conses
(and lists and NIL) like regular CAR did (perhaps by calling out
to the real CAR function), but that when applied to a floating point
number would return the integral portion.   Doing anything like this
would be considered to be inventing your own language, and that's
very difficult territory.  At least in Lisp, if you needed to do
something like this, the fact that you are now programming in your 
own language would be visually apparent, and seperate from programming
in normal Lisp.  A typical example of a good use for this kind of
approach is the implementation of SCHEME in Common Lisp.
From: Thomas A. Russ
Subject: Re: What is LISP?
Date: 
Message-ID: <ymiael7zm6t.fsf@sevak.isi.edu>
Christopher C Stacy <······@world.std.com> writes:

I'm in overall agreement with what CStacy says, but I would like to
amplify on one point:

> The point of a language is that the words have meaning.  The "operator
> overloading" in C++ is just a way to thwart the most basic vocabulary.
> That's why people say it's a bad idea.

Like many tools, there are good uses and bad uses for operator
overloading.  The problem is that once released into the wild, it is
very difficult to limit the uses of a technique to only the good ones.

Similar to CStacy's comments on overloading polymorphic names, the
reasonable approach to operator overloading is to only use it when the
overloaded operation is conceptually congruent with the operator.

So that would mean that overloading "+" to handle new arithmetic types
like bignums, rational numbers or complex numbers would make sense.
This would be a GOOD use.  The new data types interoperate with other
numbers in the way one would expect from the meaning of addition.

Overloading "+" to also mean string concatenation would be a BAD use,
since using the operator to connect a string and a number would result
in confusion.

Some of the effects of this design philosophy can be subtle and also
open to debate.  Overloading "*" for matrix operations appears IMO to be
reasonable, since there is a standard definition for what should happen
when a scalar and a matrix are multiplied.  The same cannot be said for
"+", since matrix addition only works for matrices.  Overloading in this
case begins to get a bit iffy.

-- 
Thomas A. Russ,  USC/Information Sciences Institute          ···@isi.edu    
From: Michael Hudson
Subject: Re: What is LISP?
Date: 
Message-ID: <m3puu3v9bw.fsf@atrus.jesus.cam.ac.uk>
···@sevak.isi.edu (Thomas A. Russ) writes:

> Christopher C Stacy <······@world.std.com> writes:
> 
> I'm in overall agreement with what CStacy says, but I would like to
> amplify on one point:
> 
> > The point of a language is that the words have meaning.  The "operator
> > overloading" in C++ is just a way to thwart the most basic vocabulary.
> > That's why people say it's a bad idea.
> 
> Like many tools, there are good uses and bad uses for operator
> overloading.  The problem is that once released into the wild, it is
> very difficult to limit the uses of a technique to only the good ones.
> 
> Similar to CStacy's comments on overloading polymorphic names, the
> reasonable approach to operator overloading is to only use it when the
> overloaded operation is conceptually congruent with the operator.
> 
> So that would mean that overloading "+" to handle new arithmetic types
> like bignums, rational numbers or complex numbers would make sense.
> This would be a GOOD use.  The new data types interoperate with other
> numbers in the way one would expect from the meaning of addition.

One of the issues here is the syntactic inflexibility and
inconsistency of C++. I mean, 

num1 * num2

looks very different from

matrix1.mul(matrix2)

or

mat_mul(matrix1,matrix2)

whereas

(* num1 num2)

doesn't look all that much different from

(mat* matrix1 matrix2)

The argument that overloading * for matrices is OK because it's well
defined to mix scalars and matrices in a product is bogus, IMHO,
because I can't really imagine a situation where you wouldn't know
whether a term was a scalar or a matrix.

Of course it would be easy enough (in lisp...) to implement mat* to
recognise scalars too.

And to distend the point even further you *can* overload * in lisp, by
creating a package where cl:* is shadowed. This means the domain of
overloading is syntactically restricted, but that's surely a good
thing.

Cheers,
Michael
From: Christopher C Stacy
Subject: Re: What is LISP?
Date: 
Message-ID: <x8lhffeuax5.fsf@world.std.com>
>>>>> On 11 Feb 2000 09:24:58 -0800, Thomas A Russ ("T") writes:
 T> So that would mean that overloading "+" to handle new arithmetic types
 T> like bignums, rational numbers or complex numbers would make sense.
 T> This would be a GOOD use.  The new data types interoperate with other
 T> numbers in the way one would expect from the meaning of addition.

Even if it's just arithmetic, the problem is that people could well
disagree over the correct semantics for these operations and representations
in the various domains.  When looking at an expression like a+b, 
a programmer will still not be able to know what it means.

If bignums and rationals and complex numbers were important,
they should have been provided just once in the language;
either in the core or in a standard (eg. ANSI) library.

If it's something where everyone's going to invent their own thing,
they ought to be naming the operators differently somehow.

 T> Overloading "+" to also mean string concatenation would be a BAD use,
 T> since using the operator to connect a string and a number would result
 T> in confusion.

Of course, given the capability, people will do exactly that, only
worse, with different programmers screwing each other upside down
and sideways all over the place.

A few years ago I was helping a friend with her C++ homework (from a
course at in the computer science department of a major university
here in Boston).  The teacher had them defining a data structure
representing a hotel reservation, and then using operator overloading
of the arithmetic operators (such as "+") to indicate hotel functions
(making room reservations, etc.).
From: David Thornley
Subject: Re: What is LISP?
Date: 
Message-ID: <HV_q4.159$Yd2.18716@ptah.visi.com>
In article <···············@world.std.com>,
Christopher C Stacy  <······@world.std.com> wrote:
>>>>>> On 11 Feb 2000 09:24:58 -0800, Thomas A Russ ("T") writes:
> T> So that would mean that overloading "+" to handle new arithmetic types
> T> like bignums, rational numbers or complex numbers would make sense.
> T> This would be a GOOD use.  The new data types interoperate with other
> T> numbers in the way one would expect from the meaning of addition.
>
>Even if it's just arithmetic, the problem is that people could well
>disagree over the correct semantics for these operations and representations
>in the various domains.  When looking at an expression like a+b, 
>a programmer will still not be able to know what it means.
>
I don't know what it means in C.  Is it adding two integers or two
floating-point numbers?  The difference in behavior can be significant.
To put it another way, "+" comes overloaded in most languages I'm
familiar with, and the question is whether you should be able to
overload it in other ways or not.

Stroustrup is very big on trusting the programmer.  This means that
he would like a competent programmer to have as many useful tools
as possible, even if they can be horribly misused by less competent
programmers.

>If bignums and rationals and complex numbers were important,
>they should have been provided just once in the language;
>either in the core or in a standard (eg. ANSI) library.
>
You mean in the core.  Not in a library.  Neither C nor C++ permit
ANSI libraries to redefine operators in a way any different from
user-written libraries.

You're also assuming that everything of use can be handled by the
standards committee.  IIRC, C++ has a sophisticated complex number
library (which relies on the ability to overload "+" to work), and
no bignum or rational facilities.  What the overloading means is
that somebody can write such a library, and have it work like an
integral part of the language.

C++ actually does a good job of being an extensible language for
something based on C.

>If it's something where everyone's going to invent their own thing,
>they ought to be naming the operators differently somehow.
>
There are cases where people aren't going to invent their own thing.
Everybody knows what adding two matrices does.  If you have a matrix
class, and define "+", then either it's a memberwise addition allowing
only identically dimensioned matrices, or it's wrong.

> T> Overloading "+" to also mean string concatenation would be a BAD use,
> T> since using the operator to connect a string and a number would result
> T> in confusion.
>
In that case, define string::operator+(const string &str), but not
any string::operator+(int i).  Then, using the operator is an error
caught at compile time.

>Of course, given the capability, people will do exactly that, only
>worse, with different programmers screwing each other upside down
>and sideways all over the place.
>
Well, yes.  I have tools in my house that can cause considerable
injury or death if used improperly.  Should I dispose of them?

>A few years ago I was helping a friend with her C++ homework (from a
>course at in the computer science department of a major university
>here in Boston).  The teacher had them defining a data structure
>representing a hotel reservation, and then using operator overloading
>of the arithmetic operators (such as "+") to indicate hotel functions
>(making room reservations, etc.).

It may strike some as heartless or anarchist, but I keep getting the
feeling that that's what God invented sniper rifles for.  It would cause
pain and anguish, but it would prevent hundreds of innocents from being
told that that sort of overloading is a reasonable thing to do.


--
David H. Thornley                        | If you want my opinion, ask.
·····@thornley.net                       | If you don't, flee.
http://www.thornley.net/~thornley/david/ | O-
From: Vladimir Nesterovsky
Subject: Re: What is LISP?
Date: 
Message-ID: <38a57449.668923@news.netvision.net.il>
Thanks for this explanation! :-)

On Fri, 11 Feb 2000 05:55:12 GMT, Christopher C Stacy
<······@world.std.com> wrote:
From: Fernando D. Mato Mira
Subject: Re: What is LISP?
Date: 
Message-ID: <38A3DA56.5483D9A7@iname.com>
Vladimir Nesterovsky wrote:

> Erik, ---
>
> >  no.  C++-style overloading is fundamentally evil, and is therefore not
> >  supported by good languages.  (note: this is not an opinion.)
> > ...
> >#:Erik
>
> So far it's the only C++ feature as I know of,
> that has no correspondence in Common LISP.
> That's the only argument of the C++ people
> that I don't know how to answer to.

To be more precise, the person setting free a language supporting BOTH static
and dynamic polymorphism should burn in a deeper level of Hell than "the first
to write PIC 99".

--
Fernando D. Mato Mira
Real-Time SW Eng & Networking
Advanced Systems Engineering Division
CSEM
Jaquet-Droz 1                   email: matomira AT acm DOT org
CH-2007 Neuchatel                 tel:       +41 (32) 720-5157
Switzerland                       FAX:       +41 (32) 720-5720

www.csem.ch      www.vrai.com     ligwww.epfl.ch/matomira.html
From: Erik Naggum
Subject: Re: What is LISP?
Date: 
Message-ID: <3159296157829526@naggum.no>
* Erik Naggum
| C++-style overloading is fundamentally evil, and is therefore not
| supported by good languages.  (note: this is not an opinion.)

* Vladimir Nesterovsky
| So far it's the only C++ feature as I know of, that has no correspondence
| in Common LISP.  That's the only argument of the C++ people that I don't
| know how to answer to.
| 
| While I'll take your word for it, could you please just provide me with
| some explanation, so that whenever that argument comes, I'd have an
| answer.

  sure.

  the main semantic argument against C++-style operator overloading is that
  there is nothing in the language that helps maintain consistency of any
  kind for each implementation of an overloaded operator.  in particular,
  each implementation may well have completely different argument lists,
  commutativity may differ at will, but you still have to cope with the
  same associativity and order of precedence.  a + is not a +, anymore.
  (witness the absurd and decidedly overcute use of << and >> for I/O.)

  the main pragmatic argument against C++-style operator overloading is a
  fatal design decision.  the choice of which function to call makes the
  use of overloaded operators downright dangerous: the return type of an
  overloaded operator is _not_ taken into account when choosing the
  particular implementation, which causes a cascade of decisions in nested
  or sequential forms over which you have no control.  in particular, code
  changes anywhere in an interconnected system can affect such decisions
  adversely, without even the possibility of warning or traceability since
  editing and (re-)compiling are so separated tasks.

  the main stylistic argument is that a reader of the code has no idea what
  to expect from _any_ expression that uses operators that _might_ have
  been overloaded, without _manually_ checking for surprises, _remembering_
  the types of objects, and trying to reconstruct the whole decision chain
  made by the compiler.

  so what makes a language feature evil?  first, when it wastes human brain
  time on minutiae that language features are supposed to help _conserve_
  or at least spend _more_ wisely.  second, when it forces people to
  second-guess the compiler to figure out what's going on.  third, when you
  despite second-guessing the compiler can no longer know for _certain_
  what will happen, but have to makes guesses in the first place.  all in
  all, a language feature is evil when it removes from the programmer's
  control what, precisely, he is doing, at all levels of abstraction and
  semantics and he is left with uncertainty and doubt, if not obscure bugs
  that are extremely hard to find and which makes systems using such
  features frightfully fragile.

  even the good uses of operator overloading, for which they were added to
  that miserable excuse for a programming language, destroy the ability of
  _any_ "visiting" programmer to know what _any_ expression means, meaning
  that the required level of intimacy with the code is tremendously high,
  which translates to "job security" for Joe C++ Programmer and "how to get
  royally screwed" for his employer.

  so not only is operator overloading evil, programmers who want it are
  looking for "insurance" if they should ever have any serious gripes with
  their employers.  as I have said previously, in connection with the need
  among C++ programmers to "protect" their data and methods, C++ is for
  thieves and bums who expect _others_ to steal, too; operator overloading
  is just more of the same: bad people are attracted to features with high
  abusiveness potential along with anal-retentive protection schemes
  because they expect everybody else to screw them, too.

  (very little of this is _mere_ opinion.)

#:Erik
From: Ray Blaak
Subject: Re: What is LISP?
Date: 
Message-ID: <m3ya8qr8jf.fsf@ns57.infomatch.bc.ca>
Erik Naggum <····@naggum.no> writes:
> [a good critique of C++ operator overloading]

But what about method overloading (i.e. non-operators)? Then the points in your
critique do not apply, except for C++'s problem with the lack of the return
type being considered as part of the signature.

Ada, at least, gets this "right". The full signature is considered (even
parameter names, since one can optionally use a named notation on a routine
call).

Operator overloading has serious problems, but I have found normal method
overloading to be useful at writing less cluttered code.

-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
·····@infomatch.com                            The Rhythm has my soul.
From: Marius Vollmer
Subject: Re: What is LISP?
Date: 
Message-ID: <87900etfkk.fsf@zagadka.ping.de>
Erik Naggum <····@naggum.no> writes:

[ C++ operator overloading ]
>
> a + is not a +, anymore.  (witness the absurd and decidedly overcute
> use of << and >> for I/O.)

This is even worse when overloading && and || because they lose their
short cut behaviour for user defined types.
From: Thomas A. Russ
Subject: Re: What is LISP?
Date: 
Message-ID: <ymid7q5zvei.fsf@sevak.isi.edu>
Robert Posey <·····@raytheon.com> writes:

> Question 2:
> 
> What should LISP typing method be called?  I have heard several variations, but
> all the more advanced code I have seen makes use of typing for at least some
> of the symbols.

I wonder if this more advanced code you have seen involved CLOS
methods.  In CLOS methods the types are used to enable method dispatch.

In other cases (with DECLARE statements) the use of type declarations is
done to enable the compiler to perform optimizations that require a
promise to only use values of particular types.  This is most likely
only useful for numeric types.

> Question 3:
> 
> Is it true that you can overload(in C++ Terms) built in operators in LISP? 

No.
For built-in GENERIC functions, you are allowed to define new methods,
but for portable code you need to specialize the methods using at least
one class that is not built-in.

One nice design feature of generic functions is that they require
congruent argument lists.  That restricts their ability to be
"overloaded" (in the sense of having more than one meaning), which is,
of course, a good thing.

> Question 4:
> 
> What does the :ntest (I think) key do for applicable functions?

No clue.  What is an example of such a function?

For some sequence functions, the :TEST keyword allows you to specify a
predicate to use for matching.

-- 
Thomas A. Russ,  USC/Information Sciences Institute          ···@isi.edu    
From: Robert Monfera
Subject: Re: What is LISP?
Date: 
Message-ID: <38A1C672.1C5D10CC@fisec.com>
Robert Posey wrote:

> Question 2:
>
> What should LISP typing method be called?

Manifest typing or run-time typing.

Note that typing can be turned to C-like unboxed representations with
declarations, but it only makes sense if it is guaranteed that a place
is of a certain type and the gains justify extra development time spent
with declarations.  Don't worry about these optimizations now, but rest
assured you can make your code really fast.

> Question 3:
>
> Is it true that you can overload(in C++ Terms) built in operators in LISP?

So a better way of asking Q3 is: "Can I use polymorphic functions in
Lisp?" or similar.  Ask what you _really_ want to know, to avoid having
to second-guess you.

You aren't supposed to change functions in the CL package.  As for your
own functions, CLOS provides a way of polymorphism way superior to C++
templates.  Check out DEFINE-COMPILER-MACRO also, but time is better
spent in learning Lisp rather than comparing it with other languages and
trying to do something that those languages do when you may never need
anything like that in Lisp.

Robert
From: Tom Breton
Subject: Re: What is LISP?
Date: 
Message-ID: <m3d7q5g3g9.fsf@world.std.com>
Robert Posey <·····@raytheon.com> writes:

> Dear Gentle Persons,
> 
> Question 1:
> 
> As I understand it nothing in CL standard requires an Interpreter, does it 
> even require an interactive mode?  Every LISP system I have looked has an
> Interactive Mode where at least complied functions can be run, and many have
> an interpreter in this mode.  What is actually required?  I far as I can see
> there in nothing keeping LISP from being compile and run like most C
> systems.  While I certainly love incremental compilers in any language is
> this a requirement of LISP systems, or simply a custom.

This is true, and there have been Lisp systems like GCL and CLICC
(sp?) that only compile.  I've never used either myself.

-- 
Tom Breton, http://world.std.com/~tob
Not using "gh" since 1997. http://world.std.com/~tob/ugh-free.html