[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.lisp

Package names

Blake McBride

5/30/2016 5:19:00 PM

Hi,

In terms of package name types that may be used in defpackage /
in-package / provide, I've seen strings, symbols, and keyword symbols.
Is there a best, and if so, why?

Thank you.

Blake McBride
7 Answers

Pascal J. Bourguignon

5/30/2016 6:27:00 PM

0

Blake McBride <blake1024@gmail.com> writes:

> Hi,
>
> In terms of package name types that may be used in defpackage /
> in-package / provide, I've seen strings, symbols, and keyword
> symbols. Is there a best, and if so, why?

Package names, and symbol names, are STRINGS (case sensitive).


Those operators take STRING DESIGNATORS.

(deftype string-designator () (or string symbol character))




(defpackage #\C (:use "CL") (:export :foo #:bar "Baz"))
(list 'c:foo 'c:bar 'c:|Baz|)
--> (c:foo c:bar c:|Baz|)

The problem with symbols is that you don't know what name they have
unless you also know the setting of (readtable-case *readtable*) (and it
helps to know also *print-case*).

The advantage of using strings, is that you specify precisely the case
of each character.

The inconvenient of using strings, is that depending on the current
setting of (readtable-case *readtable*) you may have to escape or not
the symbol syntax to be able to read it.

The inconvenient of using symbols, is that you assume that you are using
the same (readtable-case *readtable*) to read the defpackage form, and
to read the symbol later.


Furthermore, using symbols have additionnal problems; you have the
choice between 3 problems:

- use normal symbol, interned in the current package, and therefore
"poluting" it. For example:

(defpackage foo (:use) (:export foo))
(use-package foo) --> error.
> Debug: Using #<Package "FOO"> in #<Package "COMMON-LISP-USER">
> would cause name conflicts with symbols already present in that package:
> foo foo:foo

- use kerwords, interned in the KEYWORD package, and therefore
"poluting" it. The polution aspect is less a problem since you can
consider that all the keywords (the infinite number of them) already
exist, but they're never garbage collected, so this fills the memory
for nothing.

- use uninterned symbols, which can be acceptable, but is ugly:

#:foo

instead of:

"FOO"


Using characters had the problem that there was only 96 characters.
Nowadays, there are about one million of them, but the problem is that
most of them are hard to type. So you have the choice between those two
problems:

- define a package with a name that collides with another package (if
you use an upper case letter in the standard character set, that gives
place for only 26 packages)

- define packages with a 1-character name, but that is hard or
impossible to type on your keyboard. Also, can you distinguish A:X
and А:X ?



I prefer to use strings.




For PROVIDE, there's also the difficulty that the module name (a case
sensitive string), is used to access an external resource, possibly
using the module name as a physical pathname component, and therefore
you have to write them with a specific, implementation and platform
dependent case. It would be inconvenient to count again on
(readtable-case *readtable*), to be the right thing to use.

--
__Pascal Bourguignon__ http://www.informat...
â??The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.� -- Carl Bass CEO Autodesk

Blake McBride

5/30/2016 8:13:00 PM

0

On 05/30/2016 01:27 PM, Pascal J. Bourguignon wrote:
> .....
>
> I prefer to use strings.
>
>

Thanks for the explanation and your preference (which I choose to
consider "best practice"). I knew much of what you stated, but having
it set out completely by (what I consider) an expert, is very helpful.

Thank you.

Blake McBride


Kaz Kylheku

5/30/2016 11:58:00 PM

0

On 2016-05-30, Blake McBride <blake1024@gmail.com> wrote:
> Hi,
>
> In terms of package name types that may be used in defpackage /
> in-package / provide, I've seen strings, symbols, and keyword symbols.
> Is there a best, and if so, why?

Your list is not round without the mention of #:uninterned symbols
which some Lisp programmers favor.

I vote for keywords. Strings are noisy, due to quotes, and with the
default read-tables of Common Lisp, "THEY SHOUT".

Symbols require quoting when passed to functions and no quoting
when passed to macros, whereas keywords are always just :whatever
in every context.

Uninterned carry a #: dongle *and* require quoting. The justification
for using them is that they don't pollute memory, since there is no
global package which hangs on to them. If the Lisp system can
garbage-collect symbols that were referenced in top-level forms that can
never be re-executed (without reloading the module), then you have a
savings in memory by using uinterned symbols.

Kaz Kylheku

5/31/2016 12:02:00 AM

0

On 2016-05-30, Pascal J. Bourguignon <pjb@informatimago.com> wrote:
> (defpackage #\C (:use "CL") (:export :foo #:bar "Baz"))
> (list 'c:foo 'c:bar 'c:|Baz|)
> --> (c:foo c:bar c:|Baz|)
>
> The problem with symbols is that you don't know what name they have
> unless you also know the setting of (readtable-case *readtable*) (and it
> helps to know also *print-case*).
>
> The advantage of using strings, is that you specify precisely the case
> of each character.

But if you don't know the readtable-case, you don't know what symbol
tokens those strings correspond to.

At some point, code is going to appear in these files which uses the symbols
via symbol tokens, not strings.

You know that the precise name of a symbol given as "FOO" is "FOO", but
is that FOO or foo? Or does it matter? Can it be Foo, or must it be one
of FOO or foo, or either?

Of course, you always know that it's |FOO| and \F\O\O. :)

So i.e. you don't escape from assumptions about the readtable
case by using strings.

Barry Margolin

5/31/2016 1:07:00 AM

0

In article <20160530165019.530@kylheku.com>,
Kaz Kylheku <545-066-4921@kylheku.com> wrote:

> On 2016-05-30, Blake McBride <blake1024@gmail.com> wrote:
> > Hi,
> >
> > In terms of package name types that may be used in defpackage /
> > in-package / provide, I've seen strings, symbols, and keyword symbols.
> > Is there a best, and if so, why?
>
> Your list is not round without the mention of #:uninterned symbols
> which some Lisp programmers favor.
>
> I vote for keywords. Strings are noisy, due to quotes, and with the
> default read-tables of Common Lisp, "THEY SHOUT".
>
> Symbols require quoting when passed to functions and no quoting
> when passed to macros, whereas keywords are always just :whatever
> in every context.
>
> Uninterned carry a #: dongle *and* require quoting. The justification
> for using them is that they don't pollute memory, since there is no
> global package which hangs on to them. If the Lisp system can
> garbage-collect symbols that were referenced in top-level forms that can
> never be re-executed (without reloading the module), then you have a
> savings in memory by using uinterned symbols.

Bare package names are most often used in code that's only executed at
compile time, so you don't generally have to worry about them polluting
memory.

And even if they do, what's the big deal? How many packages will there
typically be in any Lisp environment, a few dozen? This isn't the
1970's, when we had to worry about every byte of memory.

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***

Pascal J. Bourguignon

5/31/2016 6:21:00 PM

0

Kaz Kylheku <545-066-4921@kylheku.com> writes:

> On 2016-05-30, Pascal J. Bourguignon <pjb@informatimago.com> wrote:
>> (defpackage #\C (:use "CL") (:export :foo #:bar "Baz"))
>> (list 'c:foo 'c:bar 'c:|Baz|)
>> --> (c:foo c:bar c:|Baz|)
>>
>> The problem with symbols is that you don't know what name they have
>> unless you also know the setting of (readtable-case *readtable*) (and it
>> helps to know also *print-case*).
>>
>> The advantage of using strings, is that you specify precisely the case
>> of each character.
>
> But if you don't know the readtable-case, you don't know what symbol
> tokens those strings correspond to.

Ah, but I do! Because my source files start with:

(|CL|:|EVAL-WHEN| (:|COMPILE-TOPLEVEL| :|LOAD-TOPLEVEL| :|EXECUTE|)
(|CL|:|SETF| |CL|:|*READTABLE*| (|CL|:|COPY-READTABLE| |CL|:|NIL|)))
(in-package "THE-PACKAGE-OF-THIS-FILE")



--
__Pascal Bourguignon__ http://www.informat...
â??The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.� -- Carl Bass CEO Autodesk

Kaz Kylheku

5/31/2016 7:00:00 PM

0

On 2016-05-31, Pascal J. Bourguignon <pjb@informatimago.com> wrote:
> Kaz Kylheku <545-066-4921@kylheku.com> writes:
>
>> On 2016-05-30, Pascal J. Bourguignon <pjb@informatimago.com> wrote:
>>> (defpackage #\C (:use "CL") (:export :foo #:bar "Baz"))
>>> (list 'c:foo 'c:bar 'c:|Baz|)
>>> --> (c:foo c:bar c:|Baz|)
>>>
>>> The problem with symbols is that you don't know what name they have
>>> unless you also know the setting of (readtable-case *readtable*) (and it
>>> helps to know also *print-case*).
>>>
>>> The advantage of using strings, is that you specify precisely the case
>>> of each character.
>>
>> But if you don't know the readtable-case, you don't know what symbol
>> tokens those strings correspond to.
>
> Ah, but I do! Because my source files start with:
>
> (|CL|:|EVAL-WHEN| (:|COMPILE-TOPLEVEL| :|LOAD-TOPLEVEL| :|EXECUTE|)
> (|CL|:|SETF| |CL|:|*READTABLE*| (|CL|:|COPY-READTABLE| |CL|:|NIL|)))
> (in-package "THE-PACKAGE-OF-THIS-FILE")

But after this header, the behavior of unescaped symbol tokens is now
predictable; continued use of strings doesn't have that cited advantage
over symbols.