您如何找到结构的字段和属性?

时间:2018-09-04 13:54:56

标签: struct reflection racket

问题

假设您有一个结构,如下所示:

(struct soldier (name rank serial-number) #:transparent)
(define s (soldier 'Smith 'private 100134))

如何找出soldiers包含哪些字段?或它支持哪些通用接口,或具有什么结构类型属性?


到目前为止的研究工作

(如果您已经知道答案,请跳过本节。)

最近几天,我一直在阅读有关struct的文档,但我一直无法弄清楚如何将这些片段组合在一起。我可能只是想念一些基本的信息,而这不向认识Racket的人说。

Reflection and Security的一章中有一个“ Structure Inspectors”部分,内容为:

  

检查器提供了对结构域和结构类型信息的访问,而没有普通的域访问器和变异器。

但是我还不知道如何让检查员来提供。

struct-infostruct-type-info提供了一些信息,但没有提供字段名称,接口,属性等:

> (struct-type-info struct:soldier)
'soldier
3
0
#<procedure:soldier-ref>
#<procedure:soldier-set!>
'(0 1 2)
#f
#f

struct->vectorstruct->list提供对实例的内容和上述数据的访问,但仅此而已:

> (struct->vector s)
'#(struct:soldier Smith private 100134)

如果您可以向我展示如何检查结构类型以查看其中的内容的示例,则可能可以弄清楚我在这里看不到的任何即将变得显而易见的东西。

1 个答案:

答案 0 :(得分:3)

字段名称在运行时不可用。但是,您可以在扩展时在结构名称上使用syntax-local-value来获取一些信息。

一个简单的例子:

#lang racket
(require (for-syntax racket/struct-info))

(struct foo (a b))
(begin-for-syntax
  (display (extract-struct-info (syntax-local-value #'foo))))

更新

在此示例中:

#lang racket
(require (for-syntax racket/struct-info))

(struct foo (a [b #:mutable] c))
(begin-for-syntax
  (display (extract-struct-info (syntax-local-value #'foo))))

突变体的标识符列表为:(#f #<syntax:4:8 set-foo-b!> #f)。 那只是第二个字段是可变的。

信息在扩展时可用,因此您可以通过调用扩展为(define info '(#f set-foo-b! #f)或类似定义的宏来将信息传输到运行时。