[Ecls-list] map iterator
Dean O'Connor
dean.oconnor at ite.com.au
Wed Nov 9 00:36:21 UTC 2005
Hi
I am having trouble finding a way to accomplish something in Lisp,
perhaps someone has ideas ....
I am trying to implement the functional equivalent an C++ iterator to an
STL map class, in Lisp.
I need this as I have a C++ application function that needs to call a
lisp function iteratively to retrieve all key/value mappings.
So I need to able to call a Lisp function that will return be the next
map pair.
From my limited experience in Lisp, hash tables seemed to be the
obvious choice. (This could be my first wrong assumption !)
So I created a class containing a hash table and methods to add, show
all and an attempt at a iterator for retrieval.
Now perhaps I am stupidly overcomplicated the matter, but reading all I
could on hash-tables, I didn't see an easy way to index or remember
where I was up to iterating thru the hash over seperate function calls.
I did find a link that encouraged me to use closures (still quite voodoo
to me :) to accomplish it.
However on this link (below), it did warn about the following:
http://www.cs.queensu.ca/software_docs/gnudev/gcl-ansi/gcl_1059.html
>> "It is unspecified what happens if any of the implicit interior
state of an iteration is returned outside the dynamic extent of the
*with-hash-table-iterator* /form/ such as by returning some /closure/
over the invocation /form/."
Now my example nearly works (incorrectly returns FIRST pair for both
calls) but its pretty clear to me my closure is not remembering the
state of the "with-hash-table-iterator".
I am pretty sure I haven't done enough syntactically for it to work
poperly, but also I was wondering if there is any official word of the
behaviour of this form in ELCS ?
If my approach is all wrong, does anyone have any suggestions.
;---------------------------------------------------------------------
; Class: mapper-class
;---------------------------------------------------------------------
(defclass mapper-class ()
((hash-table
:initform (make-hash-table)
:accessor table)
(iterator
:initform nil
:accessor it)))
;---------------------------------------------------------------------
; Methods: mapper-class
;---------------------------------------------------------------------
(defmethod show ((m mapper-class))
(with-accessors ((ht table)) m
(maphash #'(lambda (k v) (format t "~a => ~a~%" k v)) ht)))
(defmethod add ((m mapper-class) key value)
(with-accessors ((ht table)) m
(setf (gethash key ht) value)))
(defmethod clear ((m mapper-class))
(with-accessors ((ht table)) m
(clrhash ht)))
(defmethod set-start ((m mapper-class))
(with-accessors ((ht table) (it it)) m
(setf it #'(lambda ()
(with-hash-table-iterator (next-entry ht)
(next-entry))))))
(defmethod get-next ((m mapper-class))
(with-accessors ((it it)) m
(multiple-value-bind (more key value)
(funcall it)
(if more
(cons key value)
nil))))
;---------------------------------------------------------------------
; Example of populating and retrieving key/values
;---------------------------------------------------------------------
(defparameter *map1* (make-instance 'mapper-class))
(add *map1* "key1" "val1")
(add *map1* "key2" "val2")
(show *map1*)
(set-start *map1*)
(setf key-val (get-next *map1*))
(format t "~a => ~a~%" (first key-val) (rest key-val))
(setf key-val (get-next *map1*))
(format t "~a => ~a~%" (first key-val) (rest key-val))
Cheers
Dean.
More information about the ecl-devel
mailing list