How do I return a copy of an object?

867 views Asked by At

I need to implement a function of one argument -- obj -- that returns a Scheme expression that, when evaluated, will return a copy of obj.

Any ideas on how to proceed with the problem?

2

There are 2 answers

0
Nietzche-jou On

If you want your procedure to be able to duplicate any object, then the object could be any one of Scheme's basic types. By virtue of being different types, they have differing "natures," or structure, or what have you, and so making a copy of an object of one type is necessarily going to involve different strategies from making a copy of another object of a different type.

So how you approach this is to examine each of Scheme's types (or rather, the subset of Scheme's types you care about handling) and puzzle out what it means to duplicate an object of that type. If you do this in the obvious way, you should end up with a set of specialized procedures like COPY-NUMBER, COPY-SYMBOL, etc. (spoiler: a lot of these procedures aren't going to be very interesting.)

To unite these specialized procedures into a single one that can duplicate any object you give it reduces down to determining the object's real type and calling out to the COPY-FOO procedure to do the work (you could as well expand the procedure inline). You can organize this really easily with a COND and the type-determining predicates:

(define (copy-object obj)
  (cond ((number? obj) (copy-number obj))
        ((boolean? obj) (copy-boolean obj))
        ...
        ))

This is a general design pattern for performing an operation on a datum regardless of its type called "dispatch on type." It's actually a pretty piss-poor way to do generic programming, not that that matters too much in this situation.

The last thing is the added wrinkle of returning a thing you can evaluate to get the copies. Might as well tell you what that is straight up: encapsulate a call to COPY-OBJECT inside a lambda-expression of no arguments:

(define (expr-returning obj)
  (lambda () (copy-object obj)))

Then you can do stuff like

guile> (define x (list 1 2 3 4))
guile> (define y (expr-returning x))
guile> (define cx (y))
guile> x
(1 2 3 4)
guile> cx
(1 2 3 4)
guile> (set-cdr! x 'foo)
guile> x
(1 . foo)
guile> z
(1 2 3 4)
etc.
0
John Clements On

I'm guessing that you meant to write "a function expr-returning [that accepts an] obj [and] returns a Scheme expression that, when evaluated, ..."

Assuming this is the case: what you really need here is the design recipe. To begin with: write down examples of what your function accepts, and what it returns. This will clarify what you're trying to do, both to others and (probably more importantly) to yourself.

Hope this is helpful; sorry to be so opaque...