From: Florian Weimer
Subject: When to use keywords
Date: 
Message-ID: <87bs1doo3a.fsf@deneb.enyo.de>
Is it a good idea to use keywords (instead of plain symbols) as
symbolic constants?

Let me give an example: IP protocols have a one-byte number (6) and an
abbreviation (TCP).  Which of the two alternatives is considered
better style?

  (make-ip-packet src-ip dst-ip ttl 'tcp ...)

  (make-ip-packet src-ip dst-ip ttl :tcp ...)

I guess the symbol form is better if you plan to introduce keyword
arguments somewhere, but I've seen some code which uses keywords for
something similar to MAKE-IP-PACKET.

From: Henrik Motakef
Subject: Re: When to use keywords
Date: 
Message-ID: <87n0kxkd79.fsf@interim.henrik-motakef.de>
Florian Weimer <··@deneb.enyo.de> writes:

> Is it a good idea to use keywords (instead of plain symbols) as
> symbolic constants?
> 
> Let me give an example: IP protocols have a one-byte number (6) and an
> abbreviation (TCP).  Which of the two alternatives is considered
> better style?
> 
>   (make-ip-packet src-ip dst-ip ttl 'tcp ...)
> 
>   (make-ip-packet src-ip dst-ip ttl :tcp ...)
> 
> I guess the symbol form is better if you plan to introduce keyword
> arguments somewhere, but I've seen some code which uses keywords for
> something similar to MAKE-IP-PACKET.

One problem with the first form is that symbols live in packages:

* (defpackage :ip
    (:use :common-lisp)
    (:export :tcp-p :tcp-keyword-p))
#<The IP package, 0/7 internal, 2/2 external>
* (in-package :ip)
#<The IP package, 0/7 internal, 2/2 external>
* (defun tcp-p (symbol)
    (eq 'tcp symbol))
TCP-P
* (defun tcp-keyword-p (keyword)
    (eq :tcp keyword))
TCP-KEYWORD-P
* (tcp-p 'tcp)
T
* (tcp-keyword-p :tcp)
T
* (defpackage :some-user-package
    (:use :common-lisp))
#<The SOME-USER-PACKAGE package, 0/9 internal, 0/2 external>
* (in-package :some-user-package)
#<The SOME-USER-PACKAGE package, 0/9 internal, 0/2 external>
* (ip:tcp-p 'tcp)
NIL
* (ip:tcp-keyword-p :tcp)
T
* (ip:tcp-p 'ip::tcp)
T

hth
Henrik
From: Florian Weimer
Subject: Re: When to use keywords
Date: 
Message-ID: <87znoxloq9.fsf@deneb.enyo.de>
Henrik Motakef <··············@web.de> writes:

> One problem with the first form is that symbols live in packages:

Thanks.

This suggests that keywords are the way to go.  However, things like

  (make-ip-packet :source-address src-ip :destination-address dst-ip
                  :protocol :tcp :data data)

look a bit awkward.  Or should I just get used to this
keyword-after-keyword style?

> * (defpackage :ip
>     (:use :common-lisp)
>     (:export :tcp-p :tcp-keyword-p))
> #<The IP package, 0/7 internal, 2/2 external>
> * (in-package :ip)
> #<The IP package, 0/7 internal, 2/2 external>

So this is how Programming In The Large is done using Lisp?  Can you
suggest any instructive real-world examples?

(I came to Lisp via GNU Emacs...)
From: Thomas F. Burdick
Subject: Re: When to use keywords
Date: 
Message-ID: <xcvu1f5jq68.fsf@famine.OCF.Berkeley.EDU>
Florian Weimer <··@deneb.enyo.de> writes:

> Henrik Motakef <··············@web.de> writes:
> 
> > One problem with the first form is that symbols live in packages:

This is only a problem if you don't export your symbols correctly.
All of the interface should be exported from a package, and the
internals should remain internal.  Normally, this is considered a
feature, not a problem.

> This suggests that keywords are the way to go.  However, things like
> 
>   (make-ip-packet :source-address src-ip :destination-address dst-ip
>                   :protocol :tcp :data data)
> 
> look a bit awkward.  Or should I just get used to this
> keyword-after-keyword style?

You should just get used to it ;-).  The standard functions are
usually a good place to look for style tips (except for odd things
remaining from the past, such as RPLACD) -- here, you should take your
cue from OPEN.

When deciding whether to make symbolic values symbols in the keyword
package, or symbols in my module's package, I go with keywords if
there is no chance that the user of my package will want to extend the
set of acceptable symbolic values.  If the user might want to add
symbols if his/her own, then I put the symbols in my module's package.
In this case, unless you're planning on making MAKE-IP-PACKET
extensible--so that users could implement their own protocols--then
you should go with keywords.

As an example of where I would use non-keyword symbols, imagine a
graphing package that can create graphs in a couple of different image
formats.  But it allows the user to supply functions that know how to
make other image formats, to extend the package's capabilities.  Eg:

  (grapher:graph-data data :output-file "foo.bmp" :output-type :bmp)

  (defun my-jpg-filter (raw-stream out-stream)
    ...)

  (grapher:supply-filter #'my-jpg-filter :jpg)
  (grapher:graph-data data :output-file "foo.jpg" :output-type :jpg)

Now, say that I load another package, written by my coworker Bob, that
*also* wants to produce jpegs, but Bob was in a hurry, and wrote the
filter wrong, so it creates broken jpegs.  Now if I do:

  (load "bobs-module")
  ;; ...
  (grapher:graph-data data :output-file "foo.jpg" :output-type :jpg)

I get a broken image.  This is because Bob's definition clobbered
mine, because we were both using keywords, which are a global
resource.  If we'd done this in our own packages, it wouldn't be a
problem:

  ;; Produce a good jpeg
  (grapher:graph-data data :output-file "tom.jpg" :output-type 'tom:jpg)
  ;; Produce a broken one
  (grapher:graph-data data :output-file "bob.jpg" :output-type 'bob:jpg)

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Rahul Jain
Subject: Re: When to use keywords
Date: 
Message-ID: <87adgxe05a.fsf@localhost.localdomain>
···@famine.OCF.Berkeley.EDU (Thomas F. Burdick) writes:

> When deciding whether to make symbolic values symbols in the keyword
> package, or symbols in my module's package, I go with keywords if
> there is no chance that the user of my package will want to extend the
> set of acceptable symbolic values.  If the user might want to add
> symbols if his/her own, then I put the symbols in my module's package.
> In this case, unless you're planning on making MAKE-IP-PACKET
> extensible--so that users could implement their own protocols--then
> you should go with keywords.

I would use both, with keywords for basic options such as the standard
udp, tcp, icmp, etc. It makes sense to do that because those are
"globally" useful options. Also, the protocols are named in a way that
doesn't have any conflicts, so maybe using keywords for all of them
works in this case.

However, in a more general case, I would still use keywords for the set
of options that are considered to be the most primitive or basic or
generally useful. That way, we don't need to worry about exporting some
name that could conflict with another package. Sure, it can be worked
around using symbol-macros, but I'd rather not have this inconvenience
if it makes sense to use a global namespace for those identifiers in the
first place. What I've said here may seem a bit incoherent, but that's
because I haven't thought about the matter formally. I'm just expressing
my gut feeling as best as I can. Maybe as this discussion progresses,
I'll be able to express my opinion more accurately (or someone else will
do it for me ;).

--
Rahul Jain
From: Henrik Motakef
Subject: Re: When to use keywords
Date: 
Message-ID: <87heb5k71z.fsf@interim.henrik-motakef.de>
Florian Weimer <··@deneb.enyo.de> writes:

> However, things like
> 
>   (make-ip-packet :source-address src-ip :destination-address dst-ip
>                   :protocol :tcp :data data)
> 
> look a bit awkward.  Or should I just get used to this
> keyword-after-keyword style?

You wouldn't be the only one to use it. For example:

(with-open-file (stream path :direction :input) ...)

(make-pathname :directory wherever :name :wild :version :newest)

> > * (defpackage :ip
> >     (:use :common-lisp)
> >     (:export :tcp-p :tcp-keyword-p))
> > #<The IP package, 0/7 internal, 2/2 external>
> > * (in-package :ip)
> > #<The IP package, 0/7 internal, 2/2 external>
> 
> So this is how Programming In The Large is done using Lisp?  Can you
> suggest any instructive real-world examples?

Examples for using packages? Well, about every library you'll find on
the net uses at least one package of its own, some use several. There
isn't really a lot of magic involved, try reading the pages on
*PACKAGE*, IN-PACKAGE, DEFPACKAGE, USE-PACKAGE, EXPORT and
SYMBOL-PACKAGE in the Hyperspec, and maybe others that 
(apropos "package") finds that look interesting.

hth
Henrik
From: Florian Weimer
Subject: Re: When to use keywords
Date: 
Message-ID: <87adgsvyjw.fsf@deneb.enyo.de>
Henrik Motakef <··············@web.de> writes:

> You wouldn't be the only one to use it. For example:
>
> (with-open-file (stream path :direction :input) ...)

I see.  Thanks.

> Examples for using packages? Well, about every library you'll find on
> the net uses at least one package of its own, some use several.

I've looked at a few examples, and it doesn't seem to be common
practice to include the package name in the symbols.  Is this the
regular style, or is my sample just too small?
From: Drew McDermott
Subject: Re: When to use keywords
Date: 
Message-ID: <b2r16a$r8b$1@news.ycc.yale.edu>
Florian Weimer wrote:
>  things like
> 
>   (make-ip-packet :source-address src-ip :destination-address dst-ip
>                   :protocol :tcp :data data)
> 
> look a bit awkward.  Or should I just get used to this
> keyword-after-keyword style?

I like to distinguish between keywords used as argument markers and 
keywords used as data by quoting the latter.

(make-ip-packet :source-address src-ip :destination-address dst-ip
                 :protocol ':tcp :data data)

Just because the quote is optional doesn't mean you have to leave it out.


                                              -- Drew McDermott
From: Christopher C. Stacy
Subject: Re: When to use keywords
Date: 
Message-ID: <ufzqmr75q.fsf@dtpq.com>
>>>>> On Mon, 17 Feb 2003 11:04:24 -0500, Drew McDermott ("Drew") writes:
 Drew> (make-ip-packet :source-address src-ip :destination-address dst-ip
 Drew>                  :protocol ':tcp :data data)

That's what I do, too, and I use keywords as data when I don't want to
export a symbol to the user that I think he might already be using for
the same semantics.  For example, some keyword data I used recently
was :POST and :GET (quoted where it appears in the source code).
From: Kaz Kylheku
Subject: Re: When to use keywords
Date: 
Message-ID: <cf333042.0302171123.6bc514d3@posting.google.com>
Florian Weimer <··@deneb.enyo.de> wrote in message news:<··············@deneb.enyo.de>...
> Henrik Motakef <··············@web.de> writes:
> 
> > One problem with the first form is that symbols live in packages:
> 
> Thanks.
> 
> This suggests that keywords are the way to go.  However, things like
> 
>   (make-ip-packet :source-address src-ip :destination-address dst-ip
>                   :protocol :tcp :data data)
> 
> look a bit awkward.  Or should I just get used to this
> keyword-after-keyword style?

Yes. If it bothers you, then use whitespace to separate the pairs:

   (make-ip-packet :source-address src-ip
                   :destination-address dst-ip
                   :protocol :tcp
                   :data data)

> (I came to Lisp via GNU Emacs...)

So how do you do property parameter lists in that language? If you
don't have keywords, you are then writing: 'protocol 'tcp 'data 'data.
 Same readability problem, assuming you view it as a problem. Or you
could have special evaluation rules for function calls that would let
you write protocol 'tcp data 'data. But then the evaluation rules
depend on the function definition, which can change dynamically.
From: Florian Weimer
Subject: Re: When to use keywords
Date: 
Message-ID: <87r8a4ufxp.fsf@deneb.enyo.de>
···@ashi.footprints.net (Kaz Kylheku) writes:

> Yes. If it bothers you, then use whitespace to separate the pairs:
>
>    (make-ip-packet :source-address src-ip
>                    :destination-address dst-ip
>                    :protocol :tcp
>                    :data data)

Yes, this looks nice, and the ':keyword approach is helpful, too.

>> (I came to Lisp via GNU Emacs...)
>
> So how do you do property parameter lists in that language?

Recent Emacsen support keyword symbols.  It's still a bit unusual to
use property-style argument lists, though.
From: Brian Palmer
Subject: Re: When to use keywords
Date: 
Message-ID: <0wh3cmihzln.fsf@rescomp.Stanford.EDU>
Florian Weimer <··@deneb.enyo.de> writes:
 
> Recent Emacsen support keyword symbols.  It's still a bit unusual to
> use property-style argument lists, though.

Nifty. (I was still using defun* when I used keywords; and it looks
like they (well, xemacs at least) handle keywords as arguments to
other keywords, unlike defun*)
-- 
If you want divine justice, die.
                  -- Nick Seldon 
From: Kalle Olavi Niemitalo
Subject: Re: When to use keywords
Date: 
Message-ID: <87y945v057.fsf@Astalo.kon.iki.fi>
Brian Palmer <·······@rescomp.Stanford.EDU> writes:

> (I was still using defun* when I used keywords; and it looks
> like they (well, xemacs at least) handle keywords as arguments to
> other keywords, unlike defun*)

If cl-do-arglist (and perhaps cl-parsing-keywords) used
plist-member rather than memq, functions defined with defun*
could properly handle keywords as values of keyword parameters.
It seems such a change was already made in GNU Emacs CVS on
2000-10-15 but then reverted on 2001-07-02.
From: Kaz Kylheku
Subject: Re: When to use keywords
Date: 
Message-ID: <cf333042.0302171117.244e7914@posting.google.com>
Florian Weimer <··@deneb.enyo.de> wrote in message news:<··············@deneb.enyo.de>...
> Is it a good idea to use keywords (instead of plain symbols) as
> symbolic constants?

Keywords give you package-proofness in a simple, easy to digest form.

> Let me give an example: IP protocols have a one-byte number (6) and an
> abbreviation (TCP).  Which of the two alternatives is considered
> better style?
> 
>   (make-ip-packet src-ip dst-ip ttl 'tcp ...)
> 
>   (make-ip-packet src-ip dst-ip ttl :tcp ...)

What object 'tcp refers to depends on in what package that expression
is read. What object :tcp refers to does not depend on that: it's a
symbol in the KEYWORD package, always.

A keyword always stands for itself under evaluation, so you can insert
it into forms without worrying about quoting.

If you use a keyword as a syntactic marker in some macro-based
language feature, it may be better to use an unquoted symbol, and then
take care to treat it as a string, rather than a symbol. This is how
the LOOP syntax works. When you write (LOOP FOR X IN ...), the LOOP
macro does not care in what package FOR and IN are; it cares about
their names, "FOR" and "IN". Thus these keywords effectively behave
like the KEYWORD package keywords, but without the leading colon.

If you must use regular symbols in the interface of MAKE-IP-PACKET, it
might be a good idea to provide this kind of package-proofing
also---accept a symbol named "TCP" from any package.

> I guess the symbol form is better if you plan to introduce keyword
> arguments somewhere, but I've seen some code which uses keywords for

Why is that better? Because you think it's confusing to have keyword
values interspersed with keyword parameters? I don't. :)
From: Nils Goesche
Subject: Re: When to use keywords
Date: 
Message-ID: <lyheb2hfo2.fsf@cartan.de>
···@ashi.footprints.net (Kaz Kylheku) writes:

> Florian Weimer <··@deneb.enyo.de> wrote in message news:<··············@deneb.enyo.de>...

> > Is it a good idea to use keywords (instead of plain symbols) as
> > symbolic constants?
> 
> Keywords give you package-proofness in a simple, easy to digest form.
> 
> > Let me give an example: IP protocols have a one-byte number (6) and an
> > abbreviation (TCP).  Which of the two alternatives is considered
> > better style?
> > 
> >   (make-ip-packet src-ip dst-ip ttl 'tcp ...)
> > 
> >   (make-ip-packet src-ip dst-ip ttl :tcp ...)
> 
> What object 'tcp refers to depends on in what package that
> expression is read. What object :tcp refers to does not depend on
> that: it's a symbol in the KEYWORD package, always.

> > I guess the symbol form is better if you plan to introduce keyword
> > arguments somewhere, but I've seen some code which uses keywords
> > for
> 
> Why is that better? Because you think it's confusing to have keyword
> values interspersed with keyword parameters? I don't. :)

Here is one possible reason:

(defpackage "A"
  (:use "CL")
  (:export "A"))

(in-package "A")

(defclass a ()
  ((a :initarg a :reader a)))

(defpackage "B"
  (:use "CL")
  (:export "A" "B"))

(in-package "B")

(defclass b ()
  ((a :initarg a :reader a)))

(defpackage "C"
  (:use "CL")
  (:export "C"))

(in-package "C")

(defclass c (a:a b:b)
  ())

(defun foo ()
  (make-instance 'c 'a:a 42 'b:a 37))

Regards,
-- 
Nils G�sche
"Don't ask for whom the <CTRL-G> tolls."

PGP key ID 0x0655CFA0
From: Johan Kullstam
Subject: Re: When to use keywords
Date: 
Message-ID: <873cmmygpm.fsf@sysengr.res.ray.com>
Florian Weimer <··@deneb.enyo.de> writes:

> Is it a good idea to use keywords (instead of plain symbols) as
> symbolic constants?
> 
> Let me give an example: IP protocols have a one-byte number (6) and an
> abbreviation (TCP).  Which of the two alternatives is considered
> better style?
> 
>   (make-ip-packet src-ip dst-ip ttl 'tcp ...)
> 
>   (make-ip-packet src-ip dst-ip ttl :tcp ...)
> 
> I guess the symbol form is better if you plan to introduce keyword
> arguments somewhere, but I've seen some code which uses keywords for
> something similar to MAKE-IP-PACKET.

As I understand it (and someone with more experience/knowledge
*please* correct me if I am confused/mistaken), keywords are used when
you just want to have symbol name.  All you seem to want to do is
compare strings by employing the reader.  This application doesn't
"use up" the keyword namespace.  Just because your MAKE-IP-PACKET
checks for :TCP in something like (WHEN (EQ PROTOCOL :TCP) .....)
doesn't change :TCP itself, nor does it depend upon any changabe
aspect of this symbol.

-- 
Johan KULLSTAM <··········@attbi.com> sysengr
From: Joe Marshall
Subject: Re: When to use keywords
Date: 
Message-ID: <3cmkmekd.fsf@ccs.neu.edu>
Florian Weimer <··@deneb.enyo.de> writes:

> Is it a good idea to use keywords (instead of plain symbols) as
> symbolic constants?

Use keywords when the symbols are part of the public API, use plain
symbols when they are `private'.

  (make-ip-packet src-ip dst-ip ttl :tcp ...)

Presumably, people who call MAKE-IP-PACKET would be supplying the :TCP
(or :UDP or whatever), so it is part of the API.  But suppose that
your implementation had some hack for buffer management such that
internally you could pass in a pre-allocated buffer, but you *don't*
want that argument to be part of the API

  (defun make-ip-packet (source-ip destination-ip time-to-live protocol
                         &key ((buffer buffer) nil))

Presumably, you'd export MAKE-IP-PACKET, but not BUFFER, so a caller
would not be able to pass in a buffer unless he did

  (make-ip-packet src-ip dst-ip ttl :tcp 'socket-package::buffer some-buffer)