·····@eunet.no (Christian Nyb�) writes:
> I'd like to get a list of structs that satisfy a filter. This is the
> code I've written:
>
> (defparameter *message-stack* (make-hash-table :test '=)
> "Hashtable with number SEQNO as key, struct MESSAGE as value.")
Informative correction -- :test argument to make-hash-table is one of
eq, eql (default), equal or equalp.
Janis Dzerins
--
Ever feel like life was a game and you had the wrong instruction book?
Janis Dzerins <·····@latnet.lv> writes:
> ·····@eunet.no (Christian Nyb�) writes:
>
> > (defparameter *message-stack* (make-hash-table :test '=)
> > "Hashtable with number SEQNO as key, struct MESSAGE as value.")
>
> Informative correction -- :test argument to make-hash-table is one of
> eq, eql (default), equal or equalp.
Although CLTL2 does not explicitly permit other designators, the
implementation I use (ACL 5.01) allows for any test function. Using
`=' instead of `eq' tells readers that I want the hash to test
numbers, rather than objects. That's why I used it.
I think
#+Allegro (make-hash-table :test '=) #-Allegro(make-hash-table :test 'eq)
would be better, as it would have conveyed the same information in a
portable manner.
--
chr
·····@eunet.no (Christian Nyb�) writes:
> Although CLTL2 does not explicitly permit other designators, the
> implementation I use (ACL 5.01) allows for any test function. Using
> `=' instead of `eq' tells readers that I want the hash to test
> numbers, rather than objects. That's why I used it.
>
> I think
> #+Allegro (make-hash-table :test '=) #-Allegro(make-hash-table :test 'eq)
> would be better, as it would have conveyed the same information in a
> portable manner.
I don't think that eq is a good idea if you're using numbers.
(eq 3.0 3.0) is not guaranteed to return t.
From the Hyperspec, on function EQ:
"An implementation is permitted to make ``copies'' of characters and
numbers at any time. The effect is that Common Lisp makes no guarantee
that eq is true even when both its arguments are ``the same thing'' if
that thing is a character or number."
Christophe
--
Jesus College, Cambridge, CB5 8BL +44 1223 524 842
(FORMAT T "(·@{~w ········@{~w~^ ~})" 'FORMAT T "(·@{~w ········@{~w~^ ~})")
Christophe Rhodes <·····@cam.ac.uk> writes:
> ·····@eunet.no (Christian Nyb�) writes:
>
> > Although CLTL2 does not explicitly permit other designators, the
> > implementation I use (ACL 5.01) allows for any test function. Using
> > `=' instead of `eq' tells readers that I want the hash to test
> > numbers, rather than objects. That's why I used it.
> >
> > I think
> > #+Allegro (make-hash-table :test '=) #-Allegro(make-hash-table :test 'eq)
> > would be better, as it would have conveyed the same information in a
> > portable manner.
>
> I don't think that eq is a good idea if you're using numbers.
> (eq 3.0 3.0) is not guaranteed to return t.
equalp is a bertter test to use if you're using numbers since it's portable
and it bottoms out at = for numbers.
·····@eunet.no (Christian Nyb�) writes:
> Janis Dzerins <·····@latnet.lv> writes:
>
> > ·····@eunet.no (Christian Nyb�) writes:
> >
> > > (defparameter *message-stack* (make-hash-table :test '=)
> > > "Hashtable with number SEQNO as key, struct MESSAGE as value.")
> >
> > Informative correction -- :test argument to make-hash-table is one of
> > eq, eql (default), equal or equalp.
>
> Although CLTL2 does not explicitly permit other designators, the
> implementation I use (ACL 5.01) allows for any test function. Using
> `=' instead of `eq' tells readers that I want the hash to test
> numbers, rather than objects. That's why I used it.
>
> I think
> #+Allegro (make-hash-table :test '=) #-Allegro(make-hash-table :test 'eq)
> would be better, as it would have conveyed the same information in a
> portable manner.
And
(make-hash-table :test #'eql)
would be portable across the board without any problem and without
#+/#-.
Cheers
--
Marco Antoniotti =============================================================
NYU Bioinformatics Group tel. +1 - 212 - 998 3488
719 Broadway 12th Floor fax +1 - 212 - 995 4122
New York, NY 10003, USA http://galt.mrl.nyu.edu/valis
Like DNA, such a language [Lisp] does not go out of style.
Paul Graham, ANSI Common Lisp
Marco Antoniotti <·······@cs.nyu.edu> writes:
> And
>
> (make-hash-table :test #'eql)
>
> would be portable across the board without any problem and without
> #+/#-.
It depends on whether he wants 3.0 and 3 to be seen as equivalent hash
keys. The fnction = will do this since (= 3.0 3), but EQL will not since
(NOT (EQL 3.0 3)). However, (EQUALP 3.0 3), which is why I suggested an
EQUALP hash table.
Kent M Pitman <······@world.std.com> writes:
> Marco Antoniotti <·······@cs.nyu.edu> writes:
>
> > And
> >
> > (make-hash-table :test #'eql)
> >
> > would be portable across the board without any problem and without
> > #+/#-.
>
> It depends on whether he wants 3.0 and 3 to be seen as equivalent hash
> keys. The fnction = will do this since (= 3.0 3), but EQL will not since
> (NOT (EQL 3.0 3)). However, (EQUALP 3.0 3), which is why I suggested an
> EQUALP hash table.
I stand corrected.
Cheers
--
Marco Antoniotti =============================================================
NYU Bioinformatics Group tel. +1 - 212 - 998 3488
719 Broadway 12th Floor fax +1 - 212 - 995 4122
New York, NY 10003, USA http://galt.mrl.nyu.edu/valis
Like DNA, such a language [Lisp] does not go out of style.
Paul Graham, ANSI Common Lisp
·····@eunet.no (Christian Nyb�) writes:
> I'd like to get a list of structs that satisfy a filter. This is the
> code I've written:
>
> (defmacro filter-structs (hash-containing-structs &rest args)
> "Return a list of keys of structs,
> filtered by ARGS, which should be keys corresponding
> to slot-names of the structs, and the required values."
> `(let (list-of-seqnos)
> (maphash (lambda (key value)
> ,(do ((first (first args) (first args))
> (second (second args) (second args))
> result)
> ((not (and args (pop args) (pop args)))
> `(and ,@result (push key list-of-seqnos)))
> (push `(equal
> ,second
> (funcall
> (symbol-function
> (intern
> (concatenate
> 'string
> (symbol-name (type-of value))
> "-"
> (symbol-name ,first))))
> value))
> result)))
> ,hash-containing-structs)
> list-of-seqnos))
First, this is not robust because it's not interning the symbol in any
particular package. You have no idea what package will prevail when you
are running this code--it might not be the load package even. One very
explicit reason DEFCLASS doesn't do the :conc-name thing that DEFSTRUCT
does is that we had a lot of problems in the olden days with code like this.
Even if you make INTERN use a fixed package, like (intern ... *my-package*),
you may sometimes lose. e.g., if the type-of was in another package that was
not *my-package*, the constructors *probably* [but not necessarily] will
be, too. Ditto if you do (intern ... (symbol-package (type-of value)))
you will lose in some cases. The reason you'll sometimes lose has to do
with package use list searching, so that if you have a struct named CAR,
you can't do
(intern (symbol-name (type-of *my-car*)) (symbol-package (type-of *my-car*)))
because you'll sometimes find CAR is in the CL package, and it's bad to
intern other symbols like CAR-ENGINE and MAKE-CAR in that package. That may
be a bad example, but at least it gives you the flavor of how use lists
interfere. It's possible to construct many other examples.
Symbol magic at runtime is also pretty slow--you don't want to be doing
that many interns if you're searching a thousand-message db on a busy
machine.
You are better off using classes and directly using SLOT-VALUE, for example.
So you'd say (filter-strucsts *message-stack* 'initials "jqp" 'revision 1)
and then you'd use (slot-value message slot-name) in order to get the value.
Slot-value is both less error-prone (because changes to the slot-name and
its package happen in predictable ways between definition and use) and more
efficient (because slot-value is NOT slow).