From: ···········@gmail.com
Subject: organizing lisp code
Date: 
Message-ID: <1149017544.671560.275890@j73g2000cwa.googlegroups.com>
Hi

Is there any convention for organizing lisp code into different files?
I'm most used to Java where every class goes into it's own files (with
a few exceptions, of course) but that seems overkill in lisp where a
defclass would probably be just a few lines at most.

In another post, it was discussed that the defgeneric's be in defined
on their own since in CLOS methods don't belong to the classes
themselved.

Any suggestions welcome.

Thanks
Vijay Lakshminarayanan

From: ···········@gmail.com
Subject: Re: organizing lisp code
Date: 
Message-ID: <1149022959.233262.127710@j55g2000cwa.googlegroups.com>
Personally, I tend to organize my definitions into logical "modules,"
and put each in a file. There are three guidelines I use to decide what
a module is:

1) The definitions inside a module are usually fairly closely coupled.
Generally, it consists of a few classes, which are often related by
containment or inheritance, and some functions/methods which operate on
those classes.

2) The definitions, when taken together, form a coherent,
information-hiding interface. Unfortunately, as far as I know, there is
no language support for deciding which definitions are interface, and
which are implementation: Common Lisp only has packages, which aren't
fine-grained enough to give one to each module. Some programmers prefix
their "private" symbols with % signs or the like.

3) Once I've split my code into modules, I can make a dependency
ordering on them. I can say, for instance, "module C only uses
definitions from modules A and B, and module B only uses definitions
from module A." I try to organize the modules so that each module has
as few dependencies as possible, and I avoid circular dependencies like
the plague. If you have a circular dependency, it almost always means
that you should move some definitions around, or split off the
troublesome definitions into a separate module.

Hope that helps!
Nick Thomas
From: ···········@gmail.com
Subject: Re: organizing lisp code
Date: 
Message-ID: <1149042492.512091.165380@c74g2000cwc.googlegroups.com>
···········@gmail.com wrote:
> Personally, I tend to organize my definitions into logical "modules,"
> and put each in a file. There are three guidelines I use to decide what
> a module is:
>
> 1) The definitions inside a module are usually fairly closely coupled.
> Generally, it consists of a few classes, which are often related by
> containment or inheritance, and some functions/methods which operate on
> those classes.

Okay.  That sounds good.

> 2) The definitions, when taken together, form a coherent,
> information-hiding interface. Unfortunately, as far as I know, there is
> no language support for deciding which definitions are interface, and
> which are implementation: Common Lisp only has packages, which aren't
> fine-grained enough to give one to each module. Some programmers prefix
> their "private" symbols with % signs or the like.

This I have never encountered before (though I admit that I
haven't encoutered much in Lisp) I thought that CLOS' lack
of support for encapsulation had it's own reasons and that
that programmers just exported the symbols that are `public'
so to speak.  Peter Seibel in PCL says something along these
very lines I think (I don't own the book but mostly follow
it online -- it's on my wish-list and I'm hoping someone
buys it for me soon ;-)) and I think he also says that if
necessary, a programmer can use an un-exported symbol if the
author has forgotten to do the same.  And I believe that
Lispers consider lack of encapsulation a feature than a
loss.

Do you know how commonly this %private-symbol convention
is used?

> 3) Once I've split my code into modules, I can make a dependency
> ordering on them. I can say, for instance, "module C only uses
> definitions from modules A and B, and module B only uses definitions
> from module A." I try to organize the modules so that each module has
> as few dependencies as possible, and I avoid circular dependencies like
> the plague. If you have a circular dependency, it almost always means
> that you should move some definitions around, or split off the
> troublesome definitions into a separate module.

Can I say that all defconstants (related to a module) would
go into one single file?

Would the defparameters and defvars go in this same file?
Or would they be coupled with the module file where the
classes etc are defined?

> Hope that helps!

It does.  Thanks :)

Cheers
Vijay Lakshminarayanan
From: ···········@gmail.com
Subject: Re: organizing lisp code
Date: 
Message-ID: <1149121899.949891.145080@c74g2000cwc.googlegroups.com>
···········@gmail.com wrote:
> This I have never encountered before (though I admit that I
> haven't encoutered much in Lisp) I thought that CLOS' lack
> of support for encapsulation had it's own reasons and that
> that programmers just exported the symbols that are `public'
> so to speak.  Peter Seibel in PCL says something along these
> very lines I think (I don't own the book but mostly follow
> it online -- it's on my wish-list and I'm hoping someone
> buys it for me soon ;-)) and I think he also says that if
> necessary, a programmer can use an un-exported symbol if the
> author has forgotten to do the same.  And I believe that
> Lispers consider lack of encapsulation a feature than a
> loss.

I don't think there are many people who think that encapsulation is a
bad idea. What the author of PCL is probably referring to is the fact
that Common Lisp doesn't actively *prevent* you from breaking
encapsulation, which is a good thing, since it makes it possible to do
more things with metaprogramming (source-level debuggers, smart
editors, etc.) That's "good" encapsulation-breaking. "Bad"
encapsulation-breaking (which should be avoided) can be characterized
by this rule of thumb: it is any kind of breakage will result in the
ceased functioning of the code doing the breaking when the code it is
breaking into changes. A debugger won't stop working if someone removes
%private-bar from the frobble library, but any code that calls
%private-bar probably will break.

> Do you know how commonly this %private-symbol convention
> is used?

Having not worked on many Lisp projects that other people wrote, I
don't know. Perhaps someone else can help out here. You can be pretty
sure, though, that people will know what you mean if you do it.

> Can I say that all defconstants (related to a module) would
> go into one single file?
>
> Would the defparameters and defvars go in this same file?
> Or would they be coupled with the module file where the
> classes etc are defined?

Myself, I put the def{constant,var,parameter}s inside the file with all
of the other definitions in their module. Since Common Lisp has some
(not a lot, but some) restrictions regarding what order you declare
things, I generally separate declarations by their types, and put them
in the following order: macros, classes,
constants/variables/parameters, generics, functions/methods. The only
things I put in a separate file are the package definitions, which all
go in one file, 'packages.lisp'.

Of course, these aren't hard-and-fast rules. They're just the way I do
it, and they have drawbacks as well as advantages.
From: ···········@gmail.com
Subject: Re: organizing lisp code
Date: 
Message-ID: <1149188219.883117.204450@j55g2000cwa.googlegroups.com>
···········@gmail.com wrote:
> ···········@gmail.com wrote:
> >  And I believe that
> > Lispers consider lack of encapsulation a feature than a
> > loss.
>
> I don't think there are many people who think that encapsulation is a
> bad idea. What the author of PCL is probably referring to is the fact
> that Common Lisp doesn't actively *prevent* you from breaking
> encapsulation, which is a good thing, since it makes it possible to do
> more things with metaprogramming (source-level debuggers, smart
> editors, etc.) That's "good" encapsulation-breaking. "Bad"
> encapsulation-breaking (which should be avoided) can be characterized
> by this rule of thumb: it is any kind of breakage will result in the
> ceased functioning of the code doing the breaking when the code it is
> breaking into changes. A debugger won't stop working if someone removes
> %private-bar from the frobble library, but any code that calls
> %private-bar probably will break.

I don't understand what you mean by a debugger not breaking.  Should I
refer to the (in my case) SBCL manual to see what the debugger can do?

Or do you mean that, when %private-bar is _already removed_ from the
package, we can fix the problem when using a debugger but external
code using it won't provide the required restart to substitute the
value we need?

> > Do you know how commonly this %private-symbol convention
> > is used?
>
> Having not worked on many Lisp projects that other people wrote, I
> don't know. Perhaps someone else can help out here. You can be pretty
> sure, though, that people will know what you mean if you do it.

I have noticed that SBCL warns when using a variable like *foo*
without having previously declared it as special.  But since this is
not a _conventionally_ used method, I guess there won't be a warning
but as you said, I guess I can depend on other lispers to know what I
mean and from now on, so will I.

> > Can I say that all defconstants (related to a module) would
> > go into one single file?
> >
> > Would the defparameters and defvars go in this same file?
> > Or would they be coupled with the module file where the
> > classes etc are defined?
>
> Myself, I put the def{constant,var,parameter}s inside the file with all
> of the other definitions in their module. Since Common Lisp has some
> (not a lot, but some) restrictions regarding what order you declare
> things, I generally separate declarations by their types, and put them
> in the following order: macros, classes,
> constants/variables/parameters, generics, functions/methods. The only
> things I put in a separate file are the package definitions, which all
> go in one file, 'packages.lisp'.

In the time between my question and now, I have discovered EVAL-WHEN.
Originally I didn't know it existed so I thought it would be necessary
to keep all constants in a separate file so that re-evaluating the
file would not throw up so many errors about attempting to redifine a
DEFCONSTANT

Your way is similar to the conventions that Thomas A. Russ has defined
in
his reply, except he keeps some of them in different files.  But for
the most part your order is the same.

> Of course, these aren't hard-and-fast rules. They're just the way I do
> it, and they have drawbacks as well as advantages.

I can see the immediate advantages.  What drawbacks are there?

Thanks for the elaborate answers.  I will use them.

Vijay Lakshminarayanan
From: Mikalai
Subject: Re: organizing lisp code
Date: 
Message-ID: <1149355780.358609.215920@c74g2000cwc.googlegroups.com>
···········@gmail.com wrote:
--- snip ---
> In the time between my question and now, I have discovered EVAL-WHEN.
> Originally I didn't know it existed so I thought it would be necessary
> to keep all constants in a separate file so that re-evaluating the
> file would not throw up so many errors about attempting to redifine a
> DEFCONSTANT

Do not forget that you may use REQUIRE, not just LOAD. In file that you
require, put a provide option. Required file will be loaded only once!
From: ···········@gmail.com
Subject: Re: organizing lisp code
Date: 
Message-ID: <1149436100.508330.133770@i39g2000cwa.googlegroups.com>
Mikalai wrote:
> ···········@gmail.com wrote:
> --- snip ---
> > In the time between my question and now, I have discovered EVAL-WHEN.
> > Originally I didn't know it existed so I thought it would be necessary
> > to keep all constants in a separate file so that re-evaluating the
> > file would not throw up so many errors about attempting to redifine a
> > DEFCONSTANT
>
> Do not forget that you may use REQUIRE, not just LOAD. In file that you
> require, put a provide option. Required file will be loaded only once!

That is another thing I have learnt now :-) I've seen the same in
several emacs lisp packages but never in CL.  However, CLtL2 appears
to favour usage of DEFPACKAGE over REQUIRE and PROVIDE:

 +--------------------------------------------------------------+
 | X3J13 voted  in January 1989  (REQUIRE-PATHNAME-DEFAULTS) to |
 | eliminate the entire module facility from the language; that |
 | is,  the variable  *modules* and  the functions  provide and |
 | require are  deleted. X3J13 commented  that the file-loading |
 | feature of  require is not portable, and  that the remaining |
 | functionality is  easily implemented  by user code.  (I will |
 | add  that in  any case  the specification  of require  is so |
 | vague  that  different implementations  are  likely to  have |
 | differing behavior.)                                         |
 +--------------------------------------------------------------+

because after that note, in the "Examples" section, Guy L. Steele
shows how to do a package definition using DEFPACKAGE that was defined
with REQUIRE and PROVIDE.[*]

Hyperspec also says:

 +---------------------------------------------------+
 | The functions provide and require are deprecated. |
 +---------------------------------------------------+

[*] However, he also says this about DEFPACKAGE:

 +--------------------------------------------------------------+
 | Conclusion:  defpackage goes  a long  way, but  it certainly |
 | doesn't solve all the  possible problems of package and file |
 | management.  Neither  did   require  and  provide.   Perhaps |
 | further  experimentation will  yield  facilities appropriate |
 | for future standardization.                                  |
 +--------------------------------------------------------------+

Is it recommended to use REQUIRE and PROVIDE?  Are they used often?

Thanks
Vijay Lakshminarayanan
From: Rob Warnock
Subject: Re: organizing lisp code
Date: 
Message-ID: <I82dnf3pmaN86h7ZnZ2dnUVZ_omdnZ2d@speakeasy.net>
<···········@gmail.com> wrote:
+---------------
| Mikalai wrote:
| > Do not forget that you may use REQUIRE, not just LOAD. In file that you
| > require, put a provide option. Required file will be loaded only once!
| 
| That is another thing I have learnt now :-) I've seen the same in
| several emacs lisp packages but never in CL.  However, CLtL2 appears
| to favour usage of DEFPACKAGE over REQUIRE and PROVIDE:
+---------------

But remember that CLtL2 is *NOT* normative, nor was it ever approved
by ANSI, and in fact it occasionally differs in significant ways from
what ended up in the actual standard.

+---------------
| Hyperspec also says:
|  | The functions provide and require are deprecated. |
+---------------

But note that the CLHS *also* says:

    1.8 Deprecated Language Features
    Deprecated language features are not expected to appear in
    future Common Lisp tandards, but are required to be implemented
    for conformance with this standard; see Section 1.5.1.1
    (Required Language Features).

Common Lisp has *LOTS* of deprecated language features that people
depend on working properly in any decent implementation.  ;-}  ;-}

+---------------
| Is it recommended to use REQUIRE and PROVIDE?
+---------------

Recommended by whom? In what circumstances? They're required (pardon
the pun) to be there, so you can depend on them being there, but their
behavior is under-specified and/or implementation-dependent [which is
the main reason they were deprecated], so you might have to wrap some
feature tests around them for portability across CL implementations.

+---------------
| Are they used often?
+---------------

I can't speak for others, but I use them a lot in interactive (REPL)
sessions to suck in locally-written small libs. But for starting up
large and/or long-running applications, I tend to use a mixture of
REQUIRE and ASDF, with more of the latter the bigger the app is.

Note that SBCL has blurred the line further by extending REQUIRE
so that (REQUIRE :FOO) does (ASDF:OPERATE 'ASDF:LOAD-OP :FOO) if
there is a "foo.asd" visible via the ASDF:*CENTRAL-REGISTRY*.

In short, REQURE/PROVIDE are perfectly fine to use, if their
limitations don't get in the way for you. If I were writing
libraries intended for use by others, I'd supply an ASDF wrapper.


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: ···········@gmail.com
Subject: Re: organizing lisp code
Date: 
Message-ID: <1149557432.876905.296950@j55g2000cwa.googlegroups.com>
Rob Warnock wrote:
> <···········@gmail.com> wrote:
> +---------------
> | Mikalai wrote:
> | > Do not forget that you may use REQUIRE, not just LOAD. In file that you
> | > require, put a provide option. Required file will be loaded only once!
> |
> | That is another thing I have learnt now :-) I've seen the same in
> | several emacs lisp packages but never in CL.  However, CLtL2 appears
> | to favour usage of DEFPACKAGE over REQUIRE and PROVIDE:
> +---------------
>
> But remember that CLtL2 is *NOT* normative, nor was it ever approved
> by ANSI, and in fact it occasionally differs in significant ways from
> what ended up in the actual standard.
>
> +---------------
> | Hyperspec also says:
> |  | The functions provide and require are deprecated. |
> +---------------
>
> But note that the CLHS *also* says:
>
>     1.8 Deprecated Language Features
>     Deprecated language features are not expected to appear in
>     future Common Lisp tandards, but are required to be implemented
>     for conformance with this standard; see Section 1.5.1.1
>     (Required Language Features).
>
> Common Lisp has *LOTS* of deprecated language features that people
> depend on working properly in any decent implementation.  ;-}  ;-}
>
> +---------------
> | Is it recommended to use REQUIRE and PROVIDE?
> +---------------
>
> Recommended by whom? In what circumstances? They're required (pardon
> the pun) to be there, so you can depend on them being there, but their
> behavior is under-specified and/or implementation-dependent [which is
> the main reason they were deprecated], so you might have to wrap some
> feature tests around them for portability across CL implementations.
>
> +---------------
> | Are they used often?
> +---------------
>
> I can't speak for others, but I use them a lot in interactive (REPL)
> sessions to suck in locally-written small libs. But for starting up
> large and/or long-running applications, I tend to use a mixture of
> REQUIRE and ASDF, with more of the latter the bigger the app is.
>
> Note that SBCL has blurred the line further by extending REQUIRE
> so that (REQUIRE :FOO) does (ASDF:OPERATE 'ASDF:LOAD-OP :FOO) if
> there is a "foo.asd" visible via the ASDF:*CENTRAL-REGISTRY*.
>
> In short, REQURE/PROVIDE are perfectly fine to use, if their
> limitations don't get in the way for you. If I were writing
> libraries intended for use by others, I'd supply an ASDF wrapper.

Thank you for the elaborate explanations Rob.

Vijay Lakshminarayanan
From: ···········@gmail.com
Subject: Re: organizing lisp code
Date: 
Message-ID: <1149372924.677873.195980@h76g2000cwa.googlegroups.com>
···········@gmail.com wrote:
> ···········@gmail.com wrote:
> > I don't think there are many people who think that encapsulation is a
> > bad idea. What the author of PCL is probably referring to is the fact
> > that Common Lisp doesn't actively *prevent* you from breaking
> > encapsulation, which is a good thing, since it makes it possible to do
> > more things with metaprogramming (source-level debuggers, smart
> > editors, etc.) That's "good" encapsulation-breaking. "Bad"
> > encapsulation-breaking (which should be avoided) can be characterized
> > by this rule of thumb: it is any kind of breakage will result in the
> > ceased functioning of the code doing the breaking when the code it is
> > breaking into changes. A debugger won't stop working if someone removes
> > %private-bar from the frobble library, but any code that calls
> > %private-bar probably will break.
>
> I don't understand what you mean by a debugger not breaking.  Should I
> refer to the (in my case) SBCL manual to see what the debugger can do?
>
> Or do you mean that, when %private-bar is _already removed_ from the
> package, we can fix the problem when using a debugger but external
> code using it won't provide the required restart to substitute the
> value we need?

First, I apologize for the poor clarity of my explanation. Let me try
again.

The Lisp debugger is written in Lisp, and isn't "special" in any way.
So, for instance, when you evaluate (step (foo bar baz)), the STEP
macro does some special processing on the expression to emulate an
interactive EVAL. You could, in theory, write your own debugger using
(mostly) standard Lisp operators.

In a sense, the debugger is breaking encapsulation: it's looking inside
the code you're debugging and making decisions based on what's in
there. But, it's not "bad" encapsulation-breaking, because the debugger
will continue to function if you change the internals of FOO.
From: ···········@gmail.com
Subject: Re: organizing lisp code
Date: 
Message-ID: <1149433684.831746.242070@i39g2000cwa.googlegroups.com>
···········@gmail.com wrote:
> ···········@gmail.com wrote:
> > ···········@gmail.com wrote:
> > > I don't think there are many people who think that encapsulation is a
> > > bad idea. What the author of PCL is probably referring to is the fact
> > > that Common Lisp doesn't actively *prevent* you from breaking
> > > encapsulation, which is a good thing, since it makes it possible to do
> > > more things with metaprogramming (source-level debuggers, smart
> > > editors, etc.) That's "good" encapsulation-breaking. "Bad"
> > > encapsulation-breaking (which should be avoided) can be characterized
> > > by this rule of thumb: it is any kind of breakage will result in the
> > > ceased functioning of the code doing the breaking when the code it is
> > > breaking into changes. A debugger won't stop working if someone removes
> > > %private-bar from the frobble library, but any code that calls
> > > %private-bar probably will break.
> >
> > I don't understand what you mean by a debugger not breaking.  Should I
> > refer to the (in my case) SBCL manual to see what the debugger can do?
> >
> > Or do you mean that, when %private-bar is _already removed_ from the
> > package, we can fix the problem when using a debugger but external
> > code using it won't provide the required restart to substitute the
> > value we need?
>
> First, I apologize for the poor clarity of my explanation. Let me try
> again.
>
> The Lisp debugger is written in Lisp, and isn't "special" in any way.
> So, for instance, when you evaluate (step (foo bar baz)), the STEP
> macro does some special processing on the expression to emulate an
> interactive EVAL. You could, in theory, write your own debugger using
> (mostly) standard Lisp operators.
>
> In a sense, the debugger is breaking encapsulation: it's looking inside
> the code you're debugging and making decisions based on what's in
> there. But, it's not "bad" encapsulation-breaking, because the debugger
> will continue to function if you change the internals of FOO.

Yes I understand now.  Thank you for elaborating.

Cheers
Vijay Lakshminarayanan
From: Pascal Costanza
Subject: Re: organizing lisp code
Date: 
Message-ID: <4e3s03F1d2pqnU1@individual.net>
···········@gmail.com wrote:
> Hi
> 
> Is there any convention for organizing lisp code into different files?

No, there is no convention that you can mechanically follow.

> I'm most used to Java where every class goes into it's own files (with
> a few exceptions, of course) but that seems overkill in lisp where a
> defclass would probably be just a few lines at most.

In Java, a file can also contain several classes, even without inner 
classes. It indeed makes sense to put helper classes together with the 
classes they help in the same file even in Java.

So the guideline in Common Lisp is this: Think about what code belongs 
together because of what it does, not in what construct it is expressed.

As an analogy: In a book, you also don't start a new chapter for each 
sentence, and there is also no convention how to organize your text into 
chapters.

> In another post, it was discussed that the defgeneric's be in defined
> on their own since in CLOS methods don't belong to the classes
> themselved.

Again: Organize the code according to its meaning, not its structural 
properties. Sometimes it is better to define methods close to the 
classes on which they are specialized, and sometimes its better to 
collect them all together.

Recall what you use the Visitor pattern for in languages like Java: You 
use the Visitor pattern so that you can group functionality together. 
Whenever you would use the Visitor pattern, just group all the methods 
for a generic function together (and forget about double dispatch and 
all the ugly details of Visitors ;).


Pascal

-- 
3rd European Lisp Workshop
July 3 - Nantes, France - co-located with ECOOP 2006
http://lisp-ecoop06.bknr.net/
From: ···········@gmail.com
Subject: Re: organizing lisp code
Date: 
Message-ID: <1149043680.365722.64390@i39g2000cwa.googlegroups.com>
Pascal Costanza wrote:
> ···········@gmail.com wrote:
> > Hi
> >
> > Is there any convention for organizing lisp code into different files?
>
> No, there is no convention that you can mechanically follow.
>
> > I'm most used to Java where every class goes into it's own files (with
> > a few exceptions, of course) but that seems overkill in lisp where a
> > defclass would probably be just a few lines at most.
>
> In Java, a file can also contain several classes, even without inner
> classes. It indeed makes sense to put helper classes together with the
> classes they help in the same file even in Java.

True but typically each java file has one class and the
inner classes or other classes in that file are used as
helpers for the main class (after which the file itself is
named).  Basically, the only `symbols' that are exported are
the class after which the file is named and it's public
symbols and other classes are not.  This is not the case in
Lisp.

> So the guideline in Common Lisp is this: Think about what code belongs
> together because of what it does, not in what construct it is expressed.
>
> As an analogy: In a book, you also don't start a new chapter for each
> sentence, and there is also no convention how to organize your text into
> chapters.

I don't understand this analogy right now.  But I shall not
question it either.  You obviously know what you are talking
about.  Hopefully someday I will understand the Lisp world
better and come back to you with my opinion of this.

> > In another post, it was discussed that the defgeneric's be in defined
> > on their own since in CLOS methods don't belong to the classes
> > themselved.
>
> Again: Organize the code according to its meaning, not its structural
> properties. Sometimes it is better to define methods close to the
> classes on which they are specialized, and sometimes its better to
> collect them all together.

All right.  I am not used to the Lisp way yet.  It is
unusual to be allowed to do just about anything in the
language.  Right from starting variables with numbers (I
don't use this but it is cool nonetheless :-) to variables
using the same name as a function to complete freedom in
CLOS and the like.  And then you have macros of course.

> Recall what you use the Visitor pattern for in languages like Java: You
> use the Visitor pattern so that you can group functionality together.
> Whenever you would use the Visitor pattern, just group all the methods
> for a generic function together (and forget about double dispatch and
> all the ugly details of Visitors ;).

Actually I've never used the Visitor pattern in Java.  I've
seen a toy C compiler written in Python use it and I've seen
Peter Seibel's speech at Google.  Scary.

Thanks for the help!

Cheers
Vijay Lakshminarayanan
From: Pascal Costanza
Subject: Re: organizing lisp code
Date: 
Message-ID: <4e4sgrF1ck764U1@individual.net>
···········@gmail.com wrote:

> Actually I've never used the Visitor pattern in Java.  I've
> seen a toy C compiler written in Python use it and I've seen
> Peter Seibel's speech at Google.  Scary.

:)

-- 
3rd European Lisp Workshop
July 3 - Nantes, France - co-located with ECOOP 2006
http://lisp-ecoop06.bknr.net/
From: Thomas A. Russ
Subject: Re: organizing lisp code
Date: 
Message-ID: <ymiwtc1g481.fsf@sevak.isi.edu>
···········@gmail.com writes:

> Hi
> 
> Is there any convention for organizing lisp code into different files?

Well, the breakdown that I normally use is as follows:

1.  A file with the DEFPACKAGE definition(s) for a system.  This is
    really useful to have in a separate file so it can get loaded first.

2.  A file with general purpose MACRO definitions.  Again, this needs to
    loadable before any uses of the macros or bad things will happen.
    Macros that are local to a single file can go there (see below).

3.  Similarly for general purpose STRUCTURE definitions.  For local
    defstructs, they can also go in the local file.

4.  For large systems with many classes, I will often put the class
    definitions together in one file.  Very few methods, generally
    only print functions go into this file.

5.  Other files are organized around major chunks of functionality.
    Each file has a set of methods and functions that hang together
    in some modular sense.  There can be any number of these files.



6.  Finally, if the system is very large with substantial subsystems,
    I will divide it again using directories.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: ···········@gmail.com
Subject: Re: organizing lisp code
Date: 
Message-ID: <1149187084.916505.237250@f6g2000cwb.googlegroups.com>
Thomas A. Russ wrote:
> > Is there any convention for organizing lisp code into different files?
>
> Well, the breakdown that I normally use is as follows:
>
> 1.  A file with the DEFPACKAGE definition(s) for a system.  This is
>     really useful to have in a separate file so it can get loaded first.

Doesn't this make it difficult for distributing and maintaining the
different packages?  Also if you are using some version control for
the code, wouldn't it be easier to have them all in a separate
repository?

I admit that these are preconceived ideas I have.  I guess the
implicit question I have is: how are lisp packages packaged?

If, as Pascal Costanza said, the answer is "you'll know in time", I'm
all right with such an answer.  I plan to stay here for a while :)

> 2.  A file with general purpose MACRO definitions.  Again, this needs to
>     loadable before any uses of the macros or bad things will happen.
>     Macros that are local to a single file can go there (see below).
>
> 3.  Similarly for general purpose STRUCTURE definitions.  For local
>     defstructs, they can also go in the local file.
>
> 4.  For large systems with many classes, I will often put the class
>     definitions together in one file.  Very few methods, generally
>     only print functions go into this file.
>
> 5.  Other files are organized around major chunks of functionality.
>     Each file has a set of methods and functions that hang together
>     in some modular sense.  There can be any number of these files.

These divisions seem akin to a C-style partitioning (inasfar as the
comparison can be made).  Where the structures go into header files
and functions into C files.

> 6.  Finally, if the system is very large with substantial subsystems,
>     I will divide it again using directories.

Thank you for the assistance.  I hope the time isn't too far away when
I'm
using step 6.  Of course the better way would be to participate in a
free software project in Lisp.

Vijay Lakshminarayanan
From: Thomas A. Russ
Subject: Re: organizing lisp code
Date: 
Message-ID: <ymifyiofsh2.fsf@sevak.isi.edu>
···········@gmail.com writes:

> Thomas A. Russ wrote:
> > > Is there any convention for organizing lisp code into different files?
> >
> > Well, the breakdown that I normally use is as follows:
> >
> > 1.  A file with the DEFPACKAGE definition(s) for a system.  This is
> >     really useful to have in a separate file so it can get loaded first.
> 
> Doesn't this make it difficult for distributing and maintaining the
> different packages?  Also if you are using some version control for
> the code, wouldn't it be easier to have them all in a separate
> repository?

No.  First of all remember that in Lisp "PACKAGE" is the term for a
symbol namespace.  It has nothing to do with a set of files that form a
system or module.

So, having all of the package definition forms in a single file for a
system (a set of related files that provide some functionality) makes it
simpler to maintain the namespace, and make sure that the proper
inheritance, importing and shadowing of symbols is done.

This really wants to be in a separate file, because the state of the
package definitions affects the reader, and the reader is used to ingest
the other source files for the compiler.

So you really want to have the package file loaded first before loading
(and thus reading) any other files that use the packages defined in the
package file.

> I admit that these are preconceived ideas I have.  I guess the
> implicit question I have is: how are lisp packages packaged?

They are defined by DEFPACKAGE.

Generally a small, simple system will have only a single package.  More
complicated systems may have additional packages for specific modules.




-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: ···········@gmail.com
Subject: Re: organizing lisp code
Date: 
Message-ID: <1149218244.568400.295150@g10g2000cwb.googlegroups.com>
Thomas A. Russ wrote:
> ···········@gmail.com writes:
>
> > Thomas A. Russ wrote:
> > > > Is there any convention for organizing lisp code into different files?
> > >
> > > Well, the breakdown that I normally use is as follows:
> > >
> > > 1.  A file with the DEFPACKAGE definition(s) for a system.  This is
> > >     really useful to have in a separate file so it can get loaded first.
> >
> > Doesn't this make it difficult for distributing and maintaining the
> > different packages?  Also if you are using some version control for
> > the code, wouldn't it be easier to have them all in a separate
> > repository?
>
> No.  First of all remember that in Lisp "PACKAGE" is the term for a
> symbol namespace.  It has nothing to do with a set of files that form a
> system or module.

Yes.  Thanks for reminding me of that.  I know that is what packages
are for but it keeps slipping my mind.  (I used to have a similar
problem with emacs reference to window and frame, but am used to it
now.  The transition will take place in Lisp.)

> So, having all of the package definition forms in a single file for a
> system (a set of related files that provide some functionality) makes it
> simpler to maintain the namespace, and make sure that the proper
> inheritance, importing and shadowing of symbols is done.

> > > 1.  A file with the DEFPACKAGE definition(s) for a system.  This is
> > >     really useful to have in a separate file so it can get loaded first.

I misunderstood what you said

> > > 1.  A file with the DEFPACKAGE definition(s) for a system.  This is
> > >     really useful to have in a separate file so it can get loaded first.

I understood the plural `definitions' to mean there would be more than
one DEFPACKAGE form in a file, hence my confusion.

> This really wants to be in a separate file, because the state of the
> package definitions affects the reader, and the reader is used to ingest
> the other source files for the compiler.
>
> So you really want to have the package file loaded first before loading
> (and thus reading) any other files that use the packages defined in the
> package file.

Yes, I have experienced this myself.  All files belonging to a package
begin with (in-package #:foo-package) and for the reader to understand
what's going on the package must have been predefined.

>
> > I admit that these are preconceived ideas I have.  I guess the
> > implicit question I have is: how are lisp packages packaged?
>
> They are defined by DEFPACKAGE.

I already knew this :) but I what I'd written earlier was misleading.
I forgot about why packages exist in Lisp and went back to my Java way
of thinking.

Thank you Thomas.

Vijay Lakshminarayanan
From: Thomas A. Russ
Subject: Re: organizing lisp code
Date: 
Message-ID: <ymiwtbzebyo.fsf@sevak.isi.edu>
···········@gmail.com writes:
> > > > 1.  A file with the DEFPACKAGE definition(s) for a system.  This is
> > > >     really useful to have in a separate file so it can get loaded first.
> 
> I understood the plural `definitions' to mean there would be more than
> one DEFPACKAGE form in a file, hence my confusion.

There sometimes are more than one DEFPACKAGE form in a file.  This is
generally only true for fairly large systems, but it isn't completely
uncommon, particularly if there are substantial subsystems.

Portable AllegroServe is one example of a generally available system
that has multiple packages used for its implementation.  CL-HTTP is
another.

For example, one might have something like

(defpackage my-system-internal ....)
(defpackage my-system :export ...)
(defpackage my-system-user :use (:common-lisp :my-system) ...)



-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: ···········@gmail.com
Subject: Re: organizing lisp code
Date: 
Message-ID: <1149437139.861716.51370@y43g2000cwc.googlegroups.com>
Thomas A. Russ wrote:
> There sometimes are more than one DEFPACKAGE form in a file.  This is
> generally only true for fairly large systems, but it isn't completely
> uncommon, particularly if there are substantial subsystems.
>
> Portable AllegroServe is one example of a generally available system
> that has multiple packages used for its implementation.  CL-HTTP is
> another.

I had a look at this and indeed cl-http/server/package.lisp lists 12
packages or so.

> For example, one might have something like
>
> (defpackage my-system-internal ....)
> (defpackage my-system :export ...)
> (defpackage my-system-user :use (:common-lisp :my-system) ...)

This is a most elucidating example.  Thank you :-)

Thank you for your comments and examples, Thomas.

Vijay Lakshminarayanan
From: ······@corporate-world.lisp.de
Subject: Re: organizing lisp code
Date: 
Message-ID: <1149461012.122027.96840@h76g2000cwa.googlegroups.com>
···········@gmail.com schrieb:

> Hi
>
> Is there any convention for organizing lisp code into different files?
> I'm most used to Java where every class goes into it's own files (with
> a few exceptions, of course) but that seems overkill in lisp where a
> defclass would probably be just a few lines at most.
>
> In another post, it was discussed that the defgeneric's be in defined
> on their own since in CLOS methods don't belong to the classes
> themselved.
>
> Any suggestions welcome.
>
> Thanks
> Vijay Lakshminarayanan

Usually the management of the sources is done by a system facility.
I think Kent Pitman had a paper on this. Several system do
exist and each vendor provides his own. Most SYSTEM facilities
will dictate atleast some source organization.

http://www.nhplace.com/kent/Papers/Large-Systems.html

For LARGER software I would do:

create a directory for the whole software.

Subsystems go into subdirectories.

Don't put any source code into the top-level directory.
The top-level directory should give you a quick overview
what the modules are and point you to a few important
files (like README or INSTALL).

Setup a logical pathname for the system directory.

(setf (logical-pathname-translations "FOO")
    '(("foo:doc;*.text" "docserver:/docs/*.text")
     ("foo:src;*.lisp" "srcserver:/foo/src/*.lisp")
     ("foo:src;mod1;*.lisp" "srcserver:/foo/src/mod1/*.lisp")
     ("foo:bin;*.fasl" "srcserver:/foo/bin/lisp1/*.fasl")
     ("foo:bin;*.fsl" "srcserver:/foo/bin/lisp2/*.fsl")))

Yours might be very different.

Sometimes you want to create subdirectories for different compiled
files for different compilers or architectures.

Earlier for large systems it was not uncommon to
put parts of the files on different machines (depending
for example on the disk space or other criteria).
Often there was one machine on the network
for documentation archives or one for multimedia files.


Setup a package declaration for each subsystem.

Define the software in layered subsystem. For example
define a common subsystem for all modules that provides
portability (like WWW-UTILS in CL-HTTP).

For any subsystem create special files for system dependent
code. Make sure that you separate portable from system
dependent code and name the file, so you can see
from the name that this is special code for some
machine, implementation, or other.

Setup a SYSTEM declaration using the logical pathname.
On the Lisp Machine I'll put a pointer to this into
a central registry directory. Source code should
always be named by logical pathnames, that makes
moving the code easier and you can also have shorter
names. In CL-HTTP (ed "http:examples;configuration.lisp")
will always edit the configuration file, regardless on which
system or architecture you are.
If your SYSTEM has a central registry use it. Often
you an use REQUIRE to load the stuff. LOAD-SYSTEM
or COMPILE-SYSTEM might also be useful.

The SYSTEM declaration has declarations for each subsystem.

Try to model the dependencies as much as needed. For example
you might want to force compilation of some files when a
file containing macros has be recompiled. Subsystem
may depend on other systems.

Each subsystem might have its own package and its own package
declaration
file.

Some systems (like CLIM) have also a way to define 'protocols'.

Sometimes it might be useful to put all class definitions in one file.

Don't use more than one IN-PACKAGE per file. You can use more, but that
would be bad style.

Add all additional files to the system declaration (fonts, images,
sounds, text, examples,
doc, ...).

Write any necessary extensions to the system facility (for example to
build
products) and make them available in the same spirit as the other
tools (LOAD-SYSTEM, COMPILE-SYSTEM, ...).

For some self-written macros you want to add source-recording
functionality.
So that meta-. on a symbol will do the right thing.

Don't use too many small files. I find larger files quite okay -
especially
if the IDE gives you some navigation help. Most of the time I navigate
over the code with meta-. and similar tools. Many small files create
just a multitude of editor buffers - I find that not very convenient.

Most of the time I put some 'logical' functionality in one file. For
example
if you implement the basic FTP protocol, much of it can go into
one file. Classes, generic functions, methods and variables.

Most Implementations don't need a DEFGENERIC, since DEFMETHOD
generates the basic generic function if needed. Sometimes you
want to add options to the generic function, then you need a
defgeneric.
On the Lisp machine you also needed a defgeneric, if you later
wanted to change the generic function.

Some Lisp systems have browsers for these software systems and
have special editor commands for these systems. For example
you can constraint the search to a specific system.