From: Peter Seibel
Subject: Is this gross?
Date: 
Message-ID: <m3hdqofibj.fsf@javamonkey.com>
Or an appropriate use of read-time evaluation?

  (defun frame-name (id)
    (gethash 
     id
     #.(let ((hash (make-hash-table :test #'equal)))
         (loop for (ids . name) in 
               '((("COM" "COMM")        . "Comment")
                 (("TAL" "TALB")        . "Album")
                 (("TCM" "TCOM")        . "Composer")
                 (("TCO" "TCON")        . "Genre")
                 (("TEN" "TENC")        . "Encoding program")
                 (("TP1" "TPE1")        . "Artist")
                 (("TPA" "TPOS")        . "Part of set")
                 (("TRK" "TRCK")        . "Track")
                 (("TT2" "TIT2")        . "Song")
                 (("TYE" "TYER" "TDRC") . "Year"))
               do (dolist (id ids) (setf (gethash id hash) name)))
         hash)
     id))

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp

From: Harald Hanche-Olsen
Subject: Re: Is this gross?
Date: 
Message-ID: <pcoeklsti7h.fsf@shuttle.math.ntnu.no>
+ Peter Seibel <·····@javamonkey.com>:

| Or an appropriate use of read-time evaluation?
| 
|   (defun frame-name (id)
|     (gethash 
|      id
|      #.(let ((hash (make-hash-table :test #'equal)))
|          (loop for (ids . name) in 
|                '((("COM" "COMM")        . "Comment")
|                  (("TAL" "TALB")        . "Album")
|                  (("TCM" "TCOM")        . "Composer")
|                  (("TCO" "TCON")        . "Genre")
|                  (("TEN" "TENC")        . "Encoding program")
|                  (("TP1" "TPE1")        . "Artist")
|                  (("TPA" "TPOS")        . "Part of set")
|                  (("TRK" "TRCK")        . "Track")
|                  (("TT2" "TIT2")        . "Song")
|                  (("TYE" "TYER" "TDRC") . "Year"))
|                do (dolist (id ids) (setf (gethash id hash) name)))
|          hash)
|      id))

I certainly think the following is easier on the eyes.
Are you worried about a performance hit from using closures?

  (let ((hash (make-hash-table :test #'equal)))
    (loop for (ids . name) in 
          '((("COM" "COMM")        . "Comment")
            (("TAL" "TALB")        . "Album")
            (("TCM" "TCOM")        . "Composer")
            (("TCO" "TCON")        . "Genre")
            (("TEN" "TENC")        . "Encoding program")
            (("TP1" "TPE1")        . "Artist")
            (("TPA" "TPOS")        . "Part of set")
            (("TRK" "TRCK")        . "Track")
            (("TT2" "TIT2")        . "Song")
            (("TYE" "TYER" "TDRC") . "Year"))
          do (dolist (id ids) (setf (gethash id hash) name)))
    (defun frame-name (id)
      (gethash id hash id)))

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Debating gives most of us much more psychological satisfaction
  than thinking does: but it deprives us of whatever chance there is
  of getting closer to the truth.  -- C.P. Snow
From: Johannes Groedem
Subject: Re: Is this gross?
Date: 
Message-ID: <87oekw5js8.fsf@ifi.uio.no>
* Peter Seibel <·····@javamonkey.com>:

>   (defun frame-name (id)
>     (gethash 
>      id
>      #.(let ((hash (make-hash-table :test #'equal)))
>          (loop for (ids . name) in 
>                '((("COM" "COMM")        . "Comment")
>                  (("TAL" "TALB")        . "Album")
>                  (("TCM" "TCOM")        . "Composer")
>                  (("TCO" "TCON")        . "Genre")
>                  (("TEN" "TENC")        . "Encoding program")
>                  (("TP1" "TPE1")        . "Artist")
>                  (("TPA" "TPOS")        . "Part of set")
>                  (("TRK" "TRCK")        . "Track")
>                  (("TT2" "TIT2")        . "Song")
>                  (("TYE" "TYER" "TDRC") . "Year"))
>                do (dolist (id ids) (setf (gethash id hash) name)))
>          hash)
>      id))

I used Erik Naggum's with-hashed-identity (as posted in
<················@naggum.net>) for this, and I think it looks rather
nice:  (Thanks, Erik.)

(defun frame-name (id)
  (with-hashed-identity (:test 'equal)
    (case id
      (("TALB" "TOAL" "TAL") 'collection)
      (("TDOR" "TDRC" "TDRL" "TDTG" "TYER" "TORY"
        "TDA" "TOR" "TRD" "TYE")
       'year)
      (("TEXT" "TOLY" "TCOM" "TCM" "TOPE" "TOA" "TOL" "TXT") 'author)
      (("TIT1" "TIT2" "TIT3" "TOT" "TT1" "TT2" "TT3") 'title)
      (("TPE1" "TPE2" "TPE3" "TPE4" "TP1" "TP2" "TP3" "TP4") 'performer)
      (("TRCK" "TRK") 'sequence)
      (("TCON" "TCN") 'category))))

-- 
Johannes Groedem <OpenPGP: 5055654C>
From: Harald Hanche-Olsen
Subject: Re: Is this gross?
Date: 
Message-ID: <pcovff3ktu0.fsf@shuttle.math.ntnu.no>
+ Johannes Groedem <······@ifi.uio.no>:

| I used Erik Naggum's with-hashed-identity (as posted in
| <················@naggum.net>) for this, and I think it looks rather
| nice:  (Thanks, Erik.)

Ah, indeed.  I think there is a valuable lesson here: Consider using
LOAD-TIME-VALUE whenever you're tempted to use #. as the OP did.

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Debating gives most of us much more psychological satisfaction
  than thinking does: but it deprives us of whatever chance there is
  of getting closer to the truth.  -- C.P. Snow
From: Peter Seibel
Subject: Re: Is this gross?
Date: 
Message-ID: <m31xhqgby2.fsf@javamonkey.com>
Harald Hanche-Olsen <······@math.ntnu.no> writes:

> + Johannes Groedem <······@ifi.uio.no>:
>
> | I used Erik Naggum's with-hashed-identity (as posted in
> | <················@naggum.net>) for this, and I think it looks rather
> | nice:  (Thanks, Erik.)
>
> Ah, indeed.  I think there is a valuable lesson here: Consider using
> LOAD-TIME-VALUE whenever you're tempted to use #. as the OP did.

Okay, I'll consider it. But what do you see as the advantage in this
case?

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Harald Hanche-Olsen
Subject: Re: Is this gross?
Date: 
Message-ID: <pcou0umpeiy.fsf@shuttle.math.ntnu.no>
+ Peter Seibel <·····@javamonkey.com>:

| > Ah, indeed.  I think there is a valuable lesson here: Consider using
| > LOAD-TIME-VALUE whenever you're tempted to use #. as the OP did.
| 
| Okay, I'll consider it. But what do you see as the advantage in this
| case?

It's a question of style.  It seems more appropriate to create the
hash table at load time than letting the reader do it.  Consider what
happens if you compile a file with your function definition:  The fasl
file would have to contain a literal hash table.  It's better, I think
to allow the compiler to compile the code needed to create the table,
then execute that code at load time.  (Besides, I don't even know if
it's reasonable to expect to be able to have a literal hash table in
the fasl file in the first place, but I'm too lazy to look for
evidence either way in the CLHS.)

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Debating gives most of us much more psychological satisfaction
  than thinking does: but it deprives us of whatever chance there is
  of getting closer to the truth.  -- C.P. Snow
From: Harald Hanche-Olsen
Subject: Re: Is this gross?
Date: 
Message-ID: <pco1xhp68bd.fsf@shuttle.math.ntnu.no>
+ Harald Hanche-Olsen <······@math.ntnu.no>:

| (Besides, I don't even know if it's reasonable to expect to be able
| to have a literal hash table in the fasl file in the first place,
| but I'm too lazy to look for evidence either way in the CLHS.)

Lars Brinkhoff wrote and put me right on this issue:  The key concept
is that of similarity, see CLHS 3.2.4.2.2.  This section, together
with surrounding text, makes it clear that hash tables are
externalizable, so long as the keys and values in that hash table are
externalizable too.  And that means they can be stored in a compiled
file and reloaded with the expected result.  Thanks, Lars.

(But still, whenever I see #. in code, my builtin "ugly hack" detector
goes off.  Maybe I need to reset this detector?  Hmm.)

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- Debating gives most of us much more psychological satisfaction
  than thinking does: but it deprives us of whatever chance there is
  of getting closer to the truth.  -- C.P. Snow
From: Vassil Nikolov
Subject: Re: Is this gross?
Date: 
Message-ID: <lzpt59zbh1.fsf@janus.vassil.nikolov.names>
Harald Hanche-Olsen <······@math.ntnu.no> writes:

> [...]
> (But still, whenever I see #. in code, my builtin "ugly hack" detector
> goes off.  Maybe I need to reset this detector?  Hmm.)


  Well, there is also the "won't work with *READ-EVAL* bound to NIL"
  detector...  Of course, if I trust a piece of code enough to run it,
  I might be expected to trust its use of #., too, but if I had some
  sort of code walker that checked for undesirable code, it would only
  be _reading_ the source (with *READ-EVAL* bound to NIL, of course).

  (And with only the standard readtable in place, so any non-standard
  character macros would cause additional trouble, like the need to
  examine their code separately and install just it in order to read
  the source.)

  ---Vassil.


-- 
Vassil Nikolov <········@poboxes.com>

Hollerith's Law of Docstrings: Everything can be summarized in 72 bytes.
From: Fernando
Subject: Re: Is this gross?
Date: 
Message-ID: <jul1j01tfdm1o7dc25sh7u5cbb3o563s1i@4ax.com>
On Fri, 27 Aug 2004 23:54:31 +0200, Johannes Groedem <······@ifi.uio.no>
wrote:


>
>I used Erik Naggum's with-hashed-identity (as posted in
><················@naggum.net>) for this, and I think it looks rather
>nice:  (Thanks, Erik.)

How can you retrieve this message? 
Thanks
From: Edi Weitz
Subject: Re: Is this gross?
Date: 
Message-ID: <87sma7dqbv.fsf@bird.agharta.de>
On Sat, 28 Aug 2004 21:07:29 +0200, Fernando <···@NOSPAMeasyjob.net> wrote:

> On Fri, 27 Aug 2004 23:54:31 +0200, Johannes Groedem <······@ifi.uio.no>
> wrote:
>
>> I used Erik Naggum's with-hashed-identity (as posted in
>> <················@naggum.net>) for this, and I think it looks
>> rather nice: (Thanks, Erik.)
>
> How can you retrieve this message? 

Use Google Group's "Advanced Search" feature:

  <··························································@naggum.net>

Edi.

-- 

"Lisp doesn't look any deader than usual to me."
(David Thornley, reply to a question older than most languages)

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Coby Beck
Subject: OT Google and message IDs (wasRe: Is this gross?)
Date: 
Message-ID: <hE8Yc.70882$X12.30285@edtnps84>
"Edi Weitz" <········@agharta.de> wrote in message
···················@bird.agharta.de...
> On Sat, 28 Aug 2004 21:07:29 +0200, Fernando <···@NOSPAMeasyjob.net>
wrote:
> >> I used Erik Naggum's with-hashed-identity (as posted in
> >> <················@naggum.net>) for this, and I think it looks
> >> rather nice: (Thanks, Erik.)
> >
> > How can you retrieve this message?
>
> Use Google Group's "Advanced Search" feature:
>
>   <··························································@naggum.net>

How?  I usually copy-paste the ID into a url like above, but never see a
"With Message ID" field in their Advanced search form, though have long
thought it would be a nice convenience.

-- 
Coby Beck
(remove #\Space "coby 101 @ big pond . com")
From: Joost Kremers
Subject: Re: OT Google and message IDs (wasRe: Is this gross?)
Date: 
Message-ID: <slrncj264e.93.joostkremers@j.kremers4.news.arnhem.chello.nl>
Coby Beck wrote:
[google advanced group search and message ID]
> How?  I usually copy-paste the ID into a url like above, but never see a
> "With Message ID" field in their Advanced search form, though have long
> thought it would be a nice convenience.

well, if i go to this page:

<http://groups.google.com/advanced_group_search?hl=en>

i do see a box where you can fill out a Message ID. perhaps you're
confusing the advanced group search with the advanced web search?

-- 
Joost Kremers                                      ············@yahoo.com
Selbst in die Unterwelt dringt durch Spalten Licht
EN:SiS(9)
From: Coby Beck
Subject: Re: OT Google and message IDs (wasRe: Is this gross?)
Date: 
Message-ID: <cvaYc.71072$X12.22679@edtnps84>
"Joost Kremers" <············@yahoo.com> wrote in message
·······························@j.kremers4.news.arnhem.chello.nl...
> Coby Beck wrote:
> [google advanced group search and message ID]
> > How?  I usually copy-paste the ID into a url like above, but never see a
> > "With Message ID" field in their Advanced search form, though have long
> > thought it would be a nice convenience.
>
> well, if i go to this page:
>
> <http://groups.google.com/advanced_group_search?hl=en>
>
> i do see a box where you can fill out a Message ID. perhaps you're
> confusing the advanced group search with the advanced web search?

I was, thanks.

-- 
Coby Beck
(remove #\Space "coby 101 @ big pond . com")
From: Damien Diederen
Subject: Re: Is this gross?
Date: 
Message-ID: <878ybw3344.fsf@keem.bcc>
Hi,

Edi Weitz <········@agharta.de> writes:
> On Sat, 28 Aug 2004 21:07:29 +0200, Fernando <···@NOSPAMeasyjob.net> wrote:
>> On Fri, 27 Aug 2004 23:54:31 +0200, Johannes Groedem <······@ifi.uio.no>
>> wrote:
>>
>>> I used Erik Naggum's with-hashed-identity (as posted in
>>> <················@naggum.net>) for this, and I think it looks
>>> rather nice: (Thanks, Erik.)
>>
>> How can you retrieve this message? 
>
> Use Google Group's "Advanced Search" feature:
>
>   <··························································@naggum.net>
>
> Edi.

You can also use this nice shortcut from the normal search form:

  ······················@naggum.net

Cu,
Damien.

-- 
http://users.swing.be/diederen/

There are two types of people in this world, good and bad.  The good
sleep better, but the bad seem to enjoy the waking hours much more.
		-- Woody Allen
From: Johan Bockgård
Subject: Re: Is this gross?
Date: 
Message-ID: <yoijbrguzu9c.fsf@ancalime.dd.chalmers.se>
Fernando <···@NOSPAMeasyjob.net> writes:

> Johannes Groedem <······@ifi.uio.no> wrote:
>
>>
>>I used Erik Naggum's with-hashed-identity (as posted in
>><················@naggum.net>) for this, and I think it looks rather
>>nice: (Thanks, Erik.)
>
> How can you retrieve this message? 

I simply press RET.
From: Kaz Kylheku
Subject: Re: Is this gross?
Date: 
Message-ID: <cf333042.0408301548.40687074@posting.google.com>
Peter Seibel <·····@javamonkey.com> wrote in message news:<··············@javamonkey.com>...
> Or an appropriate use of read-time evaluation?
> 
>   (defun frame-name (id)
>     (gethash 
>      id
>      #.(let ((hash (make-hash-table :test #'equal)))
>          (loop for (ids . name) in 
>                '((("COM" "COMM")        . "Comment")
>                  (("TAL" "TALB")        . "Album")
>                  (("TCM" "TCOM")        . "Composer")
>                  (("TCO" "TCON")        . "Genre")
>                  (("TEN" "TENC")        . "Encoding program")
>                  (("TP1" "TPE1")        . "Artist")
>                  (("TPA" "TPOS")        . "Part of set")
>                  (("TRK" "TRCK")        . "Track")
>                  (("TT2" "TIT2")        . "Song")
>                  (("TYE" "TYER" "TDRC") . "Year"))
>                do (dolist (id ids) (setf (gethash id hash) name)))
>          hash)
>      id))

You might want to consider using LOAD-TIME-VALUE instead. All you care
about is not constructing this table each time you run the function.
You don't need to go all the way back to read time for that, just load
time.

If you construct an object at read time, your compiler will have to do
the equivalent of LOAD-TIME-VALUE anyway. That is to say, the
mechanisms by which objects such as hash tables and whatnot embedded
in the source code are compiled into the object file and restored on
loading is probably closely related to the way LOAD-TIME-VALUE is
implemented.
From: Pascal Bourguignon
Subject: Re: Is this gross?
Date: 
Message-ID: <87n00cm8ju.fsf@thalassa.informatimago.com>
···@ashi.footprints.net (Kaz Kylheku) writes:

> Peter Seibel <·····@javamonkey.com> wrote in message news:<··············@javamonkey.com>...
> > Or an appropriate use of read-time evaluation?
> > 
> >   (defun frame-name (id)
> >     (gethash 
> >      id
> >      #.(let ((hash (make-hash-table :test #'equal)))
> >          (loop for (ids . name) in 
> >                '((("COM" "COMM")        . "Comment")
> >                  (("TAL" "TALB")        . "Album")
> >                  (("TCM" "TCOM")        . "Composer")
> >                  (("TCO" "TCON")        . "Genre")
> >                  (("TEN" "TENC")        . "Encoding program")
> >                  (("TP1" "TPE1")        . "Artist")
> >                  (("TPA" "TPOS")        . "Part of set")
> >                  (("TRK" "TRCK")        . "Track")
> >                  (("TT2" "TIT2")        . "Song")
> >                  (("TYE" "TYER" "TDRC") . "Year"))
> >                do (dolist (id ids) (setf (gethash id hash) name)))
> >          hash)
> >      id))
> 
> You might want to consider using LOAD-TIME-VALUE instead. All you care
> about is not constructing this table each time you run the function.
> You don't need to go all the way back to read time for that, just load
> time.
> 
> If you construct an object at read time, your compiler will have to do
> the equivalent of LOAD-TIME-VALUE anyway. That is to say, the
> mechanisms by which objects such as hash tables and whatnot embedded
> in the source code are compiled into the object file and restored on
> loading is probably closely related to the way LOAD-TIME-VALUE is
> implemented.


Honestly, I don't see the point of making it so complicated. Just write:

(defparameter +frame-name-hash+
    (let ((hash (make-hash-table :test #'equal)))
         (loop for (ids . name) in 
               '((("COM" "COMM")        . "Comment")
                 (("TAL" "TALB")        . "Album")
                 (("TCM" "TCOM")        . "Composer")
                 (("TCO" "TCON")        . "Genre")
                 (("TEN" "TENC")        . "Encoding program")
                 (("TP1" "TPE1")        . "Artist")
                 (("TPA" "TPOS")        . "Part of set")
                 (("TRK" "TRCK")        . "Track")
                 (("TT2" "TIT2")        . "Song")
                 (("TYE" "TYER" "TDRC") . "Year"))
               do (dolist (id ids) (setf (gethash id hash) name)))
         hash))

(defun frame-name (id) (gethash id +frame-name-hash+))

And this has the added advantage that now you can call frame-name in
any macro, at any time (once the file where it's defined is loaded).

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

Our enemies are innovative and resourceful, and so are we. They never
stop thinking about new ways to harm our country and our people, and
neither do we.
From: Christophe Turle
Subject: Re: Is this gross?
Date: 
Message-ID: <chs668$ado$1@amma.irisa.fr>
Pascal Bourguignon wrote:
> ···@ashi.footprints.net (Kaz Kylheku) writes:
> 
> 
>>Peter Seibel <·····@javamonkey.com> wrote in message news:<··············@javamonkey.com>...
>>
>>>Or an appropriate use of read-time evaluation?
>>>
>>>  (defun frame-name (id)
>>>    (gethash 
>>>     id
>>>     #.(let ((hash (make-hash-table :test #'equal)))
>>>         (loop for (ids . name) in 
>>>               '((("COM" "COMM")        . "Comment")
>>>                 (("TAL" "TALB")        . "Album")
>>>                 (("TCM" "TCOM")        . "Composer")
>>>                 (("TCO" "TCON")        . "Genre")
>>>                 (("TEN" "TENC")        . "Encoding program")
>>>                 (("TP1" "TPE1")        . "Artist")
>>>                 (("TPA" "TPOS")        . "Part of set")
>>>                 (("TRK" "TRCK")        . "Track")
>>>                 (("TT2" "TIT2")        . "Song")
>>>                 (("TYE" "TYER" "TDRC") . "Year"))
>>>               do (dolist (id ids) (setf (gethash id hash) name)))
>>>         hash)
>>>     id))
>>
>>You might want to consider using LOAD-TIME-VALUE instead. All you care
>>about is not constructing this table each time you run the function.
>>You don't need to go all the way back to read time for that, just load
>>time.
>>
>>If you construct an object at read time, your compiler will have to do
>>the equivalent of LOAD-TIME-VALUE anyway. That is to say, the
>>mechanisms by which objects such as hash tables and whatnot embedded
>>in the source code are compiled into the object file and restored on
>>loading is probably closely related to the way LOAD-TIME-VALUE is
>>implemented.
> 
> 
> 
> Honestly, I don't see the point of making it so complicated. Just write:
> 
> (defparameter +frame-name-hash+
>     (let ((hash (make-hash-table :test #'equal)))
>          (loop for (ids . name) in 
>                '((("COM" "COMM")        . "Comment")
>                  (("TAL" "TALB")        . "Album")
>                  (("TCM" "TCOM")        . "Composer")
>                  (("TCO" "TCON")        . "Genre")
>                  (("TEN" "TENC")        . "Encoding program")
>                  (("TP1" "TPE1")        . "Artist")
>                  (("TPA" "TPOS")        . "Part of set")
>                  (("TRK" "TRCK")        . "Track")
>                  (("TT2" "TIT2")        . "Song")
>                  (("TYE" "TYER" "TDRC") . "Year"))
>                do (dolist (id ids) (setf (gethash id hash) name)))
>          hash))
> 
> (defun frame-name (id) (gethash id +frame-name-hash+))
> 
> And this has the added advantage that now you can call frame-name in
> any macro, at any time (once the file where it's defined is loaded).
> 

and to go further :


; -- in your utils file --

(defmacro some-keys-value->hashtable (&rest keys-value-list)
  `(let ((hash (make-hash-table :test #'equal)))
     (loop for (ids . name) in ',keys-value-list
           do  (dolist (id ids) (setf (gethash id hash) name)) )
     hash ))


; -- in your app file --

(defparameter +frame-name-hash+
  (some-keys-value->hashtable (("COM" "COMM")        . "Comment")
			      (("TAL" "TALB")        . "Album")
			      (("TCM" "TCOM")        . "Composer")
			      (("TCO" "TCON")        . "Genre")
			      (("TEN" "TENC")        . "Encoding program")
			      (("TP1" "TPE1")        . "Artist")
			      (("TPA" "TPOS")        . "Part of set")
			      (("TRK" "TRCK")        . "Track")
			      (("TT2" "TIT2")        . "Song")
			      (("TYE" "TYER" "TDRC") . "Year") ))

(defun frame-name (id) (gethash id +frame-name-hash+))



----------------
Christophe Turle