如何返回对象的副本?

时间:2011-02-24 10:38:18

标签: scheme racket r6rs

我需要实现一个参数的函数 - obj - 返回一个Scheme表达式,在计算时,它将返回obj的副本。

有关如何解决问题的任何想法?

2 个答案:

答案 0 :(得分:1)

我猜你打算写一个“函数expr-returning [接受一个] obj [和]返回一个Scheme表达式,在评估时,......”

假设情况如此:你真正需要的是设计配方。首先:写下函数接受的示例以及它返回的内容。这将澄清你正在尝试做的事情,包括对他人和(可能更重要的)你自己。

希望这有用;抱歉这么不透明......

答案 1 :(得分:1)

如果您希望您的程序能够复制任何对象,那么该对象可以是Scheme basic types.中的任何一个。由于 不同的类型,它们具有不同的“性质, “或者结构,或者你有什么,因此制作一种类型的对象的副本必然会涉及制作不同类型的另一个对象的副本的不同策略。

所以你如何处理这个问题就是检查Scheme的每个类型(或者更确切地说,你关心处理的Scheme类型的子集),并弄清楚复制那种类型的对象意味着什么。如果你以显而易见的方式做到这一点,你应该最终得到一组专门的程序,如COPY-NUMBER,COPY-SYMBOL等。(扰流:很多这些程序都不会很有趣。)

要将这些专门的程序统一到一个可以复制你给出的任何对象的程序,它将减少到确定对象的真实类型并调用COPY-FOO程序来完成工作(你也可以扩展内联程序) )。您可以使用COND和类型确定谓词轻松组织此操作:

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

这是一种用于对数据执行操作的通用设计模式,无论其类型称为“类型调度”。这实际上是一种非常糟糕的通用编程方式,而不是在这种情况下这太重要了。

最后一件事就是回复你可以评估的东西以获得副本。不妨告诉你这是什么直接:在一个没有参数的lambda表达式中封装对COPY-OBJECT的调用:

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

然后你可以做像

这样的事情
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.