如何让struct copy创建与原始结构相同类型的结构?

如何让struct copy创建与原始结构相同类型的结构?,struct,racket,Struct,Racket,举例来说,这里有一个小的不可变结构和一个更新它的函数: (struct timeseries (variable observations) #:transparent) (define (add-observation ts t v) (struct-copy timeseries ts [observations (conj (timeseries-observations ts) `(,t ,v))])) 我的问题是:如果我创建一个从timeserie

举例来说,这里有一个小的不可变结构和一个更新它的函数:

(struct timeseries (variable observations) #:transparent)

(define (add-observation ts t v)
  (struct-copy timeseries ts
               [observations (conj (timeseries-observations ts) `(,t ,v))]))
我的问题是:如果我创建一个从
timeseries
继承的结构,那么
addobservation
将返回一个
timeseries
结构,而不是它所传递的类型的结构。如何更新结构并保留其类型


顺便说一句,如果上面的代码不是如何在球拍做事情,请让我知道传统的方式。事实上,我在Racket库中没有找到这样的函数,但它保留了原始结构的类型,这让我怀疑我的做法是错误的。是否有一些普通的方法可以实现相同的目的,而不会遇到返回与开始时不同类型的结构的问题?

不幸的是,这是
struct copy
众所周知的局限性之一,其中大部分局限性都源于Sam Tobin Hochstadt恰当地实现了它“不和谐地将结构的各个部分粘贴在一起”(而不是复制结构的低级概念),并且是“
结构复制
是无望的,并且在结构工作方式没有重大改变的情况下无法修复。”Matthias Felleisen将此视为“我们世界中的阿喀琉斯之踵”。“球拍界显然希望改善这种状况,但出于一些原因,这似乎令人望而生畏。我不知道有谁在积极研究这个问题,一个有原则的解决方案应该是什么样子,这似乎是一个悬而未决的问题

结构在很多方面都是球拍的基础。从概念上讲,Racket中的每个值都可以是某种结构类型的实例,但实际上运行时系统对某些内置项有专门的表示。事实上,我认为正在进行的在Racket实现中用Chez方案替换C的工作可能会对遗留Racket VM中内置的某些东西使用结构。这是可能的,因为结构提供了强大的封装功能,特别是通过。改进structs的工作方式将涉及到基本上所有的Racket,并涉及到许多不同的考虑,特别是在向后兼容性方面

以下是进一步阅读这些问题的几点建议:

  • Sam从中勾勒出
    struct
    如何在保持向后兼容性的同时开始提供更多静态信息
  • ,特别是Alexis最后的评论,指出(a)添加正确的静态信息并不明显,(b)添加关于字段名的静态信息不足以解决子类型问题
  • 指出了结构副本的不同限制,包括Alexis的一个很好的总结:

    struct copy
    无法修复,如果没有 球拍结构系统的根本改变。也就是说,它具有 使用结构时C++程序员熟悉的“切片”问题 继承,以及它从 提供的字段名不卫生,很容易被阻止


好消息是,虽然很难找到正确的方法来处理一般情况,但Racket的语言库方法使所有程序员和库作者都可以在自己的代码中尝试不同的方法。有各种各样的球拍包来帮助功能更新和其他功能。Alexis'提供了一个宏来合成函数,如
timeseries观测更新
。Jay McCarthy还尝试了库内代码。您还可以根据您的特定用例实施量身定制的解决方案,从实施一致的
copy
方法(使用
racket/generic
racket/class
)到创建能够更自然地表达您的问题域的领域特定语言,尽管主题是这样的,但它涵盖了Racket中很多功能更新的方法(包括我对DSL的一些想法)

据我所知,这是不可能的(除非您更改结构继承的含义)。您可能不得不接受这样一个事实:您将只获得一个
timeseries
struct。另外,您现在是否正在积极使用结构继承,或者这只是一个普遍的担忧,担心以后结构继承会把事情搞砸?@AlexKnauth我现在没有积极使用结构继承。我刚开始学球拍。我想通过立即学习传统的良好实践,从正确的方向开始。我确实有多年用其他语言编程的经验,
struct copy
的第一个参数“闻起来”像一个bug生成器,这可能是我不应该养成的习惯。“还有比这更吵闹的方法吗?”阿列克斯克纳思我有幸和萨姆思交谈过。我觉得Racket中的struct是一种非常低级的数据结构,而我认为它们在某种程度上可以与OO语言中的类相媲美。正确的答案可能是这样的吗?-“如果你有一堆不同类型的结构正在(功能上)更新,那么你还需要编写一些代码,在调用
struct copy
时选择要创建的适当类型的结构。是的,这很有意义。