a better deep-clone for STklos, and suggestions for hash tables

From: Doug Orleans <dougo_at_ccs.neu.edu>
Date: Thu, 30 May 1996 15:25:36 -0400 (EDT)

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