Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Importing into KEYWORD.

127 views
Skip to first unread message

Pascal J. Bourguignon

unread,
Apr 2, 2012, 5:46:11 PM4/2/12
to

Not all symbols present in the KEYWORD package are keywords!
Or should they?


# Importing a symbol from CL-USER into KEYWORD:

$ clall -r '(progn (makunbound (quote cl-user::toto))
(unintern :toto "KEYWORD")
(import (quote cl-user::toto) "KEYWORD")
(boundp (find-symbol "TOTO" "KEYWORD")))'

Armed Bear Common Lisp --> NIL
International Allegro CL Free Express Edition --> NIL
Clozure Common Lisp --> T
CLISP --> NIL
CMU Common Lisp --> NIL
SBCL --> NIL


# Importing a homeless symbol-USER into KEYWORD:

$ clall -r '(progn (unintern :toto "KEYWORD")
(import (make-symbol "TOTO") "KEYWORD")
(boundp (find-symbol "TOTO" "KEYWORD")))'

Armed Bear Common Lisp --> NIL
International Allegro CL Free Express Edition --> NIL
Clozure Common Lisp --> T
CLISP --> T
CMU Common Lisp --> NIL
SBCL --> NIL


CLHS INTERN says that when a symbol is INTERNED into KEYWORD, then it is
automatically bound to itself, marked as a constant, and exported from
the KEYWORD package.

11.1.2.3.1 Interning a Symbol in the KEYWORD Package

The KEYWORD package is treated differently than other packages in
that special actions are taken when a symbol is interned in it. In
particular, when a symbol is interned in the KEYWORD package, it is
automatically made to be an external symbol and is automatically
made to be a constant variable with itself as a value.


On the other hand, CLHS IMPORT says:

"If any symbol to be imported has no home package (i.e.,
(symbol-package symbol) => nil), import sets the home package of
the symbol to package."

not saying what happens in the contrary case, but one may assume that in
that case import does not set the home package of the imported symbol.
And nothing's said about making them external or constants.


So, my questions are:

- is it specified that the above form should return NIL?
- is it specified that the above form should return T?
- are both behaviors conforming?



IMO, the behavior of ccl is the correct one, importing a symbol into
KEYWORD should behave like interning it, but I feel that it's not
specified.


On the other hand, it might be useful to be able to define keywords that
are not bound to themselves:

$ clall -r '(progn (defconstant cl-user::haha :foo)
(import (quote cl-user::haha) "KEYWORD")
(symbol-value (find-symbol "HAHA" "KEYWORD")))'

Armed Bear Common Lisp --> :FOO
International Allegro CL Free Express Edition --> :FOO
Clozure Common Lisp --> HAHA
CLISP --> :FOO
CMU Common Lisp --> :FOO
SBCL --> :FOO



--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.

Tim Bradshaw

unread,
Apr 2, 2012, 6:37:07 PM4/2/12
to
On 2012-04-02 22:46:11 +0100, Pascal J. Bourguignon said:

> IMO, the behavior of ccl is the correct one, importing a symbol into
> KEYWORD should behave like interning it, but I feel that it's not
> specified.

Well, there is some confusion here. interning is not something which
is done to symbols, it is something which takes a string and finds or
creates a symbol whose name is the string, or a copy of it.

What you are doing is importing a preexisting symbol into a package,
which is a different thing. I think it's clear that import sets the
home package of the symbol to be the package it is being imported into
iff it does not already have a home package.

I think the right thing is probably that:
- interning a string into the keyword package should set the value of
the symbol created appropriately;
- importing a symbol with a preexisting home package into the keyword
package should not set the value;
- importing a symbol with no home package and which has no value into
the keyword package just might bind it, but I think probably should not.

Pascal J. Bourguignon

unread,
Apr 2, 2012, 7:07:46 PM4/2/12
to
This has been mentionned in there too:
http://groups.google.com/group/comp.lang.lisp/browse_frm/thread/aeeaa3e31b5e01d3/0fd49d0516e09000?lnk=gst&q=import+keyword#0fd49d0516e09000



Notice that in ansi-test:


(deftest keyword.1
(do-symbols (s "KEYWORD" t)
(unless (keywordp s)
(return (list s nil))))
t)

expects all symbols in KEYWORD to be KEYWORDP, ie. to have
their SYMBOL-PACKAGE be KEYWORD.



(deftest keyword.3
(do-symbols (s "KEYWORD" t)
(cond
((not (boundp s))
(return (list s "NOT-BOUND")))
((not (eqt s (symbol-value s)))
(return (list s (symbol-value s))))))
t)

expects all symbols in KEYWORD to be bound to themselves.


Given your understanding of IMPORT, this may not be the case.
But it looks like it is an expectation.
On the other hand, the majority of implementors agree with you.


Perhaps the tests should be modified to expect those properties only
from symbols in KEYWORD that are KEYWORDP?

Tim Bradshaw

unread,
Apr 3, 2012, 3:00:01 AM4/3/12
to
On 2012-04-03 00:07:46 +0100, Pascal J. Bourguignon said:

> Given your understanding of IMPORT, this may not be the case.
> But it looks like it is an expectation.

Well, I think it would be basically extremely weird to have symbols
present in KEYWORD whose home package was not KEYWORD, which I think is
the same as keywordp? Although you can construct such things (and
other monsters such as symbols present in KEYWORD which have *no* home
package) I think most bets are off.

I think I would be happy with an interpretation (what's the word for
the masses of semi-canonical interpretation which grow up around sacred
texts? We need that) which said something like "the consequences are
undefined if a symbol is present in KEYWORD which is not keywordp and
which is not bound to itself and ...".

Barry Margolin

unread,
Apr 3, 2012, 10:22:02 AM4/3/12
to
In article <jle75h$79t$1...@dont-email.me>, Tim Bradshaw <t...@tfeb.org>
wrote:

> On 2012-04-03 00:07:46 +0100, Pascal J. Bourguignon said:
>
> > Given your understanding of IMPORT, this may not be the case.
> > But it looks like it is an expectation.
>
> Well, I think it would be basically extremely weird to have symbols
> present in KEYWORD whose home package was not KEYWORD, which I think is
> the same as keywordp? Although you can construct such things (and
> other monsters such as symbols present in KEYWORD which have *no* home
> package) I think most bets are off.

It's extremely weird to IMPORT symbols into KEYWORD in the first place,
or to INTERN them explicitly (rather than letting the reader do it
automatically when it sees keywords). The keyword package has a special
role, and the only reason it can be accessed using the normal package
functions is because we wanted to minimize the number of kludges.

Can anyone offer a good reason why you would ever INTERN or IMPORT
functions into KEYWORD?

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

Pascal J. Bourguignon

unread,
Apr 3, 2012, 10:57:39 AM4/3/12
to
I'd be as glad if we decided that IMPORT into the keyword package is
non-conforming.

Notice that INTERN is described in terms of "entering a symbol into the
package [as an internal or external symbol]", while IMPORT says "import
adds symbol or symbols to the internals of package" and 11.1.2.3.1 only
talks about interning the symbol.

So it seems that what's specified is that import doesn't necessarily
make a symbol a keyword (it sets the symbol-package only of homeless
symbols), and that it doesn't make them constants bound to themselves,
and I notice now that it doesn't make them external either. On the
other hand, the :keyword syntax interns a symbol in the keyword package
be it external or not, so when you use it, you may get an internal
symbols, an unbound symbol, and if you evaluate it, a different value.
If you have imported symbols in KEYWORD, you should better quote your
keywords!



So what's currently specified is that:

[pjb@kuiper :0 ~]$ cat keyword-test.lisp

(defun full-keyword-p (object)
(and (symbolp object)
(eq (symbol-package object) (find-package :keyword))
#|ie.|# (keywordp object)
(boundp object)
(eq (symbol-value object) object)
(constantp object)))

(defun keyword-without-constant-value-p (object)
(and (symbolp object)
(eq (symbol-package object) (find-package :keyword))
#|ie.|# (keywordp object)
(not (and (boundp object)
(eq (symbol-value object) object)
(constantp object)))))

(defun not-a-keyword/unbound-p (object)
(and (symbolp object)
(not (eq (symbol-package object) (find-package :keyword)))
#|ie.|# (not (keywordp object))
(not (boundp object))))

(defun not-a-keyword/bound-p (object)
(and (symbolp object)
(not (eq (symbol-package object) (find-package :keyword)))
#|ie.|# (not (keywordp object))
(boundp object)))

(defmacro report (&body body)
`(multiple-value-bind (object name) (progn ,@body)
(let ((before-intern (list (full-keyword-p object)
(keyword-without-constant-value-p object)
(not-a-keyword/unbound-p object)
(not-a-keyword/bound-p object)))
(find-symbol-result (multiple-value-list (find-symbol name :keyword)))
(interned (intern name :keyword))
(after-intern (list (full-keyword-p object)
(keyword-without-constant-value-p object)
(not-a-keyword/unbound-p object)
(not-a-keyword/bound-p object))))
(print (append (list (and (equalp before-intern after-intern)
(eq object interned)))
(list before-intern)
find-symbol-result)))))

(report (unintern ':normal-keyword :keyword)
(let ((object (intern "NORMAL-KEYWORD" :keyword)))
(values object "NORMAL-KEYWORD")))
;; --> (T (T NIL NIL NIL) :NORMAL-KEYWORD :EXTERNAL)

(report (unintern ':homeless-symbol :keyword)
(let ((object (make-symbol "HOMELESS-SYMBOL")))
(import object :keyword)
(values object "HOMELESS-SYMBOL")))
;; --> (T (NIL T NIL NIL) :HOMELESS-SYMBOL :INTERNAL)

(report (unintern ':unbound-symbol :keyword)
(unintern 'cl-user::unbound-symbol :cl-user)
(let ((object (intern "UNBOUND-SYMBOL" :cl-user)))
(makunbound object)
(import object :keyword)
(values object "UNBOUND-SYMBOL")))
;; --> (T (NIL NIL T NIL) COMMON-LISP-USER::UNBOUND-SYMBOL :INTERNAL)

(report
(unintern ':bound-symbol :keyword)
(unintern 'cl-user::bound-symbol :cl-user)
(let ((object (intern "BOUND-SYMBOL" :cl-user)))
(setf (symbol-value object) 42)
(import object :keyword)
(values object "BOUND-SYMBOL")))
;; --> (T (NIL NIL NIL T) COMMON-LISP-USER::BOUND-SYMBOL :INTERNAL)



[pjb@kuiper :0 ~]$ clall '(progn (load "keyword-test.lisp" :verbose nil) (values))' \
'(quote (:normal-keyword :homeless-symbol :unbound-symbol :bound-symbol))'

# Note: you cannot evaluate :unbound-symbol ;-)


Armed Bear Common Lisp:
(T (T NIL NIL NIL) :NORMAL-KEYWORD :EXTERNAL)
(T (NIL T NIL NIL) :HOMELESS-SYMBOL :INTERNAL)
(T (NIL NIL T NIL) COMMON-LISP-USER::UNBOUND-SYMBOL :INTERNAL)
(T (NIL NIL NIL T) COMMON-LISP-USER::BOUND-SYMBOL :INTERNAL)

Armed Bear Common Lisp:
--> (:NORMAL-KEYWORD :HOMELESS-SYMBOL COMMON-LISP-USER::UNBOUND-SYMBOL COMMON-LISP-USER::BOUND-SYMBOL)


International Allegro CL Free Express Edition:
(T (T NIL NIL NIL) :NORMAL-KEYWORD :EXTERNAL)
(T (NIL T NIL NIL) :HOMELESS-SYMBOL :INTERNAL)
(T (NIL NIL T NIL) COMMON-LISP-USER::UNBOUND-SYMBOL :INTERNAL)
(T (NIL NIL NIL T) COMMON-LISP-USER::BOUND-SYMBOL :INTERNAL)

International Allegro CL Free Express Edition:
--> (:NORMAL-KEYWORD :HOMELESS-SYMBOL COMMON-LISP-USER::UNBOUND-SYMBOL COMMON-LISP-USER::BOUND-SYMBOL)


Clozure Common Lisp:
(T (T NIL NIL NIL) :NORMAL-KEYWORD :EXTERNAL)
(T (T NIL NIL NIL) :HOMELESS-SYMBOL :EXTERNAL)
(T (NIL NIL NIL T) COMMON-LISP-USER::UNBOUND-SYMBOL :EXTERNAL)
(T (NIL NIL NIL T) COMMON-LISP-USER::BOUND-SYMBOL :EXTERNAL)

Clozure Common Lisp:
--> (:NORMAL-KEYWORD :HOMELESS-SYMBOL COMMON-LISP-USER::UNBOUND-SYMBOL COMMON-LISP-USER::BOUND-SYMBOL)


CLISP:
(T (T NIL NIL NIL) :NORMAL-KEYWORD :EXTERNAL)
(T (T NIL NIL NIL) :HOMELESS-SYMBOL :EXTERNAL)

(T (NIL NIL T NIL) COMMON-LISP-USER::UNBOUND-SYMBOL :EXTERNAL)
(T (NIL NIL NIL T) COMMON-LISP-USER::BOUND-SYMBOL :EXTERNAL)

CLISP:
-->
(:NORMAL-KEYWORD :HOMELESS-SYMBOL COMMON-LISP-USER::UNBOUND-SYMBOL
COMMON-LISP-USER::BOUND-SYMBOL)


CMU Common Lisp:
(T (T NIL NIL NIL) :NORMAL-KEYWORD :EXTERNAL)
(T (NIL T NIL NIL) :HOMELESS-SYMBOL :INTERNAL)
(T (NIL NIL T NIL) COMMON-LISP-USER::UNBOUND-SYMBOL :INTERNAL)
(T (NIL NIL NIL T) COMMON-LISP-USER::BOUND-SYMBOL :INTERNAL)

CMU Common Lisp:
--> (:NORMAL-KEYWORD :HOMELESS-SYMBOL COMMON-LISP-USER::UNBOUND-SYMBOL
COMMON-LISP-USER::BOUND-SYMBOL)


SBCL:
(T (T NIL NIL NIL) :NORMAL-KEYWORD :EXTERNAL)
(T (NIL T NIL NIL) :HOMELESS-SYMBOL :INTERNAL)
(T (NIL NIL T NIL) COMMON-LISP-USER::UNBOUND-SYMBOL :INTERNAL)
(T (NIL NIL NIL T) COMMON-LISP-USER::BOUND-SYMBOL :INTERNAL)

SBCL:
--> (:NORMAL-KEYWORD :HOMELESS-SYMBOL COMMON-LISP-USER::UNBOUND-SYMBOL
COMMON-LISP-USER::BOUND-SYMBOL)

========================================================================


ie. ANSI-TESTs keyword.lsp is entirely wrong, and ccl and clisp need
conformance bug reports.

Tim Bradshaw

unread,
Apr 3, 2012, 11:08:05 AM4/3/12
to
On 2012-04-03 15:22:02 +0100, Barry Margolin said:

> Can anyone offer a good reason why you would ever INTERN or IMPORT
> functions into KEYWORD?

I think it might be reasonable to intern them if, for instance, you
were writing a reader (other than the CL one) or something like that.
But I think then that you might also be expected to do the other
necessary things in that case.

I find it hard to think of a case where you'd want to import a
preexisting symbol.

Pascal J. Bourguignon

unread,
Apr 3, 2012, 11:20:42 AM4/3/12
to
Barry Margolin <bar...@alum.mit.edu> writes:

> In article <jle75h$79t$1...@dont-email.me>, Tim Bradshaw <t...@tfeb.org>
> wrote:
>
>> On 2012-04-03 00:07:46 +0100, Pascal J. Bourguignon said:
>>
>> > Given your understanding of IMPORT, this may not be the case.
>> > But it looks like it is an expectation.
>>
>> Well, I think it would be basically extremely weird to have symbols
>> present in KEYWORD whose home package was not KEYWORD, which I think is
>> the same as keywordp? Although you can construct such things (and
>> other monsters such as symbols present in KEYWORD which have *no* home
>> package) I think most bets are off.
>
> It's extremely weird to IMPORT symbols into KEYWORD in the first place,
> or to INTERN them explicitly (rather than letting the reader do it
> automatically when it sees keywords). The keyword package has a special
> role, and the only reason it can be accessed using the normal package
> functions is because we wanted to minimize the number of kludges.
>
> Can anyone offer a good reason why you would ever INTERN or IMPORT
> functions into KEYWORD?

That's not the question.

If an operation is possible it's possible to use it for profit. As long
as the results are specified deterministically.

I don't say you have to use it, or that it's not a bad idea most of the
time to use it.

Tim Bradshaw

unread,
Apr 3, 2012, 12:17:32 PM4/3/12
to
On 2012-04-03 16:20:42 +0100, Pascal J. Bourguignon said:

> If an operation is possible it's possible to use it for profit. As long
> as the results are specified deterministically.

That's why I would vote for my "undefined behaviour" caveat: if you do
things to KEYWORD yourself it is your job to make sure the results
conform.

Barry Margolin

unread,
Apr 3, 2012, 1:33:01 PM4/3/12
to
In article <jlf7qs$nn6$1...@dont-email.me>, Tim Bradshaw <t...@tfeb.org>
wrote:
That's my thinking, as well. It's such a weird thing to do, I don't see
any need to specify it precisely if no one can come up with a good
reason for it.

Pascal J. Bourguignon

unread,
Apr 3, 2012, 2:28:31 PM4/3/12
to
Sure. The question is conform to what? My conclusion for now is that
the keyword tests in ANSI TEST don't check CLHS conformity.

Tim Bradshaw

unread,
Apr 4, 2012, 5:42:04 AM4/4/12
to
On 2012-04-03 19:28:31 +0100, Pascal J. Bourguignon said:

> Sure. The question is conform to what? My conclusion for now is that
> the keyword tests in ANSI TEST don't check CLHS conformity.

One caveat is that I don't think there is a real way of forcing
something to be a constant without using defconstant, but you want
(constantp '<kw-symbol>) to be true, I think.

So I think my reasoning that I would like to be able to create keyword
symbols programmatically without calling READ (really: I would like to
be able to implement READ) implies that (intern x "KEYWORD") should do
everything needed: bind the symbol, make it a constant etc, because you
can't make it a constant yourself. But that should probably be the
only way of doing it, and in particular I don't think it should be safe
to expect that something like (import (make-symbol x) "KEYWORD") would
work (though I think it should be allowed to work).

However I don't think the spec *says* that intern needs to do all that,
does it? If that's right then I think that (a) it should say that, and
(b) conformity would be testing that that is what happens
(specifically, only testing intern). Is something like this right?

(defun test-keyword-symbol (name)
(declare (type string name))
(let ((kp (find-package "KEYWORD")))
(assert (not (find-symbol name kp)) (name) "symbol named ~S exists" name)
(let ((s (intern name kp)))
(unwind-protect
(and
(eq (symbol-value s) s)
(constantp s)
(multiple-value-bind (ss status) (find-symbol name kp)
(and (eq ss s)
(eq status ':external))))
(unintern s kp)))))


Tim Bradshaw

unread,
Apr 4, 2012, 5:58:55 AM4/4/12
to
On 2012-04-04 10:42:04 +0100, Tim Bradshaw said:
> (defun test-keyword-symbol (name) ...)

Or perhaps this souped-up one (perhaps WJ will find this one day, as it
has good solid LOOP obscurity in it: "with ... and ... with" not "with
... and ... and": this kind of thing makes me like CL almost as much as
Perl, though Perl is still ahead because of trailing conditionals).

(defun test-keyword-symbol (&optional (name (loop with n = (make-string 10)
and ac = (char-code #\A)
with r = (1+ (-
(char-code #\Z)
ac))
for i below 10
do (setf (char n i)
(code-char
(+ (random r) ac)))
finally (return n))))
(declare (type string name))
(let ((kp (find-package "KEYWORD")))
(assert (not (find-symbol name kp)) (name) "symbol named ~S exists" name)
(let ((s (intern name kp)))
(unwind-protect
(values
(and
(eq (symbol-value s) s)
(eq (symbol-package s) kp)
(constantp s)
(multiple-value-bind (ss status) (find-symbol name kp)
(and (eq ss s)
(eq status ':external))))
name)
(unintern s kp)))))


CCL (trunk) and LW 6.1 pass this on OSX.

Pascal J. Bourguignon

unread,
Apr 4, 2012, 8:45:05 AM4/4/12
to
Tim Bradshaw <t...@tfeb.org> writes:

> On 2012-04-03 19:28:31 +0100, Pascal J. Bourguignon said:
>
>> Sure. The question is conform to what? My conclusion for now is that
>> the keyword tests in ANSI TEST don't check CLHS conformity.
>
> One caveat is that I don't think there is a real way of forcing
> something to be a constant without using defconstant, but you want
> (constantp '<kw-symbol>) to be true, I think.
>
> So I think my reasoning that I would like to be able to create keyword
> symbols programmatically without calling READ (really: I would like to
> be able to implement READ) implies that (intern x "KEYWORD") should do
> everything needed: bind the symbol, make it a constant etc, because
> you can't make it a constant yourself.

That's correct.


> But that should probably be the only way of doing it, and in
> particular I don't think it should be safe to expect that something
> like (import (make-symbol x) "KEYWORD") would work (though I think it
> should be allowed to work).

If by "would work" you mean "would make the symbol a keyword", we agree,
as I read it, it's not specified.

> However I don't think the spec *says* that intern needs to do all
> that, does it?

Yes, it does explicitely say that intern needs to do all that.


> If that's right then I think that (a) it should say
> that, and (b) conformity would be testing that that is what happens
> (specifically, only testing intern).


Well import is also specified for the KEYWORD package. So we need to
test that too.


> Is something like this right?
>
> (defun test-keyword-symbol (name)
> (declare (type string name))
> (let ((kp (find-package "KEYWORD")))
> (assert (not (find-symbol name kp)) (name) "symbol named ~S exists" name)
> (let ((s (intern name kp)))
> (unwind-protect
> (and
> (eq (symbol-value s) s)
> (constantp s)
> (multiple-value-bind (ss status) (find-symbol name kp)
> (and (eq ss s)
> (eq status ':external))))
> (unintern s kp)))))

This is right.

See my code for testing IMPORT into KEYWORD.

Pascal J. Bourguignon

unread,
Apr 4, 2012, 8:48:44 AM4/4/12
to
Tim Bradshaw <t...@tfeb.org> writes:

> On 2012-04-04 10:42:04 +0100, Tim Bradshaw said:
>> (defun test-keyword-symbol (name) ...)
>
> Or perhaps this souped-up one (perhaps WJ will find this one day, as
> it has good solid LOOP obscurity in it: "with ... and ... with" not
> "with ... and ... and": this kind of thing makes me like CL almost as
> much as Perl, though Perl is still ahead because of trailing
> conditionals).
>
> (defun test-keyword-symbol (&optional (name (loop with n = (make-string 10)
> and ac = (char-code #\A)
> with r = (1+ (-
> (char-code #\Z)
> ac))
> for i below 10
> do (setf (char n i)
> (code-char
> (+ (random r) ac)))
> finally (return n))))

I would have used lower case letters to reduce the probability of
collision.

With EBCDIC-like encodings you will get non alphanumeric characters in
the symbol name. Which is good for random keywords.

So let's improve on it, and just use (code-char (random
char-code-limit)). But test if the result is characterp, because some
implementation have no character for some unicode codes.

Tim Bradshaw

unread,
Apr 4, 2012, 8:51:22 AM4/4/12
to
On 2012-04-04 13:45:05 +0100, Pascal J. Bourguignon said:

> Well import is also specified for the KEYWORD package. So we need to
> test that too.

It is allowed (in the sense of not being explicitly forbidden) but I
can't see any of the behaviour which you'd want (ie that it should
become external, blah) being specified, so, again, I'd just cover this
by my "undefined behaviour" gloss (or alternatively by a "this is
forbidden" gloss).

Pascal J. Bourguignon

unread,
Apr 4, 2012, 10:08:17 AM4/4/12
to
I can accept that the intend was that the implications of importing
into the keyword package be undefined. In that case the ansi-tests
should still be written defensively against it. Ie. as you do in your
test-keyword-symbol function, not looping over all symbols in the keyword
package.

Tim Bradshaw

unread,
Apr 4, 2012, 10:22:32 AM4/4/12
to
On 2012-04-04 15:08:17 +0100, Pascal J. Bourguignon said:

> In that case the ansi-tests
> should still be written defensively against it.

You mean

(handler-case ...
(nasal-demons ...)
(plague-of-frogs ...)
(spirits-from-the-vasty-deep ...)
(old-ones ...)
(WJ ...))

RG

unread,
Apr 4, 2012, 12:28:16 PM4/4/12
to
In article <jlh51c$1mu$1...@dont-email.me>, Tim Bradshaw <t...@tfeb.org>
wrote:

> On 2012-04-03 19:28:31 +0100, Pascal J. Bourguignon said:
>
> > Sure. The question is conform to what? My conclusion for now is that
> > the keyword tests in ANSI TEST don't check CLHS conformity.
>
> One caveat is that I don't think there is a real way of forcing
> something to be a constant without using defconstant

Note that DEFCONSTANT doesn't force the variable being defined to be a
constant, it just makes the consequences of changing the variable's
value undefined. The variable defined by DEFCONSTANT is only required
to be a constant variable (what a weird concept) in compiled code. In
interactive code, the value of constant variables can change, e.g.:

? (defconstant :x 1)
> Error: Constant :X is already defined with a different value (:X)
> While executing: CCL::DEFINE-CONSTANT, in process Listener(20).
> Type cmd-/ to continue, cmd-. to abort, cmd-\ for a list of available restarts.
> If continued: Redefine :X to have new value 1
> Type :? for other options.
1 >
Invoking restart: Redefine :X to have new value 1
:X
? (list :x)
(1)

rg

WJ

unread,
Apr 4, 2012, 1:05:37 PM4/4/12
to
Guy L. Steele, Jr., July 1989:

I think we may usefully compare the approximate number of pages
in the defining standard or draft standard for several
programming languages:

Common Lisp 1000 or more
COBOL 810
ATLAS 790
Fortran 77 430
PL/I 420
BASIC 360
ADA 340
Fortran 8x 300
C 220
Pascal 120
DIBOL 90
Scheme 50


-----


Brooks and Gabriel 1984, "A Critique of Common Lisp":

Every decision of the committee can be locally rationalized
as the right thing. We believe that the sum of these
decisions, however, has produced something greater than its
parts; an unwieldy, overweight beast, with significant costs
(especially on other than micro-codable personal Lisp
engines) in compiler size and speed, in runtime performance,
in programmer overhead needed to produce efficient programs,
and in intellectual overload for a programmer wishing to be
a proficient COMMON LISP programmer.


-----


Bernard Lang:

Common Lisp did kill Lisp. Period. (just languages take a
long time dying ...) It is to Lisp what C++ is to C. A
monstrosity that totally ignores the basics of language
design, simplicity and orthogonality to begin with.


-----

Gilles Kahn:

To this day I have not forgotten that Common Lisp killed
Lisp, and forced us to abandon a perfectly good system,
LeLisp.

-----


Paul Graham, May 2001:

A hacker's language is terse and hackable. Common Lisp is not.

The good news is, it's not Lisp that sucks, but Common Lisp.

Historically, Lisp has been good at letting hackers have their
way. The political correctness of Common Lisp is an aberration.
Early Lisps let you get your hands on everything.

A really good language should be both clean and dirty:
cleanly designed, with a small core of well understood and
highly orthogonal operators, but dirty in the sense that it
lets hackers have their way with it. C is like this. So were
the early Lisps. A real hacker's language will always have a
slightly raffish character.

Organic growth seems to yield better technology and richer
founders than the big bang method. If you look at the
dominant technologies today, you'll find that most of them
grew organically. This pattern doesn't only apply to
companies. You see it in sponsored research too. Multics and
Common Lisp were big-bang projects, and Unix and MacLisp
were organic growth projects.


-----

Jeffrey M. Jacobs:


I think CL is the WORST thing that could possibly happen to LISP. In
fact, I consider it a language different from "true" LISP.

--

Common LISP is the PL/I of Lisps. Too big and too
incomprehensible, with no examination of the real world of
software engineering.

... The CL effort resembles a bunch of spoiled children,
each insisting "include my feature or I'll pull out, and
then we'll all go down the tubes". Everybody had vested
interests, both financial and emotional.

CL is a nightmare; it has effectively killed LISP
development in this country. It is not commercially viable
and has virtually no future outside of the traditional
academic/defense/research arena.



-----


Dick Gabriel:

Common Lisp is a significantly ugly language. If Guy and I
had been locked in a room, you can bet it wouldn't have
turned out like that.


-----

Paul Graham:

Do you really think people in 1000 years want to be
constrained by hacks that got put into the foundations of
Common Lisp because a lot of code at Symbolics depended on
it in 1988?

WJ

unread,
Apr 4, 2012, 1:11:38 PM4/4/12
to
Insanely useless, unproductive, and boring.

Worshippers of CL (COBOL-Like) are nothing but bureaucrats and
language-lawyers. They are certainly not programmers.
They are interested only in hair-splitting and incessant arguing
about the gargantuan COBOL-Like hyperspec.

One would have to be out of his mind to hire a worshipper of
COBOL-Like.

Dmitriy Ivanov

unread,
Apr 4, 2012, 3:42:01 PM4/4/12
to
Tim Bradshaw wrote on Tue, 3 Apr 2012 16:08:05 +0100 19:08:

TB> On 2012-04-03 15:22:02 +0100, Barry Margolin said:
TB>
TB>> Can anyone offer a good reason why you would ever INTERN or IMPORT
TB>> functions into KEYWORD?
TB>
TB> I think it might be reasonable to intern them if, for instance, you
TB> were writing a reader (other than the CL one) or something like
TB> that. But I think then that you might also be expected to do the
TB> other necessary things in that case.

Keywords are too convenient in many representations to dispense with them.

For example, keywords represent HTML tags in Franz's htmlgen. Using symbols
of another package would be possible but LHTML structures with keywords have
smaller and "stable" footprint regardless the current package you are in.

As a consequence, phtml, which is such a reader, interns parsed tag names
into the KEYWORD package.
--
Sincerely,
Dmitriy Ivanov
lisp.ystok.ru


Marco Antoniotti

unread,
Apr 4, 2012, 5:13:56 PM4/4/12
to
May we instead infer that a business-oriented person (knowledgeable of Lisp) actually fired you in the past? :)

Cheers
--
MA

Tim Bradshaw

unread,
Apr 4, 2012, 6:01:03 PM4/4/12
to
On 2012-04-04 17:28:16 +0100, RG said:

> Note that DEFCONSTANT doesn't force the variable being defined to be a
> constant, it just makes the consequences of changing the variable's
> value undefined.

What I meant specifically is that I don't think there is a documented
way of saying for a symbol x that (constantp 'x) should return true
other than defconstant, which, being a macro, is not useful in the
context of programmatically setting up a keyword symbol.

Kaz Kylheku

unread,
Apr 4, 2012, 6:22:54 PM4/4/12
to
On 2012-04-04, RG <rNOS...@flownet.com> wrote:
> The variable defined by DEFCONSTANT is only required
> to be a constant variable (what a weird concept) in compiled code. In

Maybe they should have called it "inline variable".

RG

unread,
Apr 5, 2012, 1:47:28 AM4/5/12
to
In article <jligav$jq1$1...@dont-email.me>, Tim Bradshaw <t...@tfeb.org>
wrote:
That's true, but you can always define a my-contant-p that does what you
want. You can also shadow constantp if you really want to be anal about
it.

What you can't do is insure that constantp or my-constant-p or anything
else in Common Lisp actually has anything to do with something remaining
constant in the face of perverse circumstances.

On which note, why in the world would you want to import something into
keyword anyway?

rg

Tim Bradshaw

unread,
Apr 5, 2012, 4:55:17 AM4/5/12
to
On 2012-04-05 06:47:28 +0100, RG said:

> That's true, but you can always define a my-contant-p that does what you
> want. You can also shadow constantp if you really want to be anal about
> it.

Yes, but none of those make it be the case that, for instance
(loop for x being the external-symbols of (find-package "KEYWORD")
unless (constantp x)
collect x into bads
finally (return (values (null bads) bads)))
should return t, nil

> On which note, why in the world would you want to import something into
> keyword anyway?

I don't think you would (hence my "undefined behaviour" proposed
gloss). What I think you would want to to is intern a string into the
package (using intern, not implicitly via the reader, because, for
instance, you are implementing a reader), and I think this means that
intern must do the making-constantp-return-true thing itself. I think
if someone decided that import *should* have defined behaviour (perhaps
to support something like this:

(defun intern-into-keyword-perversely (name)
(let ((s (make-symbol name)))
(import s (find-package "KEYWORD"))
s))

) then import would need to be defined to do the whole
make-it-constantp magic, at least in some cases. But I can not see a
case where I would ever want to use import rather than intern.


RG

unread,
Apr 5, 2012, 9:54:12 AM4/5/12
to
In article <jljmlk$uon$1...@dont-email.me>, Tim Bradshaw <t...@tfeb.org>
wrote:

> On 2012-04-05 06:47:28 +0100, RG said:
>
> > That's true, but you can always define a my-contant-p that does what you
> > want. You can also shadow constantp if you really want to be anal about
> > it.
>
> Yes, but none of those make it be the case that, for instance
> (loop for x being the external-symbols of (find-package "KEYWORD")
> unless (constantp x)
> collect x into bads
> finally (return (values (null bads) bads)))
> should return t, nil

Huh? That always returns T. What isn't guaranteed to return t is:

(or (not (constantp 'x))
(eq x (progn (some-arbitrary-code) x)))

> > On which note, why in the world would you want to import something into
> > keyword anyway?
>
> I don't think you would (hence my "undefined behaviour" proposed
> gloss). What I think you would want to to is intern a string into the
> package (using intern, not implicitly via the reader, because, for
> instance, you are implementing a reader), and I think this means that
> intern must do the making-constantp-return-true thing itself.

And it does. See CLHS 11.1.2.3.1.

> I think
> if someone decided that import *should* have defined behaviour (perhaps
> to support something like this:
>
> (defun intern-into-keyword-perversely (name)
> (let ((s (make-symbol name)))
> (import s (find-package "KEYWORD"))
> s))

This reminds me of the old "Doctor, it hurts when I do this" joke.
Don't do that. Just use intern. It already does the Right Thing.

rg

Tim Bradshaw

unread,
Apr 5, 2012, 10:33:03 AM4/5/12
to
On 2012-04-05 14:54:12 +0100, RG said:

> uh? That always returns T.

Does it now?

(constantp 'xyzt)
(import 'xyzt "KEYWORD")
(export 'xyzt "KEYWORD")

And now what's the answer? I have no idea: I don't think it's
specified and I don't think it should be specified.

>
> This reminds me of the old "Doctor, it hurts when I do this" joke.
> Don't do that. Just use intern. It already does the Right Thing.

As I've said more times than I can count in this thread already.

RG

unread,
Apr 5, 2012, 10:52:35 AM4/5/12
to
In article <jlkaev$ag6$1...@dont-email.me>, Tim Bradshaw <t...@tfeb.org>
wrote:

> On 2012-04-05 14:54:12 +0100, RG said:
>
> > uh? That always returns T.
>
> Does it now?

In a conforming implementation, yes:

Function CONSTANTP

Description:

Returns true if form can be determined by the implementation to be a
constant form ...

The following kinds of forms are considered constant forms:

...

* Constant variables, such as keywords

rg

Pascal J. Bourguignon

unread,
Apr 5, 2012, 11:04:19 AM4/5/12
to
RG <rNOS...@flownet.com> writes:

> On which note, why in the world would you want to import something into
> keyword anyway?

I could imagine a hypothetical situation where you want to substitute a
keyword for another:

(let ((key (make-symbol "DO-SOMETHING")))
(setf (symbol-value key) :do-something-else)
(import key :keyword)
(export key :keyword)) ; to be nice, but it's not needed ;-)

(ql:quickload :some-library-using-\:do-something)

Pascal J. Bourguignon

unread,
Apr 5, 2012, 11:09:45 AM4/5/12
to
The point is that importing a symbol into KEYWORD doesn't make it a
KEYWORDP.

(keywordp x) = (eq (symbol-package x) (find-package :keyword))

IMPORT doesn't say what happens if the imported symbol already has a
home package, only what happens if it doesn't have one:

clhs import:

If any symbol to be imported has no home package (i.e.,
(symbol-package symbol) => nil), import sets the home package of the
symbol to package.

But it seems obvious the meaning is that the home package is not changed
when it is present.

Tim Bradshaw

unread,
Apr 5, 2012, 11:10:33 AM4/5/12
to
On 2012-04-05 15:52:35 +0100, RG said:

> Constant variables, such as keywords

keyword n. 1. a symbol the home package of which is the KEYWORD package

Barry Margolin

unread,
Apr 5, 2012, 11:11:35 AM4/5/12
to
In article <87r4w2i...@kuiper.lan.informatimago.com>,
"Pascal J. Bourguignon" <p...@informatimago.com> wrote:

> RG <rNOS...@flownet.com> writes:
>
> > On which note, why in the world would you want to import something into
> > keyword anyway?
>
> I could imagine a hypothetical situation where you want to substitute a
> keyword for another:
>
> (let ((key (make-symbol "DO-SOMETHING")))
> (setf (symbol-value key) :do-something-else)
> (import key :keyword)
> (export key :keyword)) ; to be nice, but it's not needed ;-)
>
> (ql:quickload :some-library-using-\:do-something)

May I throw up now?

RG

unread,
Apr 5, 2012, 12:11:55 PM4/5/12
to
In article <87mx6qi...@kuiper.lan.informatimago.com>,
"Pascal J. Bourguignon" <p...@informatimago.com> wrote:

> RG <rNOS...@flownet.com> writes:
>
> > In article <jlkaev$ag6$1...@dont-email.me>, Tim Bradshaw <t...@tfeb.org>
> > wrote:
> >
> >> On 2012-04-05 14:54:12 +0100, RG said:
> >>
> >> > uh? That always returns T.
> >>
> >> Does it now?
> >
> > In a conforming implementation, yes:
> >
> > Function CONSTANTP
> >
> > Description:
> >
> > Returns true if form can be determined by the implementation to be a
> > constant form ...
> >
> > The following kinds of forms are considered constant forms:
> >
> > ...
> >
> > * Constant variables, such as keywords
>
> The point is that importing a symbol into KEYWORD doesn't make it a
> KEYWORDP.

There are certain things that, while not prohibited by the laws of
physics, members of a civilized society ought to agree not to do for the
sake of the common good. These include things like torturing kittens,
calling forth Cthulu, and importing symbols into the keyword package.
If you choose to defect and do any of these things you're on your own.

I just got my Lisp to do this:

? (keywordp :xyzq)
NIL
? (eq (intern "XYZQ" :cl-user) :xyzq)
T

I will now restart my Lisp to banish this monstrosity permanently to the
cosmic void, and spend the rest of the day repenting of my sin.

rg

Tim Bradshaw

unread,
Apr 5, 2012, 1:01:08 PM4/5/12
to
On 2012-04-05 17:11:55 +0100, RG said:

> I will now restart my Lisp to banish this monstrosity permanently to the
> cosmic void, and spend the rest of the day repenting of my sin.

I am rather afraid it is too late for that: it is in the world now and
it will not wish to go back from whence it came. I would try not to
sleep if I were you and, if sleep you must, not at night. I wish I
could offer some hope, but I fear there can be none.

Contradictio Salomonis cum demonio nocturno. Albericus de Mauleone
delineavit. V. Deus in adiutorium. Ps. Qui habitat. Sancte Bertrande,
demoniorum effugator, intercede pro me miserrimo. Primum uidi nocte
12mi Dec. 1694: uidebo mox ultimum. Peccaui et passus sum, plura adhuc
passurus. Dec. 29,1701

Pascal J. Bourguignon

unread,
Apr 5, 2012, 1:58:55 PM4/5/12
to
RG <rNOS...@flownet.com> writes:

>> The point is that importing a symbol into KEYWORD doesn't make it a
>> KEYWORDP.
>
> There are certain things that, while not prohibited by the laws of
> physics, members of a civilized society ought to agree not to do for the
> sake of the common good. These include things like torturing kittens,
> calling forth Cthulu, and importing symbols into the keyword package.
> If you choose to defect and do any of these things you're on your own.

That's not the point. ANSI-TEST should test the implementation
conformance, not whether you've modified the environment or not.


> I just got my Lisp to do this:
>
> ? (keywordp :xyzq)
> NIL
> ? (eq (intern "XYZQ" :cl-user) :xyzq)
> T
>
> I will now restart my Lisp to banish this monstrosity permanently to the
> cosmic void, and spend the rest of the day repenting of my sin.

As we should.

Tim Bradshaw

unread,
Apr 5, 2012, 3:29:09 PM4/5/12
to
"Pascal J. Bourguignon" <p...@informatimago.com> wrote:

> That's not the point. ANSI-TEST should test the implementation
> conformance, not whether you've modified the environment or not.

An implementation can be fully conforming while having entirely undefined
behavior in some cases. You can not test for that because any result is
conforming.

Pascal J. Bourguignon

unread,
Apr 5, 2012, 3:40:40 PM4/5/12
to
Yes, that's I think the current keyword.lsp ANSI-TESTS are wrong.

Leandro Rios

unread,
Apr 5, 2012, 7:44:17 PM4/5/12
to
El 04/04/12 14:11, WJ escribió:

>
> Worshippers of CL (COBOL-Like) are nothing but bureaucrats and
> language-lawyers. They are certainly not programmers.

Yes, of course, we're Vogons. Resistance is useless. Don't panic.

Tim Bradshaw

unread,
Apr 6, 2012, 5:10:51 AM4/6/12
to
On 2012-04-06 00:44:17 +0100, Leandro Rios said:

> Don't panic.

Use your wheels, it is what they are for
Do not attempt to rescue friends, relatives, loved ones.
You have only a few seconds to escape
Use those seconds sensibly or you will inevitably die
Do not panic
Think only of yourself
Think only of yourself

0 new messages