From: Slava Akhmechet
Subject: Exporting generic functions, the etiquette.
Date: 
Message-ID: <878xd5mffb.fsf@gmail.com>
I'm in the middle of organizing a library that makes heavy use of
generic functions. I ran into the following question.

There are a few methods meant to be called by the clients of the
library. There are many other generic functions/methods that are
designed to be called by the library internally, but the client can
specialize them to get customized behavior. Even though the client may
specialize them, he's never expected to call them himself.

Should such generic functions be exported from the library or should
the client be expected to access them via :: or 'in-package'?

-- 
Regards,
Slava Akhmechet.

From: Zach Beane
Subject: Re: Exporting generic functions, the etiquette.
Date: 
Message-ID: <m3zm5ldzr3.fsf@unnamed.xach.com>
Slava Akhmechet <·········@gmail.com> writes:

> I'm in the middle of organizing a library that makes heavy use of
> generic functions. I ran into the following question.
> 
> There are a few methods meant to be called by the clients of the
> library. There are many other generic functions/methods that are
> designed to be called by the library internally, but the client can
> specialize them to get customized behavior. Even though the client may
> specialize them, he's never expected to call them himself.
> 
> Should such generic functions be exported from the library or should
> the client be expected to access them via :: or 'in-package'?

If the user may write methods that are part of the generic function,
the name of the generic function should be exported. 

You write "Should such generic functions be exported...". Watch out
with the terminology; I find it helpful to always keep in mind that
/functions/ are not exported, /symbols/ are exported that /name/
functions (or parameters, or classes, etc). And in the case of
functions like (SETF FOO), you're actually only exporting part of full
name of the function.

Zach
From: Slava Akhmechet
Subject: Re: Exporting generic functions, the etiquette.
Date: 
Message-ID: <873b3dmcm4.fsf@gmail.com>
Zach Beane <····@xach.com> writes:

> If the user may write methods that are part of the generic function,
> the name of the generic function should be exported. 
Thanks. This is essentially what I do, I just thought it's a little
dirty to export names of functions people aren't expected to call.

> You write "Should such generic functions be exported...". Watch out
> with the terminology; I find it helpful to always keep in mind that
> /functions/ are not exported, /symbols/ are exported that /name/
> functions (or parameters, or classes, etc).
Yes, thank you.

-- 
Regards,
Slava Akhmechet.
From: Drew Crampsie
Subject: Re: Exporting generic functions, the etiquette.
Date: 
Message-ID: <87fy7dw3vw.fsf@osiris.tech.coop>
Slava Akhmechet <·········@gmail.com> writes:

> Zach Beane <····@xach.com> writes:
>
>> If the user may write methods that are part of the generic function,
>> the name of the generic function should be exported.
 
> Thanks. This is essentially what I do, I just thought it's a little
> dirty to export names of functions people aren't expected to call.

You need not export them from the same package of course. Think of
CLOS exported from COMMON-LISP vs. the MOP exported from various
implementation defined packages (sb-mop etc).

hth,

drewc



>
>> You write "Should such generic functions be exported...". Watch out
>> with the terminology; I find it helpful to always keep in mind that
>> /functions/ are not exported, /symbols/ are exported that /name/
>> functions (or parameters, or classes, etc).
> Yes, thank you.
>
> -- 
> Regards,
> Slava Akhmechet.

-- 
Posted via a free Usenet account from http://www.teranews.com
From: Barry Margolin
Subject: Re: Exporting generic functions, the etiquette.
Date: 
Message-ID: <barmar-7F6F05.21370206042007@comcast.dca.giganews.com>
In article <··············@gmail.com>,
 Slava Akhmechet <·········@gmail.com> wrote:

> Zach Beane <····@xach.com> writes:
> 
> > If the user may write methods that are part of the generic function,
> > the name of the generic function should be exported. 
> Thanks. This is essentially what I do, I just thought it's a little
> dirty to export names of functions people aren't expected to call.

You mean like INITIALIZE-INSTANCE, UPDATE-INSTANCE-FOR-REDEFINED-CLASS, 
PRINT-OBJECT, etc.?

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Slava Akhmechet
Subject: Re: Exporting generic functions, the etiquette.
Date: 
Message-ID: <876488x2td.fsf@gmail.com>
For example, a generic function for rendering objects into HTML rows
that internally calls another generic function to render each
cell. The user of the library can customize cell rendering by adding
specialized methods, but he's never expect to call the cell rendering
function himself.

-- 
Regards,
Slava Akhmechet.
From: Zach Beane
Subject: Re: Exporting generic functions, the etiquette.
Date: 
Message-ID: <m3r6qwe6hx.fsf@unnamed.xach.com>
Slava Akhmechet <·········@gmail.com> writes:

> For example, a generic function for rendering objects into HTML rows
> that internally calls another generic function to render each
> cell. The user of the library can customize cell rendering by adding
> specialized methods, but he's never expect to call the cell rendering
> function himself.

The functions Barry lists are part of the standard, and fall into
exactly this situation. It's kosher.

Zach
From: Vassil Nikolov
Subject: Re: Exporting generic functions, the etiquette.
Date: 
Message-ID: <m34pnrlqi7.fsf@localhost.localdomain>
On Sat, 07 Apr 2007 03:48:13 GMT, Slava Akhmechet <·········@gmail.com> said:

| For example, a generic function for rendering objects into HTML rows
| that internally calls another generic function to render each
| cell. The user of the library can customize cell rendering by adding
| specialized methods, but he's never expect to call the cell rendering
| function himself.

  A (system of) generic function(s) defines/is/represents a protocol.
  The symbols that are part of a public protocol should be exported,
  regardless of the particular role they play in the protocol.

  ---Vassil.


-- 
The truly good code is the obviously correct code.
From: Slava Akhmechet
Subject: Re: Exporting generic functions, the etiquette.
Date: 
Message-ID: <87irc9kvgz.fsf@gmail.com>
Zach Beane <····@xach.com> writes:

Another question, is it customary to break up export lists based on
files? For example, I have a file with 'defpackage' and then five more
files with code in that package. It's not very comfortable for me to
put the export list in one place (where 'defpackage' is), I'd prefer
to break it up and call 'export' manually in each file. Is this
something people normally do?

-- 
Regards,
Slava Akhmechet.
From: Thomas A. Russ
Subject: Re: Exporting generic functions, the etiquette.
Date: 
Message-ID: <ymilkh50y6e.fsf@sevak.isi.edu>
Slava Akhmechet <·········@gmail.com> writes:

> Zach Beane <····@xach.com> writes:
> 
> Another question, is it customary to break up export lists based on
> files? For example, I have a file with 'defpackage' and then five more
> files with code in that package. It's not very comfortable for me to
> put the export list in one place (where 'defpackage' is), I'd prefer
> to break it up and call 'export' manually in each file. Is this
> something people normally do?

It's largely a matter of style.

Although I think the current consensus frowns on putting the export
lists all over the place when making use of DEFPACKAGE.  It is nice
to have everything in a single place from the point of view of being the
user, and of having the interface documented.

It makes writing the code a bit more cumbersome, since you do have to
update the central defpackage file instead of staying where you are, but
that's why Emacs has multiple buffers and frames.  ;p

It is also generally considered better to make the user of the package's
life a bit easier than the writer of the package -- since one hopes for
many more users than writers.

But, as you point out, the constructs are there, so you can use them if
you feel this makes your development better or easier to do.

I've even seen code where the exports are written individually for the
symbols naming the functions to be exported....

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Slava Akhmechet
Subject: Re: Exporting generic functions, the etiquette.
Date: 
Message-ID: <87y7l4vo6x.fsf@gmail.com>
Hmm, that makes sense. I think I'll go with separate exports. To make
the users' life easier I'll simply generate html documentation :)

-- 
Regards,
Slava Akhmechet.
From: Pascal Bourguignon
Subject: Re: Exporting generic functions, the etiquette.
Date: 
Message-ID: <874pnqq5hv.fsf@voyager.informatimago.com>
Slava Akhmechet <·········@gmail.com> writes:

> Hmm, that makes sense. I think I'll go with separate exports.

You'll find it's a style SBCL doesn't like...


-- 
__Pascal Bourguignon__
http://www.informatimago.com
http://pjb.ogamita.org
From: Zach Beane
Subject: Re: Exporting generic functions, the etiquette.
Date: 
Message-ID: <m3veg8e6je.fsf@unnamed.xach.com>
Slava Akhmechet <·········@gmail.com> writes:

> Zach Beane <····@xach.com> writes:
> 
> Another question, is it customary to break up export lists based on
> files? For example, I have a file with 'defpackage' and then five more
> files with code in that package. It's not very comfortable for me to
> put the export list in one place (where 'defpackage' is), I'd prefer
> to break it up and call 'export' manually in each file. Is this
> something people normally do?

Opinions vary, but I prefer explicit and complete export lists in the
package's DEFPACKAGE form. Scattering EXPORTs around (or incorporating
EXPORT into macrology) means I can't be sure until I load the system
what parts of the interface will be available.

Excellent documentation trumps a complete export list, though. If the
docs are good and thorough, I may never refer to the defpackage form.

Zach
From: Pascal Bourguignon
Subject: Re: Exporting generic functions, the etiquette.
Date: 
Message-ID: <87zm5ioqma.fsf@voyager.informatimago.com>
Slava Akhmechet <·········@gmail.com> writes:

> I'm in the middle of organizing a library that makes heavy use of
> generic functions. I ran into the following question.
>
> There are a few methods meant to be called by the clients of the
> library. There are many other generic functions/methods that are
> designed to be called by the library internally, but the client can
> specialize them to get customized behavior. Even though the client may
> specialize them, he's never expected to call them himself.
>
> Should such generic functions be exported from the library or should
> the client be expected to access them via :: or 'in-package'?

If it's really that important, you could export them from different packages:

(defpackage "P-IMPLEMENTATION"
  (:use "CL")
  (:export "YOU-SHOULD-SPECIALIZE-ME"  
           "CLIENTS-CAN-CALL-ME"))

(defpackage "P-USER"
  (:use "CL" "P-IMPLEMENTATION")
  (:export "CLIENT-CAN-CALL-ME"))

(defpackage "P-SPECIALIZER"
  (:use "CL" "P-IMPLEMENTATION")
  (:export "YOU-SHOULD-SPECIALIZE-ME"))



Then the various kind of users can find the symbols thru the specific
package.

(defpackage "MY-APP")
  (:use "CL"))
(in-package "MY-APP")

(defmethod p-specializer:you-should-specialize-me ((self my-type)) 
   (i-specialize (call-next-method)))

(defun main ()
  (p-specializer:client-can-call-me))



-- 
__Pascal Bourguignon__
http://www.informatimago.com
http://pjb.ogamita.org
From: Slava Akhmechet
Subject: Re: Exporting generic functions, the etiquette.
Date: 
Message-ID: <87y7l2srey.fsf@gmail.com>
Hmm, ok. Why do you say SBCL doesn't like separate exports? So far it
seems to work well for me.

-- 
Regards,
Slava Akhmechet.
From: Pascal Bourguignon
Subject: Re: Exporting generic functions, the etiquette.
Date: 
Message-ID: <87ps66im1o.fsf@voyager.informatimago.com>
Slava Akhmechet <·········@gmail.com> writes:

> Hmm, ok. Why do you say SBCL doesn't like separate exports? So far it
> seems to work well for me.

SBCL issues a warning when it executes a defpackage that doesn't lists
all the symbols that are already exported by an existing package.

Now, perhaps I shouldn't try to load files before compiling them.


* (cat "/tmp/e.lisp")

(defpackage "EXAMPLE"
    (:use "COMMON-LISP")
    (:export "SOME-BASE-STUFF"))
(in-package "EXAMPLE")

(defun some-base-stuff ()
  'some-base-stuff)

(defun something-more ()
    'something-more)

(export 'something-more)


* (load "/tmp/e.lisp")

T
* (compile-file "/tmp/e.lisp")

; compiling file "/tmp/e.lisp" (written 15 APR 2007 01:13:02 AM):
; compiling (DEFPACKAGE "EXAMPLE" ...); 
; caught WARNING:
;   EXAMPLE also exports the following symbols:
;     (EXAMPLE:SOMETHING-MORE)
;   See also:
;     The ANSI Standard, Macro DEFPACKAGE

; compiling (IN-PACKAGE "EXAMPLE")
; compiling (DEFUN SOME-BASE-STUFF ...)
; compiling (DEFUN SOMETHING-MORE ...)
; compiling (EXPORT (QUOTE SOMETHING-MORE)); 
; compilation unit finished
;   caught 1 WARNING condition


; /tmp/e.fasl written
; compilation finished in 0:00:00
#P"/tmp/e.fasl"
T
T
* 

-- 
__Pascal Bourguignon__
http://www.informatimago.com
http://pjb.ogamita.org
From: Slava Akhmechet
Subject: Re: Exporting generic functions, the etiquette.
Date: 
Message-ID: <87odlqilkf.fsf@gmail.com>
Pascal Bourguignon <···@informatimago.com> writes:

> Now, perhaps I shouldn't try to load files before compiling them.
I see. I generally use asdf for this so it's usually never a problem.

-- 
Regards,
Slava Akhmechet.
From: John Thingstad
Subject: Re: Exporting generic functions, the etiquette.
Date: 
Message-ID: <op.tqtm6ueqpqzri1@pandora.upc.no>
On Sun, 15 Apr 2007 01:16:51 +0200, Pascal Bourguignon  
<···@informatimago.com> wrote:

>
> T
> * (compile-file "/tmp/e.lisp")
>
> ; compiling file "/tmp/e.lisp" (written 15 APR 2007 01:13:02 AM):
> ; compiling (DEFPACKAGE "EXAMPLE" ...);
> ; caught WARNING:
> ;   EXAMPLE also exports the following symbols:
> ;     (EXAMPLE:SOMETHING-MORE)
> ;   See also:
> ;     The ANSI Standard, Macro DEFPACKAGE
>
> ; compiling (IN-PACKAGE "EXAMPLE")
> ; compiling (DEFUN SOME-BASE-STUFF ...)
> ; compiling (DEFUN SOMETHING-MORE ...)
> ; compiling (EXPORT (QUOTE SOMETHING-MORE));
> ; compilation unit finished
> ;   caught 1 WARNING condition
>
>
> ; /tmp/e.fasl written
> ; compilation finished in 0:00:00
> #P"/tmp/e.fasl"
> T
> T
> *
>

Why use (export ..) instead of (defpackage .. (:export ..))?
Seem to rememeber it being mentioned in CLTL2 as being present only for
compatabilty with the standard of CLTL1.
An older form superseded by defpackage. That is why it is a warning.
It wants you to move the declaration up to the defpackage part.

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
From: Slava Akhmechet
Subject: Re: Exporting generic functions, the etiquette.
Date: 
Message-ID: <87mz19bi42.fsf@gmail.com>
"John Thingstad" <··············@chello.no> writes:

> Why use (export ..) instead of (defpackage .. (:export ..))?
It's just an annoyance for the developer. Since defpackage is in a
single place but symbols are scattered over many files after a while
it becomes really hard to manage.

-- 
Regards,
Slava Akhmechet.
From: John Thingstad
Subject: Re: Exporting generic functions, the etiquette.
Date: 
Message-ID: <op.tqudl4hlpqzri1@pandora.upc.no>
On Sun, 15 Apr 2007 20:35:58 +0200, Slava Akhmechet <·········@gmail.com>  
wrote:

> "John Thingstad" <··············@chello.no> writes:
>
>> Why use (export ..) instead of (defpackage .. (:export ..))?
> It's just an annoyance for the developer. Since defpackage is in a
> single place but symbols are scattered over many files after a while
> it becomes really hard to manage.
>

Now imagine you want to use the package.
If you have export statements scattered all over the place you have
a very hard time finding the exported functions. (you grep for it)
If they are in the package you see it at a glance.
I use a package.lisp for all my package declarations of a library.
Yes it means changing files ever so often, but in the end I find
the defpackage form seems like the one with the less hassle.

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
From: Slava Akhmechet
Subject: Re: Exporting generic functions, the etiquette.
Date: 
Message-ID: <87zm595f8m.fsf@gmail.com>
"John Thingstad" <··············@chello.no> writes:

> Now imagine you want to use the package.
> If you have export statements scattered all over the place you have
> a very hard time finding the exported functions.
I use tinaa which lets me immediately see all exported symbols along
with any documentation that's available. No need for grepping :)

-- 
Regards,
Slava Akhmechet.
From: Timofei Shatrov
Subject: Re: Exporting generic functions, the etiquette.
Date: 
Message-ID: <46230c9e.78533685@news.readfreenews.net>
On Mon, 16 Apr 2007 00:34:31 GMT, Slava Akhmechet <·········@gmail.com> tried to
confuse everyone with this message:

>"John Thingstad" <··············@chello.no> writes:
>
>> Now imagine you want to use the package.
>> If you have export statements scattered all over the place you have
>> a very hard time finding the exported functions.
>I use tinaa which lets me immediately see all exported symbols along
>with any documentation that's available. No need for grepping :)
>

Or, one may type "package-name:" in SLIME and press TAB...

-- 
|Don't believe this - you're not worthless              ,gr---------.ru
|It's us against millions and we can't take them all... |  ue     il   |
|But we can take them on!                               |     @ma      |
|                       (A Wilhelm Scream - The Rip)    |______________|
From: Luke  Gorrie
Subject: Re: Exporting generic functions, the etiquette.
Date: 
Message-ID: <1176808400.791211.320880@d57g2000hsg.googlegroups.com>
> Or, one may type "package-name:" inSLIMEand press TAB...

Or use `slime-apropos-package' (C-c C-d C-p) for a hyperlinked API
overview.
From: Tim Bradshaw
Subject: Re: Exporting generic functions, the etiquette.
Date: 
Message-ID: <1176811682.349875.89480@n59g2000hsh.googlegroups.com>
On Apr 16, 6:42 am, ····@mail.ru (Timofei Shatrov) wrote:

> Or, one may type "package-name:" in SLIME and press TAB...

Ah yes, the old excuse: "I don't need to learn to design programs
because I have such a good environment that all that boring stuff
doesn't matter.  What kind of file would you prefer, we have a
selection.
From: Tim Bradshaw
Subject: Re: Exporting generic functions, the etiquette.
Date: 
Message-ID: <1176811496.988077.94330@q75g2000hsh.googlegroups.com>
On Apr 15, 7:35 pm, Slava Akhmechet <·········@gmail.com> wrote:

> It's just an annoyance for the developer. Since defpackage is in a
> single place but symbols are scattered over many files after a while
> it becomes really hard to manage.

It's an annoyance in approximately the same sense that avoiding GO in
general code is an annoyance.  Developers who find this difficult need
their hands filed off.
From: Pascal Bourguignon
Subject: Re: Exporting generic functions, the etiquette.
Date: 
Message-ID: <87ejmlhsio.fsf@voyager.informatimago.com>
"John Thingstad" <··············@chello.no> writes:

> On Sun, 15 Apr 2007 01:16:51 +0200, Pascal Bourguignon
> <···@informatimago.com> wrote:
>
>>
>> T
>> * (compile-file "/tmp/e.lisp")
>>
>> ; compiling file "/tmp/e.lisp" (written 15 APR 2007 01:13:02 AM):
>> ; compiling (DEFPACKAGE "EXAMPLE" ...);
>> ; caught WARNING:
>> ;   EXAMPLE also exports the following symbols:
>> ;     (EXAMPLE:SOMETHING-MORE)
>> ;   See also:
>> ;     The ANSI Standard, Macro DEFPACKAGE
>>
>> ; compiling (IN-PACKAGE "EXAMPLE")
>> ; compiling (DEFUN SOME-BASE-STUFF ...)
>> ; compiling (DEFUN SOMETHING-MORE ...)
>> ; compiling (EXPORT (QUOTE SOMETHING-MORE));
>> ; compilation unit finished
>> ;   caught 1 WARNING condition
>>
>>
>> ; /tmp/e.fasl written
>> ; compilation finished in 0:00:00
>> #P"/tmp/e.fasl"
>> T
>> T
>> *
>>
>
> Why use (export ..) instead of (defpackage .. (:export ..))?
> Seem to rememeber it being mentioned in CLTL2 as being present only for
> compatabilty with the standard of CLTL1.
> An older form superseded by defpackage. That is why it is a warning.
> It wants you to move the declaration up to the defpackage part.

Which is good when you have a small static program or library.

But the use case I have in mind is that of a package that contains and
export different interactive utilities depending on the circumstances
(eg depending on the implementation it runs in).

Also, if the source of the package is one file, there's not much
problem in putting all the export in the defpackage form.  But if you
have several source files for the same package, it's easier to have
one export list per file.


-- 
__Pascal Bourguignon__