Discussion:
exporting package symbols
(too old to reply)
David Richards
2020-03-04 02:25:25 UTC
Permalink
Hello all -
I have looked at two different packages (cl-ppcre and alexandria) and noticed a difference in the way each exports its functions and symbols. The Alexandria package uses #:<symbol name> while the cl-ppcre package exports with a simple :<symbol name>. The hyperspec says:

"#: introduces an uninterned symbol whose name is symbol-name. Every time this syntax is encountered, a distinct uninterned symbol is created."

But if you're introducing a new package aren't your symbols already uninterned within your package? Can someone explain the advantage of using one over the other?
Thanks!
Dave R.
Madhu
2020-03-04 05:30:19 UTC
Permalink
Post by David Richards
I have looked at two different packages (cl-ppcre and alexandria) and
noticed a difference in the way each exports its functions and
symbols. The Alexandria package uses #:<symbol name> while the
cl-ppcre package exports with a simple :<symbol name>. The hyperspec
"#: introduces an uninterned symbol whose name is symbol-name. Every
time this syntax is encountered, a distinct uninterned symbol is
created."
I think I've seen statements to the effect that #: "just works" with
allegro's "modern mode" and also happens to work with other lisps.
I've never used allegro's "modern mode" myself
Post by David Richards
But if you're introducing a new package aren't your symbols already
uninterned within your package? Can someone explain the advantage of
using one over the other?
My preferences are the same as CL defaults. Always case insensitive and
default case is uppercase. Consequently I prefer to see
(defpackage "CL" (:use "FOO") (:export "BAR"))
where the beautiful uppercase strings are syntax-highlighted as strings
with emply """ quotes indicating they are strings.

But I think some people are prejudiced against seeing uppercase and
others are offended by string syntax though I cannot really commiserate
with them
Vladimir Sedach
2020-03-04 05:44:00 UTC
Permalink
Symbols like :foobar are keywords. Any time the reader sees one, it
is interned in the KEYWORD package if it is not already there:

--8<---------------cut here---------------start------------->8---
CL-USER> (find-symbol "FOOBAR" "KEYWORD")
NIL
NIL
CL-USER> :foobar
:FOOBAR
CL-USER> (find-symbol "FOOBAR" "KEYWORD")
:FOOBAR
:EXTERNAL
--8<---------------cut here---------------end--------------->8---

They also point to themselves as values. This makes it convenient to
use them as constants and enums. The only problem is they stick
around and take up memory. #: symbols do not, so that is the
preferred way to specify the package export list.

But that can also be done with strings:
(defpackage "ABC" (:export "XYZ"))

Why bother with #:foobar instead of "FOOBAR"? To let the reader
handle the possible case conversion options.

https://cliki.net/Case%20sensitivity

Not a problem for case sensitive implementations like Allegro modern
and CLISP with the -modern option.
--
Vladimir Sedach
Software engineering services in Los Angeles https://oneofus.la
David Richards
2020-03-04 11:59:28 UTC
Permalink
Post by Vladimir Sedach
Symbols like :foobar are keywords. Any time the reader sees one, it
--8<---------------cut here---------------start------------->8---
CL-USER> (find-symbol "FOOBAR" "KEYWORD")
NIL
NIL
CL-USER> :foobar
:FOOBAR
CL-USER> (find-symbol "FOOBAR" "KEYWORD")
:FOOBAR
:EXTERNAL
--8<---------------cut here---------------end--------------->8---
They also point to themselves as values. This makes it convenient to
use them as constants and enums. The only problem is they stick
around and take up memory. #: symbols do not, so that is the
preferred way to specify the package export list.
(defpackage "ABC" (:export "XYZ"))
Why bother with #:foobar instead of "FOOBAR"? To let the reader
handle the possible case conversion options.
https://cliki.net/Case%20sensitivity
Not a problem for case sensitive implementations like Allegro modern
and CLISP with the -modern option.
--
Vladimir Sedach
Software engineering services in Los Angeles https://oneofus.la
Good info - thank you very much!
t***@google.com
2020-03-05 17:25:43 UTC
Permalink
Post by David Richards
Hello all -
...
Post by David Richards
But if you're introducing a new package aren't your symbols already uninterned within your package? Can someone explain the advantage of using one over the other?
The question of keyword vs uninterned symbols is answered by others.

But when you are introducing a new package, the DEFPACKAGE form will often be
evaluated in a different package. (Perhaps CL-USER)?. In that case, if you used
interned symbols, you would be adding symbols into that package, when all you
really care about is getting the proper symbol-name for DEFPACKAGE to use.

Using symbols allows the reader case settings to intervene. You just need to be
sure that those settings are the same for all places the DEFPACKAGE form is
used in a single system, including already compiled files.
Ralph Schleicher
2020-03-07 18:11:34 UTC
Permalink
Post by David Richards
But if you're introducing a new package aren't your symbols already
uninterned within your package? Can someone explain the advantage of
using one over the other?
Within your package, you can also say

(export '*foo*)
(defvar *foo* t)

(export 'bar)
(defun bar ()
nil)

Then you don't have to maintain your package's export list.
--
Ralph

9969 days of Linux experience.
Nelson Alexandra
2020-03-08 18:14:11 UTC
Permalink
You might also find this resource helpful:
http://gigamonkeys.com/book/programming-in-the-large-packages-and-symbols.html
Loading...