From: Johannes Ahlmann
Subject: design and lisp
Date: 
Message-ID: <97c4504.0407310738.1195848a@posting.google.com>
hi,

I've spent a considerable amount of time getting to grips with the
concepts of lisp and would say that by now I have a good theoretical
grasp of the language.

but, coming from an object oriented (C++ *brr*) background I am having
difficulties designing my programs to make full use of LISP functional
features. have any of you had similar problems when beginning to write
programs in LISP and how did you solve them?

I am simply having problems structuring my design around LISP instead
of just implementing a C++-design in LISP...

I know this is kind of a naive question to ask, but perhaps some of
you might have pointers as how to design for LISP (i.e. radical
bottom-up programming, ...)

thanks,

Johannes

From: Rainer Joswig
Subject: Re: design and lisp
Date: 
Message-ID: <joswig-F29FB9.18001131072004@news-50.dca.giganews.com>
In article <···························@posting.google.com>,
 ·······@gmx.net (Johannes Ahlmann) wrote:

> hi,
> 
> I've spent a considerable amount of time getting to grips with the
> concepts of lisp and would say that by now I have a good theoretical
> grasp of the language.
> 
> but, coming from an object oriented (C++ *brr*) background I am having
> difficulties designing my programs to make full use of LISP functional
> features. have any of you had similar problems when beginning to write
> programs in LISP and how did you solve them?
> 
> I am simply having problems structuring my design around LISP instead
> of just implementing a C++-design in LISP...
> 
> I know this is kind of a naive question to ask, but perhaps some of
> you might have pointers as how to design for LISP (i.e. radical
> bottom-up programming, ...)
> 
> thanks,
> 
> Johannes

Reading the book Paradigms of Artificial Intelligence Programming
by Peter Norvig gives some good insights how to write (efficient)
programs in Common Lisp.
From: John Thingstad
Subject: Re: design and lisp
Date: 
Message-ID: <opsb0kdbe1pqzri1@mjolner.upc.no>
You might altso want to check out norvigs website www.norvig.com.
He has some articles here that are insightful articles on
how to use lisp effectivly.

On Sat, 31 Jul 2004 18:00:11 +0200, Rainer Joswig <······@lisp.de> wrote:

> In article <···························@posting.google.com>,
>  ·······@gmx.net (Johannes Ahlmann) wrote:
>
>> hi,
>>
>> I've spent a considerable amount of time getting to grips with the
>> concepts of lisp and would say that by now I have a good theoretical
>> grasp of the language.
>>
>> but, coming from an object oriented (C++ *brr*) background I am having
>> difficulties designing my programs to make full use of LISP functional
>> features. have any of you had similar problems when beginning to write
>> programs in LISP and how did you solve them?
>>
>> I am simply having problems structuring my design around LISP instead
>> of just implementing a C++-design in LISP...
>>
>> I know this is kind of a naive question to ask, but perhaps some of
>> you might have pointers as how to design for LISP (i.e. radical
>> bottom-up programming, ...)
>>
>> thanks,
>>
>> Johannes
>
> Reading the book Paradigms of Artificial Intelligence Programming
> by Peter Norvig gives some good insights how to write (efficient)
> programs in Common Lisp.



-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
From: Pascal Bourguignon
Subject: Re: design and lisp
Date: 
Message-ID: <87y8l02m6a.fsf@thalassa.informatimago.com>
·······@gmx.net (Johannes Ahlmann) writes:

> hi,
> 
> I've spent a considerable amount of time getting to grips with the
> concepts of lisp and would say that by now I have a good theoretical
> grasp of the language.
> 
> but, coming from an object oriented (C++ *brr*) background I am having
> difficulties designing my programs to make full use of LISP functional
> features. have any of you had similar problems when beginning to write
> programs in LISP and how did you solve them?
> 
> I am simply having problems structuring my design around LISP instead
> of just implementing a C++-design in LISP...
> 
> I know this is kind of a naive question to ask, but perhaps some of
> you might have pointers as how to design for LISP (i.e. radical
> bottom-up programming, ...)

I find it easier to build functional or "lispy" programs proceeding
bottom-up at the REPL.


if you want to keep the functional style with new classes, you have to
implement the needed supporting function.

For example, to map over a list, an array, hashtable, a package symbol
table, you already have mapcar et al., map, map-into, maphash,
do-external-symbols, etc.  But when you create your own container
class, until you program your own mapping function for this container
class, you won't be able to use it in lisp style.

    (defclass my-container (...)
        (...))

    (defmethod map-content (fun (self my-container))
        ...)

    (defparameter my-box (make-instance 'my-container))
    (map-content (lambda (item) (print item)) my-box)


Also, if you want to kee the functional style, instead of having
mutable objects, you should design only immutable objects, and state
changing methods should be replaced with creation of new instances.

    (defclass my-mutable-class ()
        ((value :type integer :initform 0 :reader value)))

    (defmethod inc-value ((self my-mutable-class) (add-value integer))
        (incf (slot-value self 'value) add-value))

    (defparameter i (make-instance 'my-mutable-class))
    (inc-value i 42)

becomes:

    (defclass my-immutable-class ()
        ((value :type integer :initform 0 :initarg :value :reader value)))

    (defmethod inc-value ((self my-immutable-class) (add-value integer))
        (make-instance 'my-immutable-class
             :value (+ (value self)  add-value)))

    (defparameter i (make-instance 'my-immutable-class))
    (setf i (inc-value i 42))

Of course object style then is harder because:

    (defparameter i (make-instance 'my-immutable-class))
    (defparameter j (inc-value i 42))
    (assert (not (eq i j)))

That means that in a functional style with objects, you have to make
evolve the whole world: all the objects that have a relation with i
must be replaced with objects in relation with j, and by transitive
closure, the whole world is duplicated in each computation step.


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

There is no worse tyranny than to force a man to pay for what he does not
want merely because you think it would be good for him. -- Robert Heinlein
From: Kenny Tilton
Subject: Re: design and lisp
Date: 
Message-ID: <LmROc.45729$oW6.9032876@twister.nyc.rr.com>
Johannes Ahlmann wrote:
> hi,
> 
> I've spent a considerable amount of time getting to grips with the
> concepts of lisp and would say that by now I have a good theoretical
> grasp of the language.
> 
> but, coming from an object oriented (C++ *brr*) background I am having
> difficulties designing my programs to make full use of LISP functional
> features. have any of you had similar problems when beginning to write
> programs in LISP and how did you solve them?

No, I was trying to write a program. I did not worry about The Lisp Way, 
exception noted below.

> 
> I am simply having problems structuring my design around LISP instead
> of just implementing a C++-design in LISP...

I think that is a good way to get started. If you code up something 
specific you think should be more Lispy, post it here and get some ideas 
from others. Specifics are easier to react to than requests for general 
guidance.

If you are really set on leapfrogging the Lisp Way learning curve, I 
guess reading a lot of good, advanced code. Stuff from Norvig or Graham 
might give you ideas for Lispy approaches to problems you would code 
much differently in C++.

> 
> I know this is kind of a naive question to ask, but perhaps some of
> you might have pointers as how to design for LISP (i.e. radical
> bottom-up programming, ...)

The one thing that I did think about while coding Lisp as a newby was 
Graham's description of what good Lisp code should look like (flowing 
down and to the right with increasing indentation). When code did not 
look like that I considered refactoring.

To my surprise, one otherwise bright and insanely productive guy I hired 
had a grudge against Lisp for some reason and did manage to resist the 
Force. You can tell which source files are his by the spike in counts of 
the string "setf". Long LET binding lists as well. When I had to 
seriously change some of his code, I had to convert it to Lispy-ness 
just to make it comprehensible. A couple of macros did wonders. It only 
took a day. I remember thinking at the time that a good lesson in The 
Lisp Way could be built around the transformations I was making, because 
watching the code become shorter and more readable as I made each 
"cosmetic" (nothing functional) change was a hoot. But that is the kind 
of thing you can get by posting code here and inviting feedback.

kenny





> 
> thanks,
> 
> Johannes

-- 
Cells? Cello? Celtik?: http://www.common-lisp.net/project/cells/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
From: Paolo Amoroso
Subject: Re: design and lisp
Date: 
Message-ID: <ff4743a5.0408012359.5840c821@posting.google.com>
Kenny Tilton <·······@nyc.rr.com> wrote in message news:<·······················@twister.nyc.rr.com>...

> To my surprise, one otherwise bright and insanely productive guy I hired 
> had a grudge against Lisp for some reason and did manage to resist the 
> Force. You can tell which source files are his by the spike in counts of 
> the string "setf". Long LET binding lists as well. When I had to 

What's wrong, i.e. un-Lispy, with long LET binding lists?


Paolo
From: Kenny Tilton
Subject: Re: design and lisp
Date: 
Message-ID: <bUtPc.45907$oW6.9546914@twister.nyc.rr.com>
Paolo Amoroso wrote:

> Kenny Tilton <·······@nyc.rr.com> wrote in message news:<·······················@twister.nyc.rr.com>...
> 
> 
>>To my surprise, one otherwise bright and insanely productive guy I hired 
>>had a grudge against Lisp for some reason and did manage to resist the 
>>Force. You can tell which source files are his by the spike in counts of 
>>the string "setf". Long LET binding lists as well. When I had to 
> 
> 
> What's wrong, i.e. un-Lispy, with long LET binding lists?

If a binding is used in only one place, it creates needless noise and 
makes code harder to read. Long binding lists generally also mean that a 
function can usefully be broken up into smaller functions. Sometimes a 
long binding list has bindings used only in one branch of the following 
logic. That's a waste and also noise. etc etc etc

kenny

-- 
Cells? Cello? Celtik?: http://www.common-lisp.net/project/cells/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
From: Rob Warnock
Subject: Re: design and lisp
Date: 
Message-ID: <Qr6dncSoZ7PpQ5PcRVn-gw@speakeasy.net>
Kenny Tilton  <·······@nyc.rr.com> wrote:
+---------------
| Paolo Amoroso wrote:
| > What's wrong, i.e. un-Lispy, with long LET binding lists?
| 
| If a binding is used in only one place, it creates needless noise and 
| makes code harder to read. Long binding lists generally also mean that a 
| function can usefully be broken up into smaller functions. Sometimes a 
| long binding list has bindings used only in one branch of the following 
| logic. That's a waste and also noise. etc etc etc
+---------------

On the other hand, breaking a long LET* into a bunch of smaller functions
can *also* create needless noise, when the LET* actually makes things
clearer by documenting a complex calculation by using single-assignment
variables to name intermediate results (subexpressions).

I find myself using this most in functions which return a newly-allocated
object of some type, particularly when there are minor decisions and
cross-checks to be made. You end up with a template of the form:

    (defun make-checked-FOO (args...)
      (let* ((field1 (or (some-computation-on-args...)
			 (alternate-computation...)
			 default))
             (field2 ...)
             (field3 ...)
	     (cse1 (intermediate-result-of args... field[123]...))
	     (field4 (some-computation args... cse1))
	     (field5 (other-computation args... cse1)))
	(make-FOO :field1 field1
	          :field2 field2
	          :field3 field3
	          :field4 field4
	          :field5 field5)))

And even when helper functions *are* needed, often a local FLET or
LABELS is the way to go. By keeping all of the tricky logic in one
place, clarity can be improved.

Or not. Obviously, if the individual computations start getting *very*
complex, they should be moved out to separate functions. I certainly
admit I have been guilty of writing monstrous LET*'s and later seeing
that they really needed refactoring to call external functions. It
all comes down to doing whichever minimizes complexity and maximizes
long-term maintainability [which includes readability]...


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Kenny Tilton
Subject: Re: design and lisp
Date: 
Message-ID: <VPEPc.111955$a92.28594@twister.nyc.rr.com>
Rob Warnock wrote:

> Kenny Tilton  <·······@nyc.rr.com> wrote:
> +---------------
> | Paolo Amoroso wrote:
> | > What's wrong, i.e. un-Lispy, with long LET binding lists?
> | 
> | If a binding is used in only one place, it creates needless noise and 
> | makes code harder to read. Long binding lists generally also mean that a 
> | function can usefully be broken up into smaller functions. Sometimes a 
> | long binding list has bindings used only in one branch of the following 
> | logic. That's a waste and also noise. etc etc etc
> +---------------
> 
> On the other hand, breaking a long LET* into a bunch of smaller functions
> can *also* create needless noise, when the LET* actually makes things
> clearer by documenting a complex calculation by using single-assignment
> variables to name intermediate results (subexpressions).

The meaningful names requirement is an ineffective bandaid on the 
difficulty of following a natural tree expression once streamrolled into 
linear form. Can we start a subthread on the care with which people name 
their variables? It would have to be subthread, because even with good 
variable names an unecessary burden is being placed on the developer's 
memeory.

> 
> I find myself using this most in functions which return a newly-allocated
> object of some type, particularly when there are minor decisions and
> cross-checks to be made. You end up with a template of the form:
> 
>     (defun make-checked-FOO (args...)
>       (let* ((field1 (or (some-computation-on-args...)
> 			 (alternate-computation...)
> 			 default))
>              (field2 ...)
>              (field3 ...)
> 	     (cse1 (intermediate-result-of args... field[123]...))
> 	     (field4 (some-computation args... cse1))
> 	     (field5 (other-computation args... cse1)))
> 	(make-FOO :field1 field1
> 	          :field2 field2
> 	          :field3 field3
> 	          :field4 field4
> 	          :field5 field5)))

Too clever by half. The parameters of make-checked-foo are the arguments 
to an instance of foo, hence they are determinative of its character. 
The above throws away an instance's determinative data, or at least 
offers no guarantee an instance will know the data by which it was 
effective authored by make-checked-FOO, which is as bad (especially for 
dynamic programming).

You need Cells. Lose make-checked-FOO. (You way be unaware of Tilton's 
Law: Thou shalt not wrap make-instance.)

  (defmodel foo ()
    (mcf-arg-00 ...)
    (mcf-arg-01 ...)
    (mcf-arg-nn ...)
    (field1 :cell t :initform (c-formula () <your computation here!>))
    ....
    (fieldn :cell t :initform (c-formula () <your computation here!>)))

A key point is that computed fields can reference other computed fields 
as well as uncomputed args, and the ordering is done automatically by 
the cells engine. No matter how complicated it gets or how much one 
changes the computations and slots during exploratory development, as 
long as one does not go cyclical (a separate, interesting issue) the 
code always runs in the right order.

Overrides are done slot by slot (not solely by class--too constricting) 
by subclassing (changing the default initarg) or by instance (specifying 
formulas as make-instance initargs). This in turn makes the code much 
more readable than the above, which requires all derivation from 
determinative args be piled into one place (make-checked-FOO) and 
thoroghly straitjackets subclassing by forcing the use of alternative 
"make-this-other-kind-of-checked-foo".

kt

-- 
Cells? Cello? Celtik?: http://www.common-lisp.net/project/cells/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
From: David Steuber
Subject: Re: design and lisp
Date: 
Message-ID: <87ekmojrpo.fsf@david-steuber.com>
Kenny Tilton <·······@nyc.rr.com> writes:

> You need Cells. Lose make-checked-FOO. (You way be unaware of Tilton's
> Law: Thou shalt not wrap make-instance.)

Odd.  Keene's book on CLOS specifically recomends wraping
make-instance to further abstract the class.  The primary rule is
provide a documented API of generic functions and make-foo as a
protocol for using the class.  This allows changes to the
implementation of foo without breaking code that might break with a
make-instance call.  Also, make-instance can not enforce required
parameters.  make-foo can do that.

-- 
An ideal world is left as an excercise to the reader.
   --- Paul Graham, On Lisp 8.1
From: Joe Marshall
Subject: Re: design and lisp
Date: 
Message-ID: <smb4jgn3.fsf@ccs.neu.edu>
David Steuber <·····@david-steuber.com> writes:

> Kenny Tilton <·······@nyc.rr.com> writes:
>
>> You need Cells. Lose make-checked-FOO. (You way be unaware of Tilton's
>> Law: Thou shalt not wrap make-instance.)
>
> Odd.  Keene's book on CLOS specifically recomends wraping
> make-instance to further abstract the class.  

I disagree.
From: Rahul Jain
Subject: Re: design and lisp
Date: 
Message-ID: <87n01boflr.fsf@nyct.net>
Joe Marshall <···@ccs.neu.edu> writes:

> David Steuber <·····@david-steuber.com> writes:
>
>> Odd.  Keene's book on CLOS specifically recomends wraping
>> make-instance to further abstract the class.  
>
> I disagree.

It can make sense if you're trying to dynamically select a specific
class based on the way the object is being initialized. In that case,
you're abstracting above classes, not above the class in question,
however.

-- 
Rahul Jain
·····@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
From: Joe Marshall
Subject: Re: design and lisp
Date: 
Message-ID: <ekmn7yan.fsf@ccs.neu.edu>
Rahul Jain <·····@nyct.net> writes:

> Joe Marshall <···@ccs.neu.edu> writes:
>
>> David Steuber <·····@david-steuber.com> writes:
>>
>>> Odd.  Keene's book on CLOS specifically recomends wraping
>>> make-instance to further abstract the class.  
>>
>> I disagree.
>
> It can make sense if you're trying to dynamically select a specific
> class based on the way the object is being initialized. In that case,
> you're abstracting above classes, not above the class in question,
> however.

Yes.

But simply wrapping make-instance adds no further abstraction, and
puts the burden on the user of the class to remember that calling
(make-instance 'foo ...) is *not* sufficient for creating a valid foo.
From: Christopher C. Stacy
Subject: Re: design and lisp
Date: 
Message-ID: <u4qnivftz.fsf@news.dtpq.com>
>>>>> On Wed, 04 Aug 2004 10:50:08 -0400, Joe Marshall ("Joe") writes:

 Joe> Rahul Jain <·····@nyct.net> writes:
 >> Joe Marshall <···@ccs.neu.edu> writes:
 >> 
 >>> David Steuber <·····@david-steuber.com> writes:
 >>> 
 >>>> Odd.  Keene's book on CLOS specifically recomends wraping
 >>>> make-instance to further abstract the class.  
 >>> 
 >>> I disagree.
 >> 
 >> It can make sense if you're trying to dynamically select a specific
 >> class based on the way the object is being initialized. In that case,
 >> you're abstracting above classes, not above the class in question,
 >> however.

 Joe> Yes.

 Joe> But simply wrapping make-instance adds no further abstraction, and
 Joe> puts the burden on the user of the class to remember that calling
 Joe> (make-instance 'foo ...) is *not* sufficient for creating a valid foo.

Maybe an unspoken assumption in this discussion is that the 
class is exported.  If it's not, then users should not be
calling MAKE-INSTANCE on it at all.
From: David Steuber
Subject: Re: design and lisp
Date: 
Message-ID: <877jsey7ks.fsf@david-steuber.com>
As a general rule, I like the class factory model over make-instance.
It may well be superfluous as Kenny says, but I think it may have
advantages in many cases.  I suspect that I am biased by my experience
with C++ and Java.  There have been times where a factory method was
cleaner than simply calling new.

Lisp also provides no real hiding of data.  Nevertheless, I also have
gotten used to 'encapsulation'.  The constructor / factory method idea
supports that when the class is not exported from its package but the
constructor and generic methods are.

I don't think this is worth a religious war since this is still mostly
a matter of taste.  I'm sure there are plenty of examples where one
way is clearly better than the other.

Although if make-foo looks like this:

(defun make-foo () (make-instance 'foo))

it sure looks like make-foo is a waste of space or whatever.  Even so,
calling it will still look a tad cleaner and have fewer keystrokes.
The usage of foo would be very much like the usage of a hashtable
using this style.  It also looks just like what you would end up with
if foo was created by defstruct instead of defclass.

So it looks to me like the make-foo style is perhaps preferable in the
general case.

-- 
An ideal world is left as an excercise to the reader.
   --- Paul Graham, On Lisp 8.1
From: Rahul Jain
Subject: Re: design and lisp
Date: 
Message-ID: <877jsdep18.fsf@nyct.net>
David Steuber <·····@david-steuber.com> writes:

> As a general rule, I like the class factory model over make-instance.

make-instance is THE factory.

-- 
Rahul Jain
·····@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
From: Joe Marshall
Subject: Re: design and lisp
Date: 
Message-ID: <oelq7iij.fsf@ccs.neu.edu>
······@news.dtpq.com (Christopher C. Stacy) writes:

>>>>>> On Wed, 04 Aug 2004 10:50:08 -0400, Joe Marshall ("Joe") writes:
>
>  Joe> But simply wrapping make-instance adds no further abstraction, and
>  Joe> puts the burden on the user of the class to remember that calling
>  Joe> (make-instance 'foo ...) is *not* sufficient for creating a valid foo.
>
> Maybe an unspoken assumption in this discussion is that the 
> class is exported.  If it's not, then users should not be
> calling MAKE-INSTANCE on it at all.

Nor any other methods!
From: Christopher C. Stacy
Subject: Re: design and lisp
Date: 
Message-ID: <uwu0ebhjp.fsf@news.dtpq.com>
>>>>> On Wed, 04 Aug 2004 16:31:00 -0400, Joe Marshall ("Joe") writes:

 Joe> ······@news.dtpq.com (Christopher C. Stacy) writes:
 >>>>>>> On Wed, 04 Aug 2004 10:50:08 -0400, Joe Marshall ("Joe") writes:
 >> 
 Joe> But simply wrapping make-instance adds no further abstraction, and
 Joe> puts the burden on the user of the class to remember that calling
 Joe> (make-instance 'foo ...) is *not* sufficient for creating a valid foo.
 >> 
 >> Maybe an unspoken assumption in this discussion is that the 
 >> class is exported.  If it's not, then users should not be
 >> calling MAKE-INSTANCE on it at all.

 Joe> Nor any other methods!

I disagree with this.  The API can provide functions that both
instantiate an object and provide (exported) methods that you
may call on the object, without exposing anything else about
the object.  The fact that it is an instance of a particular
class can be an internal detail, as is the fact that the API's
functions might be methods.  The object is just a black box, 
as are the functions that are advertised to work on it.

(setq bbox (bb:make-frob (get-universal-time)))
(bb:launch-time bbox)

Whether BBOX is a CLOS instance or a LIST is just an
implementation detail.

What you can't do is define new CLOS methods specialized on 
the class whose name you don't know.
From: ·········@random-state.net
Subject: Re: design and lisp
Date: 
Message-ID: <ces4iq$4v08p$1@midnight.cs.hut.fi>
Christopher C. Stacy <······@news.dtpq.com> wrote:

> What you can't do is define new CLOS methods specialized on 
> the class whose name you don't know.

Unless you cheat. I know this wasn't what you meant -- and all bets are
off, since MAKE-FOO may not always return objects of the same class -- but
it's late and I'm easily amused. ;-)

(defvar *black-box* (make-foo))

(defmethod foo-using-class ((class (eql (class-of *black-box*))) x)
   'black-box-magic)

(defun foo (x) (foo-using-class (class-of x) x))

(foo *black-box*) => BLACK-BOX-MAGIC

Cheers,

 -- Nikodemus                   "Not as clumsy or random as a C++ or Java. 
                             An elegant weapon for a more civilized time."
From: Joe Marshall
Subject: Re: design and lisp
Date: 
Message-ID: <wu0d5szp.fsf@ccs.neu.edu>
······@news.dtpq.com (Christopher C. Stacy) writes:

>>>>>> On Wed, 04 Aug 2004 16:31:00 -0400, Joe Marshall ("Joe") writes:
>
>  Joe> ······@news.dtpq.com (Christopher C. Stacy) writes:
>  >>>>>>> On Wed, 04 Aug 2004 10:50:08 -0400, Joe Marshall ("Joe") writes:
>  >> 
>  Joe> But simply wrapping make-instance adds no further abstraction, and
>  Joe> puts the burden on the user of the class to remember that calling
>  Joe> (make-instance 'foo ...) is *not* sufficient for creating a valid foo.
>  >> 
>  >> Maybe an unspoken assumption in this discussion is that the 
>  >> class is exported.  If it's not, then users should not be
>  >> calling MAKE-INSTANCE on it at all.
>
>  Joe> Nor any other methods!
>
> I disagree with this.  The API can provide functions that both
> instantiate an object and provide (exported) methods that you
> may call on the object, without exposing anything else about
> the object.  

I misinterpreted what you meant by `unexported'.
From: Kenny Tilton
Subject: Re: design and lisp
Date: 
Message-ID: <QWNPc.111967$a92.33212@twister.nyc.rr.com>
David Steuber wrote:

> Kenny Tilton <·······@nyc.rr.com> writes:
> 
> 
>>You need Cells. Lose make-checked-FOO. (You way be unaware of Tilton's
>>Law: Thou shalt not wrap make-instance.)
> 
> 
> Odd.  Keene's book...

Not odd. Different author, different opinion. :) Speaking of which, my 
Keene enjoys the unfortunate state of "temporarily loaned", so I cannot 
react to keene.

  on CLOS specifically recomends wraping
> make-instance to further abstract the class.  The primary rule is
> provide a documented API of generic functions and make-foo as a
> protocol for using the class.  This allows changes to the
> implementation of foo without breaking code that might break with a
> make-instance call...

Wrong, wrong, wrong. That casts things in stone (how do I override 
things done by make-foo?) and limits the user's freedom, the anithesis 
of The Lisp Way. Lispniks do not worry about breaking code (refactoring 
is easy with Lisp and if one designs well), they worry about programming 
strait jackets.

The above scheme makes sub-classing a pain. Now I have to write 
before/after/around methods on make-foo?!

   Also, make-instance can not enforce required
> parameters.   make-foo can do that.

As can shared-initialize, initialize-instance, or ":initform (error...)".

kenny


-- 
Cells? Cello? Celtik?: http://www.common-lisp.net/project/cells/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
From: Marco Gidde
Subject: Re: design and lisp
Date: 
Message-ID: <lz7jsgfdfr.fsf@tristan.br-automation.de>
David Steuber <·····@david-steuber.com> writes:
> make-instance call.  Also, make-instance can not enforce required
> parameters.  make-foo can do that.

Just seen in Peter Seibel's new chapter "A Spam Filter":

(defclass word-feature ()
  ((word       
    :initarg :word
    :accessor word
    :initform (error "Must supply :word")
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    :documentation "The word this feature represents.")
   (spam-count
    :initarg :spam-count
    :accessor spam-count
    :initform 0
    :documentation "Number of spams we have seen this feature in.")
   (ham-count
    :initarg :ham-count
    :accessor ham-count
    :initform 0
    :documentation "Number of hams we have seen this feature in.")))

I think CL is contradictory to "can not" :-)

-- 
Marco Gidde
From: Rahul Jain
Subject: Re: design and lisp
Date: 
Message-ID: <87r7qnofpd.fsf@nyct.net>
David Steuber <·····@david-steuber.com> writes:

> Also, make-instance can not enforce required parameters. make-foo can
> do that.

(defclass foo ()
  ((slot :initarg :slot :initform (error "Required slot not initialized."))))

-- 
Rahul Jain
·····@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
From: David Steuber
Subject: Re: design and lisp
Date: 
Message-ID: <87ekmnvzcl.fsf@david-steuber.com>
Rahul Jain <·····@nyct.net> writes:

> David Steuber <·····@david-steuber.com> writes:
> 
> > Also, make-instance can not enforce required parameters. make-foo can
> > do that.
> 
> (defclass foo ()
>   ((slot :initarg :slot :initform (error "Required slot not initialized."))))

It looks like I need to reread Keene as I've made some erroneous
statements.  However, I do distincly recall the recomendation of using
constructor functions (which will of course be calling make-instance).

The first mention is made in section 3.3 "Creating New Objects -
Instances".

   We recommend that you define constructor functions to be used by
   the client to make instances.  A constructor is a tailored way to
   make an instance of a given class; its name usually describes the
   kind of instance that it creates.  A constructor provides a more
   abstract external interface than does make-instance, because its
   name describes its higher level purpose (make a null lock) instead
   of its internal implementation (make an instance of the class
   null-lock).

   Another advantage is that a constructor can have required
   arguments.  In contrast, all arguments to make-instance except for
   the first are optional.  We might prefer to require that users
   initialize the name of a lock.

The last paragraph is in error as shown by the above use of
:initform.  Still, under Emacs + SLIME with auto-doc mode on, you will
see the arglist to a constructor function specific to that function.
You will see the arglist for make-instance also, but that is for the
general function make-instance.

Obviously matters of style are matters of taste and thus rather
subjective.  Even with a constructor there is nothing to prevent you
from going ahead and using make-instance anyway.

-- 
An ideal world is left as an excercise to the reader.
   --- Paul Graham, On Lisp 8.1
From: Kenny Tilton
Subject: Re: design and lisp
Date: 
Message-ID: <mh7Qc.114303$a92.90922@twister.nyc.rr.com>
David Steuber wrote:
> Rahul Jain <·····@nyct.net> writes:
> 
> 
>>David Steuber <·····@david-steuber.com> writes:
>>
>>
>>>Also, make-instance can not enforce required parameters. make-foo can
>>>do that.
>>
>>(defclass foo ()
>>  ((slot :initarg :slot :initform (error "Required slot not initialized."))))
> 
> 
> It looks like I need to reread Keene as I've made some erroneous
> statements.  However, I do distincly recall the recomendation of using
> constructor functions (which will of course be calling make-instance).
> 
> The first mention is made in section 3.3 "Creating New Objects -
> Instances".
> 
>    We recommend ...

very strange in a technical reference, btw.

that you define constructor functions to be used by
>    the client to make instances.  A constructor is a tailored way to
>    make an instance of a given class; its name usually describes the
>    kind of instance that it creates.  A constructor provides a more
>    abstract external interface than does make-instance, because its
>    name describes its higher level purpose (make a null lock) instead
>    of its internal implementation (make an instance of the class
>    null-lock).

Generating a superfluous interface for a class is a silly way to 
document it. CLOS is both expressive and readable. Assuming one does not 
want to have a whole class for null locks (I think I would), what is 
wrong with?:

(defclass lock ()
   ((nullp :initform nil :initarg :nullp :accessor nullp
           :documentation "non-nil => null lock")
    ...))

> 
>    Another advantage is that a constructor can have required
>    arguments.  In contrast, all arguments to make-instance except for
>    the first are optional.  We might prefer to require that users
>    initialize the name of a lock.
> 
> The last paragraph is in error ...

well, they are right about make-instance per se, but wrong about whether 
make-instance will return successfully if some ":initform (error...)" is 
reached.

kenny


-- 
Cells? Cello? Celtik?: http://www.common-lisp.net/project/cells/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
From: Peter Herth
Subject: Re: design and lisp
Date: 
Message-ID: <ceqv97$3kc$1@newsreader2.netcologne.de>
I have been pondering the pros and cons of a (make-something ) constructor
style versus make-instance for a while too. But I think this thread has
given me some results:

- when there are no required initargs, adding a constructor function
  usually does not provide extra abstraction or functionality, so it
  is not needed and thus perhaps even should be avoided (unless many
  classes require a constructor function and for uniformity reasons
  they are added to all classes).

- with the :initform (error ...) mechanism there is a way to enforce
  initializing a slot. Event if a constructor function is provided,
  this prevents bypassing it via direct calls to make-instance without
  initializing the corresponding slot.

- When there are mandatory arguments for object creation, a constructor
  function is a good way to go, first, as already mentioned ,it is self-
  documenting and second, if the required parameters are not given, usually 
  results in compile-time warnings, which is always preferrable to
  runtime-errors.

Peter

-- 
pet project: http://dawn.netcologne.de
homepage:    http://www.peter-herth.de
lisp stuff:  http://www.peter-herth.de/lisp.html
get Ltk here: http://www.peter-herth.de/ltk/
From: Kenny Tilton
Subject: Re: design and lisp
Date: 
Message-ID: <n18Qc.114305$a92.63373@twister.nyc.rr.com>
Peter Herth wrote:
> - When there are mandatory arguments for object creation, a constructor
>   function is a good way to go, first, as already mentioned ,it is self-
>   documenting and second, if the required parameters are not given, usually 
>   results in compile-time warnings, which is always preferrable to
>   runtime-errors.

Not so preferable as to justify creating the otherwise superfluous 
interface, especially since it does not work. Assuming I am too lazy to 
understand the class I am trying to use, I will likewise simply supply 
nil for the "required" constructor function argument I do not understand.

kenny

-- 
Cells? Cello? Celtik?: http://www.common-lisp.net/project/cells/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
From: Peter Herth
Subject: Re: design and lisp
Date: 
Message-ID: <cera5d$ra6$1@newsreader2.netcologne.de>
Kenny Tilton wrote:

> Not so preferable as to justify creating the otherwise superfluous
> interface, especially since it does not work. Assuming I am too lazy to
> understand the class I am trying to use, I will likewise simply supply
> nil for the "required" constructor function argument I do not understand.

Well it iss at least a strong hint that the argument is needed. Of course,
if you specify nil, you are actively trying to break things (unless the
constructor function knows how to deal with this case). Afterall, 
the spirit of Lisp (so far as I grasped it) is not about trying to make
things unbreakable (usually a futile exercise anyway) but about giving
some clear hints about what is the proper way, trusting its users to
know what he is doing to some extend :).
All this is assuming that this parameter is really required to
correctly construct an object of that type. As with the factory
pattern, this furthermore has the advantage, that the constructor
function in contrast to make-instance can decide not to return 
an object if construction was not possible.

Peter

-- 
pet project: http://dawn.netcologne.de
homepage:    http://www.peter-herth.de
lisp stuff:  http://www.peter-herth.de/lisp.html
get Ltk here: http://www.peter-herth.de/ltk/
From: Antonio Menezes Leitao
Subject: Re: design and lisp
Date: 
Message-ID: <87llgukc8g.fsf@evaluator.pt>
Peter Herth <·····@netcologne.de> writes:

> I have been pondering the pros and cons of a (make-something ) constructor
> style versus make-instance for a while too. But I think this thread has
> given me some results:
>
> - when there are no required initargs, adding a constructor function
>   usually does not provide extra abstraction or functionality, so it
>   is not needed and thus perhaps even should be avoided (unless many
>   classes require a constructor function and for uniformity reasons
>   they are added to all classes).
>
> - with the :initform (error ...) mechanism there is a way to enforce
>   initializing a slot. Event if a constructor function is provided,
>   this prevents bypassing it via direct calls to make-instance without
>   initializing the corresponding slot.
>
> - When there are mandatory arguments for object creation, a constructor
>   function is a good way to go, first, as already mentioned ,it is self-
>   documenting and second, if the required parameters are not given, usually 
>   results in compile-time warnings, which is always preferrable to
>   runtime-errors.

I thinks there's an obvious situation where you should define a
constructor instead of using make-instance: when you are not sure you
want to expose the fact that you are using CLOS instances instead of,
e.g., structures or conses.

This might be important when you want to use the CLOS flexibility to
prototype your class hierarquies but also want to be able to change it
latter to a more efficient data representation without disturbing the
rest of the program.

This is, IMHO, the best reason for using constructors instead of
make-instance.

Ant�nio Leit�o.
From: Pascal Costanza
Subject: Re: design and lisp
Date: 
Message-ID: <cesuoa$ih0$1@newsreader2.netcologne.de>
Antonio Menezes Leitao wrote:

> This is, IMHO, the best reason for using constructors instead of
> make-instance.

(defmethod make-instance :around ((class (eql 'my-class)))
   ... create something else ...)

However, it seems that this is prohibited by the restrictions of the 
COMMON-LISP package.


Pascal

-- 
Tyler: "How's that working out for you?"
Jack: "Great."
Tyler: "Keep it up, then."
From: ·········@random-state.net
Subject: Re: design and lisp
Date: 
Message-ID: <cet9cs$5126r$1@midnight.cs.hut.fi>
Pascal Costanza <········@web.de> wrote:

> (defmethod make-instance :around ((class (eql 'my-class)))
>    ... create something else ...)

> However, it seems that this is prohibited by the restrictions of the 
> COMMON-LISP package.

Are you referring to 11.1.2.1.2.19? At least _it_ doesn't prohibit this
unless my-class is a standardized class -- and I can't see anything else
the would. Am I missing something?

Also, since make-instance on symbols is defined to redirect to 

 (apply #'make-instance (find-class class-name) initargs) ; or equivalent

the better way is to do:

 (defmethod make-instance :around ((class (eql (find-class 'my-class)))
                                   &rest initargs)
     ...)

Though I must say I was sort of hoping to find something that disallowed
such subversion (requiring methods on MAKE-INSTANCE to return an instance
of the specified class on pain of nasal demons), I didn't. :/

Cheers,

 -- Nikodemus                   "Not as clumsy or random as a C++ or Java. 
                             An elegant weapon for a more civilized time."
From: Christophe Rhodes
Subject: Re: design and lisp
Date: 
Message-ID: <sqk6wdwwqk.fsf@cam.ac.uk>
·········@random-state.net writes:

> Pascal Costanza <········@web.de> wrote:
>
>> (defmethod make-instance :around ((class (eql 'my-class)))
>>    ... create something else ...)
>
>> However, it seems that this is prohibited by the restrictions of the 
>> COMMON-LISP package.
>
> Are you referring to 11.1.2.1.2.19? At least _it_ doesn't prohibit this
> unless my-class is a standardized class -- and I can't see anything else
> the would. Am I missing something?

The _symbol_ MY-CLASS is a direct instance of the standardized class
named by SYMBOL.  Likewise, the class #<STANDARD-CLASS MY-CLASS>, to
close the other hole, is a direct instance of the class named by
STANDARD-CLASS.

Christophe
-- 
http://www-jcsu.jesus.cam.ac.uk/~csr21/       +44 1223 510 299/+44 7729 383 757
(set-pprint-dispatch 'number (lambda (s o) (declare (special b)) (format s b)))
(defvar b "~&Just another Lisp hacker~%")    (pprint #36rJesusCollegeCambridge)
From: ·········@random-state.net
Subject: Re: design and lisp
Date: 
Message-ID: <cete7s$4su4o$1@midnight.cs.hut.fi>
Christophe Rhodes <·····@cam.ac.uk> wrote:

> named by SYMBOL.  Likewise, the class #<STANDARD-CLASS MY-CLASS>, to
> close the other hole, is a direct instance of the class named by
> STANDARD-CLASS.

My brain must be on vacation.

Cheers,

 -- Nikodemus                   "Not as clumsy or random as a C++ or Java. 
                             An elegant weapon for a more civilized time."
From: Rahul Jain
Subject: Re: design and lisp
Date: 
Message-ID: <87brhpep42.fsf@nyct.net>
Peter Herth <·····@netcologne.de> writes:

> - When there are mandatory arguments for object creation, a constructor
>   function is a good way to go, first, as already mentioned ,it is self-
>   documenting and second, if the required parameters are not given, usually 
>   results in compile-time warnings, which is always preferrable to
>   runtime-errors.

What happens when someone subclasses your object? They don't
automatically get any changes you make to your constructor in their
constructor. Also, you'll need to provide the above :initform (error)
slot options anyway in case someone decides to use make-instance.

-- 
Rahul Jain
·····@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
From: Thomas Schilling
Subject: Re: design and lisp
Date: 
Message-ID: <opsb0ftgwetrs3c0@news.CIS.DFN.DE>
Johannes Ahlmann <·······@gmx.net>:

> I've spent a considerable amount of time getting to grips with the
> concepts of lisp and would say that by now I have a good theoretical
> grasp of the language.
>
> but, coming from an object oriented (C++ *brr*) background I am having
> difficulties designing my programs to make full use of LISP functional
> features. have any of you had similar problems when beginning to write
> programs in LISP and how did you solve them?
>
> I am simply having problems structuring my design around LISP instead
> of just implementing a C++-design in LISP...
>
> I know this is kind of a naive question to ask, but perhaps some of
> you might have pointers as how to design for LISP (i.e. radical
> bottom-up programming, ...)

Just use it. ;)

Actually it's that simple. Use it and maybe compare how others wrote same 
or similar stuff. Personally I read an advanced Lisp book [1] before doing 
any serious work. That helped really a lot, because you'll see yourself 
facing similar problems. And, as always, you will still find ways to 
improve older code at any time.

What's also helpful is good knowledge of the standard library in order to 
avoid reinventing stuff, which (surprise, surprise!) will also come with 
using it.

I think you just should start. And don't be afraid--refactoring Lisp code 
is also not that costly.

Good Luck

-ts

[1] "On Lisp" by Paul Graham. also available online, ask Google

-- 
      ,,
     \../   /  <<< The LISP Effect
    |_\\ _==__
__ | |bb|   | _________________________________________________
From: Marco Gidde
Subject: Re: design and lisp
Date: 
Message-ID: <lz8ycz97hf.fsf@tristan.br-automation.de>
·······@gmx.net (Johannes Ahlmann) writes:
> but, coming from an object oriented (C++ *brr*) background I am having
> difficulties designing my programs to make full use of LISP functional
> features. have any of you had similar problems when beginning to write
> programs in LISP and how did you solve them?
> 
> I am simply having problems structuring my design around LISP instead
> of just implementing a C++-design in LISP...

If you want to get used to functional programming, just do it, all the
time and everywhere, even when you are solving some problems with
C++. It will look ugly and complicated in C++ but it often works. This
way you learn where functional style is appropriate and where you
should better use a different technique. Common Lisp is a multi
paradigm language, so you can always choose the style that fits your
problem best.


-- 
Marco Gidde
From: Alex Drummond
Subject: Re: design and lisp
Date: 
Message-ID: <ceh5vh$ove$1@uns-a.ucl.ac.uk>
Firstly, I wouldn't be too eager to start using a functional style just 
for the sake of it. There's nothing wrong with writing OO/imperative 
code in Lisp. Secondly, if you do want to develop a more functional 
style, it might help to learn a language which only allows you to 
program functionally, such as Haskell. That way you learn a lot of FP 
tricks you probably wouldn't have come across in Lisp, and it's 
surprising how many techniques from Haskell translate effectively into 
Lisp. Combinator parsing is one example of an FP technique which can be 
usefully applied in Lisp, but which isn't covered in any of the standard 
Lisp texts AFAIK.

Alex

Johannes Ahlmann wrote:
> hi,
> 
> I've spent a considerable amount of time getting to grips with the
> concepts of lisp and would say that by now I have a good theoretical
> grasp of the language.
> 
> but, coming from an object oriented (C++ *brr*) background I am having
> difficulties designing my programs to make full use of LISP functional
> features. have any of you had similar problems when beginning to write
> programs in LISP and how did you solve them?
> 
> I am simply having problems structuring my design around LISP instead
> of just implementing a C++-design in LISP...
> 
> I know this is kind of a naive question to ask, but perhaps some of
> you might have pointers as how to design for LISP (i.e. radical
> bottom-up programming, ...)
> 
> thanks,
> 
> Johannes
From: Rahul Jain
Subject: Re: design and lisp
Date: 
Message-ID: <87isbzof6m.fsf@nyct.net>
Alex Drummond <··········@ucl.ac.uk> writes:

> Combinator parsing is one example of an FP technique which can be
> usefully applied in Lisp, but which isn't covered in any of the standard
> Lisp texts AFAIK.

Any parsing technique can be used in Lisp. It's just that Lisp already
comes with an excellent generic parser, which most of us reuse for
developing our own programming constructs and configuration languages. 
Therefore, the entire subject of parsing of computer languages is rarely
discussed in Lisp texts. PAIP does, however, discuss parsing English
into its actual sentence structure.

-- 
Rahul Jain
·····@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
From: Friedrich Dominicus
Subject: Re: design and lisp
Date: 
Message-ID: <8765831ebr.fsf@fbigm.here>
·······@gmx.net (Johannes Ahlmann) writes:

>
> but, coming from an object oriented (C++ *brr*) background I am having
> difficulties designing my programs to make full use of LISP functional
> features. have any of you had similar problems when beginning to write
> programs in LISP and how did you solve them?
Functional programming /is/ different. Lisp can be programmed in a
functional way, but one has not do it that way. For me it was very
helpful to get a "pure" functional language and try to write some code
there. It has muched help on how to use the functional side from
Common Lisp. 


>
> I am simply having problems structuring my design around LISP instead
> of just implementing a C++-design in LISP...
A C++ design in Lisp can be a good design....

Regards
Friedrich

-- 
Please remove just-for-news- to reply via e-mail.
From: Christophe Turle
Subject: Re: design and lisp
Date: 
Message-ID: <cel3a3$c5r$1@amma.irisa.fr>
Johannes Ahlmann wrote:
> I know this is kind of a naive question to ask, but perhaps some of
> you might have pointers as how to design for LISP (i.e. radical
> bottom-up programming, ...)

I had the same question in my head, and actually i have more insight about it.

What i understand about the bottom-up programming :
- instead of writing your application in a language, build new languages to describe your application !

And this is THE big difference with others language. Lisp is not just a multi-paradigm language it's a meta-language.
At the end you are not writting in lisp, you are writing in your particular language, specifically designed for
your application. Changing, evolving your app will become very easy.


What's the design process ? ( not sure about it, still experimenting, use at your own risk ;-) )
- define your app with the best descriptive language for it. You will see that this language is surely not CL.
- so define this language L1 with a new language L2. L2 should be suited to describe L1 semantic.
- repeat until Ln is CL.


Reference :
On lisp, PAIP : of course.

"Lisp: A language for Stratified Design"; H.Abelson, G.J.Sussman. http://library.readscheme.org/page7.html


ctu.



 
From: Kenny Tilton
Subject: Re: design and lisp
Date: 
Message-ID: <xPtPc.45905$oW6.9546689@twister.nyc.rr.com>
Marco Parrone wrote:
>>- instead of writing your application in a language, build new languages to describe your application !
> 
> 
> Please can you describe the difference of the two above things?
> 
> Why a set of functions and data structures falls into the application
> domain in C, but the equivalent set of functions and data structures
> (or maybe classes for OO guys) falls into the language domain in Lisp?
> 
> For powerful languages like Lisp and C, Isn't the language/application 
> discrimination just a matter of personal view?  How can you objectively
> say if you are writing a language for building your application, or if
> you are writing the core of your application, or a support library?
> 
> Perhaps are you just suggesting to change view?
> 
> I'm not an expert, perhaps I'm very wrong, that's just IMHO, the questions
> are real, not rethorical.

Macros.

Your point is valid. Indeed, when some folks ask how to program in 
functional style, saying they are coming from C, I point out that one 
can work in a functional (loosely-defined) style in C.

But what you get with C et al is not a language, rather an API to a 
library. It can be a nice, clean api to a nice library, but lots of 
"wiring" will be apparent in the source.

Macros let you hide the wiring and literally create a new language. Me, 
I like sexpr syntax and Lisp syntax in general, so I have never gone 
hole hog and created an embedded language, but for certain applications 
I can see it being a good idea.

kenny

-- 
Cells? Cello? Celtik?: http://www.common-lisp.net/project/cells/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
From: Peter Seibel
Subject: Re: design and lisp
Date: 
Message-ID: <m3ekmp8pvm.fsf@javamonkey.com>
Kenny Tilton <·······@nyc.rr.com> writes:

> Macros let you hide the wiring and literally create a new language.
> Me, I like sexpr syntax and Lisp syntax in general, so I have never
> gone hole hog and created an embedded language, but for certain
> applications I can see it being a good idea.

Also it's worth noting that it's not necessary to abandon sexp syntax
to create an "embedded language". That is, the key chararcterestic of
an embedded language is whether they give you new constructs to work
with; not whether the syntax changes. For instance a parser generator
I wrote once let me define lexers and parsers using a DEFPROD macro.
The syntax of DEFPROD was still sexp based but you probably wouldn't
call it "Lisp". For example a few productions from the grammar for a
Java lexer looked like this:

  (defprod type () (/ primitive-type reference-type))

  (defprod primitive-type () (/ numeric-type "boolean"))

  (defprod numeric-type () (/ integral-type floating-point-type))

  (defprod integral-type () (/ "byte" "short" "int" "long" "char"))

  (defprod floating-point-type () (/ "float" "double"))

  ;; etc.

-Peter


-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Christophe Turle
Subject: Re: design and lisp
Date: 
Message-ID: <celrlu$igl$1@amma.irisa.fr>
Marco Parrone wrote:
>>- instead of writing your application in a language, build new languages to describe your application !
> 
> 
> Please can you describe the difference of the two above things?

i will try.

> Why a set of functions and data structures falls into the application
> domain in C, but the equivalent set of functions and data structures
> (or maybe classes for OO guys) falls into the language domain in Lisp?
> For powerful languages like Lisp and C, Isn't the language/application 
> discrimination just a matter of personal view?  How can you objectively
> say if you are writing a language for building your application, or if
> you are writing the core of your application, or a support library?


When you write a new application in C++, you must think in C++. In lisp, you CAN think directly in the right language, write in it, then implement it. It's why i prefer "meta-language" instead of "multi-paradigm".

let's take an example : rewrite rules

(defrule -> (+ x 0) x ) ;; rules saying that x + 0 may be rewritten as x.

I wrote this rule just thinking in my app domain ( rewrite rules ). Never thinking about Lisp. Of course you can argue for the S-exp notation, but this is just that a notation/syntax. But really there's no lisp there. The '+' may not be the CL one. The rule is written directly into the app domain language without interference from the implementation language.

So can you write this in C++ without thinking in C++ : choose which types to use, defining functions or class with C++ syntax ?
Yes surely, by rewriting a part of lisp in your app ;-)


> Perhaps are you just suggesting to change view?

I think that it's more deeper than that. 
 

ctu.
From: Joerg Hoehle
Subject: Re: design and lisp
Date: 
Message-ID: <usmat39da.fsf@users.sourceforge.net>
·············@email.it (Marco Parrone) writes:
> > - instead of writing your application in a language, build new languages to describe your application !
> 
> Please can you describe the difference of the two above things?
> Perhaps are you just suggesting to change view?

I'll try, as I'm fond of domain specific languages (DSL).
Lately, I had to write test cases for embedded cards.
Here's the definition of a test:

(test grow_lc		; name
  "case 0001 - Lc byte too large"	; description
  (incf lc)		; code
  error.params		; expected error code
  )

TEST is a macro (like DEFUN) that extracts the various bits and calls
some function to do the actual work.
Advantage:
 + it's quite fast to set up
 + you benefit from the interactive Lisp read-eval-print loop
 + full power of data-manipulations and a powerful language for
   implementing these - i.e. the code slot above is any Lisp code, as
   complex as necessary.

Then I can run this test acse just by LOAD'ing the file which contains it.

In other languages (e.g. C++, Java), what would it look like?
a) define a mini-language representation (e.g. XML?? no!)
b) choose&construct or configure a parser to parse that ad hoc language
c) no interactive session, it's just batch processing
   edit recompile link, no-go

How much time would a+b) take you?

Regards,
	Jorg Hohle
Telekom/T-Systems Technology Center
From: Kaz Kylheku
Subject: Re: design and lisp
Date: 
Message-ID: <cf333042.0408030656.6d62e9d9@posting.google.com>
·······@gmx.net (Johannes Ahlmann) wrote in message news:<···························@posting.google.com>...
> hi,
> 
> I've spent a considerable amount of time getting to grips with the
> concepts of lisp and would say that by now I have a good theoretical
> grasp of the language.
> 
> but, coming from an object oriented (C++ *brr*) background I am having
> difficulties designing my programs to make full use of LISP functional
> features. have any of you had similar problems when beginning to write
> programs in LISP and how did you solve them?

One idea that doesn't attract a whole lot of attention is you can make
use of your background in shell scripting. Have you ever written long
pipelines that transform text through many stages? This is a primitive
form of functional programming, over lines of text. Why is it
functional? Because a pipeline never overwrites its source data. Each
pipeline stage constructs new data out of the properties of the old,
and then when the data is saved (which is the one destructive,
imperative operation done at the end) it is put into a brand new file.

The core of functional programming is the composition of filters over
data. The data is structured, so if you are coming from that text
filtering background, you find that, by comparison, much all of the
rotten problems with text filtering go away, but the benefits remain:
you have small pipeline elements that do a small job and can be
debugged individually, data can be intercepted at various stages, etc.

> I am simply having problems structuring my design around LISP instead
> of just implementing a C++-design in LISP...

I think it starts with data. If you were putting together a little
application for yourself made using shell scripts under UNIX, you
wouldn't even think of writing data structures to represent the data.
Without a question, you would immediately think of how to represent
the data in text, and then that would dictate what kind of operations
you would apply.

Now in Lisp you run into the problem of too much choice, because you
*can* write in a style resembling C++. You *can* take some UML design
that was intended to be turned into C++ and render it in Lisp, in fact
even better.

I think that if you start with these question: how do I represent most
of the abstractions of this problem without defining any rigid
structures or classes? Then you are halfway there because you can use
the large built-in library of functions for working with sequences and
so on.

If you do use structures or classes, then to remain in a functional
style, think ``constructors and accessors only''. Once you construct
an object, you can inquire about its properties, but not mutate it so
that its properties change. This will help you because it will
eliminate surprising side effects between modules, when one program
makes an unexpected change to an object affecting the behavior of
another.

> I know this is kind of a naive question to ask, but perhaps some of
> you might have pointers as how to design for LISP (i.e. radical
> bottom-up programming, ...)

There is no one way to design in Lisp because of all the paradigms
that are supported, plus ways to codify your own. It's not necessary
to use a functional style. But your question seems to be about
incorporating more of that functional style in your Lisp programming.

How about starting with some concrete problem? Say you were writing a
game, like Pac Man. How would you do it functionally? You have all
this state information in the game, like the position of Pac Man, the
ghosts, the pellets, the scoreboard and so on. In purely functional
programming, you would never do anything like ``increment the x
coordinate of this ghost object by 5''. Rather, you would have a
recursive, hierarchical representation of the entire game: a game has
all these various properties that define its current state. Computing
the next frame of the game would be done as a global filtering
operation on the entire game object, the result of which would be the
construction of a new, different game object with a different score,
different position of Pac Man within the maze and so on.
From: Alain Picard
Subject: Re: design and lisp
Date: 
Message-ID: <873c33g8s7.fsf@memetrics.com>
···@ashi.footprints.net (Kaz Kylheku) writes:

> Say you were writing a
> game, like Pac Man. How would you do it functionally? [SNIP]...
> you would have a
> recursive, hierarchical representation of the entire game: [SNIP]
> Computing the next frame of the game ...
> the  construction of a new, different game object 

Is this ever done in practice?  (I mean, for real programs, with
demands on performance etc).  It's a wonderfully appealing idea, but
I wonder if all the copying involved eventually kills performance.

Anyone know of a real game written in this style?


-- 
It would be difficult to construe        Larry Wall, in  article
this as a feature.			 <·····················@netlabs.com>