Hello,
I'm currently trying to learn Common Lisp, and I have a question
pertaining to keyword symbols: I noted that ::= prints as :=, and (EQ
::= :=) is T. Finding this rather surprising, I tried :::= and got a
READ error. Can someone please explain what the rule for colons in
symbol names is?
Regards,
Lars
Lars wrote:
> Hello,
>
> I'm currently trying to learn Common Lisp, and I have a question
> pertaining to keyword symbols: I noted that ::= prints as :=, and (EQ
> ::= :=) is T. Finding this rather surprising, I tried :::= and got a
> READ error. Can someone please explain what the rule for colons in
> symbol names is?
In Common Lisp, the colon is used as a package marker. The package
system is a kind of module system, and package:name is a way to access a
name in some package - note the use of the colon between "package" and
"name".
What you accidentally stumbled upon are the exceptional rules for what
happens when a token starts with a package marker. You can find the
detailed rules for tokens and package markers at
http://www.lispworks.com/documentation/HyperSpec/Body/02_ce.htm
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
Lars <··@spam.please> writes:
> Hello,
>
> I'm currently trying to learn Common Lisp, and I have a question
> pertaining to keyword symbols: I noted that ::= prints as :=, and (EQ
> ::= :=) is T. Finding this rather surprising, I tried :::= and got a
> READ error. Can someone please explain what the rule for colons in
> symbol names is?
::= is scanned as: :: double package-marker
= symbol named "="
:= is scanned as: : package-marker
= symbol named "="
As you have noted,
:::= is a lexical error, there's no triple package-marker.
Since a package name lacks, the package where a symbol named "=" is
interned is the KEYWORD package.
:= has the same form as :EXTERNAL-FORMAT or :TEST
Now, the difference between : and :: is that :: will allow you to
access all the symbols that are interned in the corresponding package,
while : will allow you to access only the symbols that are _exported_
from that package.
The KEYWORD package is special, since all the symbols interned in this
package are:
- automatically exported,
- automatically defined as a constant having themselves as value:
(intern "NAME" "KEYWORD") ==> (defconstant KEYWORD::NAME 'KEYWORD::NAME)
(export 'KEYWORD::NAME)
in addition to the normal interning.
Otherwise, you will always have (EQ 'PACKAGE:SYMBOL 'PACKAGE::SYMBOL)
when the SYMBOL is exported from the PACKAGE.
--
__Pascal Bourguignon__ http://www.informatimago.com/
ADVISORY: There is an extremely small but nonzero chance that,
through a process known as "tunneling," this product may
spontaneously disappear from its present location and reappear at
any random place in the universe, including your neighbor's
domicile. The manufacturer will not be responsible for any damages
or inconveniences that may result.
Pascal Bourguignon wrote:
> ::= is scanned as: :: double package-marker
> = symbol named "="
>
> := is scanned as: : package-marker
> = symbol named "="
>
> As you have noted,
>
> :::= is a lexical error, there's no triple package-marker.
>
>
> Since a package name lacks, the package where a symbol named "=" is
> interned is the KEYWORD package.
>
> := has the same form as :EXTERNAL-FORMAT or :TEST
>
> Now, the difference between : and :: is that :: will allow you to
> access all the symbols that are interned in the corresponding package,
> while : will allow you to access only the symbols that are _exported_
> from that package.
>
>
> The KEYWORD package is special, since all the symbols interned in this
> package are:
>
> - automatically exported,
> - automatically defined as a constant having themselves as value:
>
> (intern "NAME" "KEYWORD") ==> (defconstant KEYWORD::NAME 'KEYWORD::NAME)
> (export 'KEYWORD::NAME)
> in addition to the normal interning.
>
>
> Otherwise, you will always have (EQ 'PACKAGE:SYMBOL 'PACKAGE::SYMBOL)
> when the SYMBOL is exported from the PACKAGE.
Aha, thanks! I'll consider using some other marker for BNF rules :)
Lars <··@spam.please> writes:
> Pascal Bourguignon wrote:
>> ::= is scanned as: :: double package-marker
>> = symbol named "="
>> := is scanned as: : package-marker
>> = symbol named "="
>> As you have noted,
>> :::= is a lexical error, there's no triple package-marker.
>> Since a package name lacks, the package where a symbol named "=" is
>> interned is the KEYWORD package.
>> := has the same form as :EXTERNAL-FORMAT or :TEST
>> Now, the difference between : and :: is that :: will allow you to
>> access all the symbols that are interned in the corresponding package,
>> while : will allow you to access only the symbols that are _exported_
>> from that package.
>> The KEYWORD package is special, since all the symbols interned in
>> this
>> package are:
>> - automatically exported,
>> - automatically defined as a constant having themselves as value:
>> (intern "NAME" "KEYWORD") ==> (defconstant KEYWORD::NAME
>> KEYWORD::NAME)
>> (export 'KEYWORD::NAME)
>> in addition to the normal interning.
>> Otherwise, you will always have (EQ 'PACKAGE:SYMBOL
>> PACKAGE::SYMBOL)
>> when the SYMBOL is exported from the PACKAGE.
>
> Aha, thanks! I'll consider using some other marker for BNF rules :)
You can use:
\:= |:=|
\:\:= |::=|
or if you don't need to distinguish between := and ::=, there's no
harm in using the keyword named "=":
:=
That said, pure BNF (or EBNF perhaps), also use | and . which can be
hard to read with the lisp reader too, so either you implement your
own BNF reader, or you can lispify the syntax entirely.
Both:
(read-ebnf "sexp-list := sexp | sexp sexp-list .")
(read-from-string "(--> sexp-list (alt sexp (seq sexp sexp-list)))")
can produce the same result:
(--> sexp-list (alt sexp (seq sexp sexp-list)))
--
__Pascal Bourguignon__ http://www.informatimago.com/
"Logiciels libres : nourris au code source sans farine animale."