[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