a better deep-clone for STklos, and suggestions for hash tables
The deep-clone function that comes with STklos 3.0b2 (defined in
stklos.stk) is buggy (at least by my idea of what deep-clone is
supposed to do). In particular, it does not recurse inside lists and
vectors. Here is a set of definitions which should do the right
thing:
;; A useful function for getting the name of a slot.
(define-method slot-name ((slot <symbol>)) slot)
(define-method slot-name ((slot <pair>)) (car slot))
(define-method deep-clone ((object <object>))
(let* ((class (class-of object))
(clone (%allocate-instance class))
(slots (map slot-name (class-slots class))))
(for-each (lambda (slot)
(if (slot-bound? object slot)
(slot-set! clone slot
(deep-clone (slot-ref object slot)))))
slots)
clone))
(define-method deep-clone ((pair <pair>))
(cons (deep-clone (car pair))
(deep-clone (cdr pair))))
(define-method deep-clone ((vector <vector>))
(list->vector (deep-clone (vector->list vector))))
(define-method deep-clone ((string <string>))
(string-copy string))
(define-method deep-clone ((ht <unknown>))
(if (hash-table? ht)
(let ((clone (make-hash-table)))
(hash-table-for-each ht
(lambda (key value)
(hash-table-put! clone (deep-clone key) (deep-clone value))))
clone)
ht))
(define-method deep-clone (anything-else) anything-else)
I think this covers all the mutable data types except environments,
but I don't think there's any reasonable way to copy an environment
and you probably don't want to do this anyway. Also I'm not sure what
to do with Tk-command. (I still haven't actually used any of the Tk
features of STk...)
A few suggestions for hash-tables:
(1) There ought to be a <hash-table> class, rather than having
(class-of (make-hash-table)) be <unknown>.
(2) There ought to be a way to get the comparison and hash
functions from an existing hash table. Currently the above
method will give you the wrong thing if you try to clone a
hash table with non-default comparison or hash functions.
(3) The arguments to hash-table-for-each (and hash-table map)
maybe ought to be (proc hash), not (hash proc), to parallel
for-each and map. On the other hand, putting the hash table
first keeps them in parallel with all the other hash table
functions, so maybe this is a bad idea. (As a side note, how
come there's no vector-map and vector-for-each?)
(4) There ought to be a list->hash-table that is the converse of
hash-table->list, i.e. it takes a list of (key . value) pairs
and constructs a hash table. Ideally it should also accept
comparison and hash function arguments as well; then you could
correctly (shallow) copy a hash-table with:
(list->hash-table (hash-table->list ht)
(hash-table-comparison-function ht)
(hash-table-hash-function ht))
--Doug Orleans
dougo_at_ccs.neu.edu
Received on Thu May 30 1996 - 21:27:46 CEST
This archive was generated by hypermail 2.3.0
: Mon Jul 21 2014 - 19:38:59 CEST