Marvin's Blog【程式人生】

Ability will never catch up with the demand for it

22 Apr 2021

The Racket Reference阅读笔记【三】Structures相关

The Racket Reference 阅读笔记。

5 Structures

结构类型是一种复合记录类型,由多个子域构成。每个结构类型都有一构造函数,用于生成从例。每个子域可以有对应的访问符和修改符。每个结构类型都有一判断诀,用以判断某个值是否为其从例。

结构类型的子域其实是无须命名的,之所以要为子域提供名字,只是为了错误报告。构造函数要求输入各个子域值,但是自动子域可以被省略,因为这些子域会被初始化为结构类型定义时候提供的常量值。自动子域必须排布在非自动子域之后。

结构类型可以作为另外一个结构类型的子类型。子类型可以作为父类型使用,父类型不可作为子类型使用。因为子类型比父类型有可能新加子域。子类型的子域数目是父类型的超集。

struct语句构造和make-struct-type执行诀通常创建新的结构类型,但是它们也可以访问之前创建(prefab)的结构类型。prefab结构类型只能延续prefab类型,无法拥有守护诀或者辖属。每个名字,父类型,子域数,自动子域数,自动子域值,字符可更改性只构成一种prefab类型。

两个结构从例eqv?为真时其eq?必为真,equal?为真时其eq?也必为真。默认情况下,同一结构类型的两个从例为真对应的前提是无不透明子域,且struct->vector的结果也是equal?的。一个结构类型可以自定义equal?比较,只须提供gen:equal+hash接口。

5.1 Defining Structure Types: struct

过了一遍

5.2 Creating Structure Types

make-struct-type用于创建一个结构体,可以返回五个值:

  • struct-type?
  • struct-constructor-procedure?
  • struct-predicate-procedure?
  • struct-accessor-procedure?,可以根据索引访问某子域
  • struct-mutator-procedure?,可以更加索引修改某子域

如果将inspector是’prefab的话则可以访问prefab结构体。如果super-type不是#f,那么就作为其他结构体的子类型。

返回的结构体的子域个数等于被初始化的子域的数目加上自动初始化的子域数目。子域数目不能超过32768个。props参数是一个连对,其中每个子对的car返回的是一个结构体辖属描述符,子对的cdr可以返回任意值。同一prop可以出现多次,但是值必须相同,否则就会报exn:fail:contract。如果inspector是’prefab,则props必须是null。

如果proc-spec是一个整数或者执行诀,结构类型的从例则表现为执行诀。提供非#f值给proc-spec相当于把prop:procedure赋予props的结尾,如果proc-spec是整型的话,还会将proc-spec添加到immutables中。

immutable提供一个子域位置连对,每项必须唯一,否则会抛出exn:fail:contract。每个元素必须在范围0(包括)到init-field-cnt(排除)之间。

guard参量要么是一个能够接受n+1参量的执行诀,要么是#f。此处的n是构造函数的参量数(子类型的init-field-cnt加上上级类型的init-field-cnt)。如果是执行诀,那么结构体从例化的时候会被调用,且须返回n个值。如果是次级类型,次级类型的guard会被先执行,然后轮到上级类型的guard。如果guard抛出异常,那么结构体创建失败。如果inspector是’prefac,那么guard必须为#f。

如果constructor-name非#f,那么会被作为是生成诀的名字。也会作为object-name的输出。

  • make-struct-field-accessor用于创建子域访问符
  • make-struct-field-mutator用于创建子域修改符

5.3 Structure Type Properties

结构体辖属用于给结构体类型增加信息,增加的适用于每个从例。上级结构中定义的辖属可以在次级结构体中延用,或者遮改。

make-struct-type-property创建一个结构类型辖属,并返回三个值:

  • 辖属描述符,使用于make-struct-type以及struct
  • 辖属判定诀
  • 辖属访问符

如果guard参量是一个执行诀,那么make-struct-type在添附这个辖属的时候会执行它。guard接受两个参量

  • 一个用于这个辖属的值
  • 一个包含新结构体信息的连对,可以通过struct-type-info来提取

guard可以抛出异常来阻止辖属的添附。此异常会阻止make-struct-type返回一个结构体描述符。如果guard是’can-impersonate,那么此辖属的访问符可以通过impersonate-struct来重定向。此选项等同于将can-iimpersonate?参量设置为#t。

可选的supers参量是一个辖属连对,会和当前辖属形成链条,然后添附到目标结构类型中。但

其他条目

  • struct-type-property?,判定是否是结构类型辖属描述符
  • struct-type-property-accessor-procedure?,判定是否是make-struct-type-property生成的访问符
  • struct-type-property-predicate-procedure?,判定是否是make-struct-type-property生成的判定诀

5.4 Generic Interfaces

需要(require racket/generic)

泛型函数使用define-generics构造定义,在结构类型中可使用#:methods提供。

define-generics定义以下名字:

  • gen:id,转换器绑定
  • id?,用于判定结构体类型是否实现了泛型组
  • 各个method-id
  • id/c作为一个合约联合,用来识别结构体实例是否实现了gen:id通用接口。

#:defaults选项只可出现一次。出现时,每个通用函数会在派发到通用方法表失败时,使用default-pred?来派发到默认的方法实现default-impl。

#:fast-defaults只可出现一次。如#:defaults类似,但是在分发之前会检查fast-pred?。主要是为了提供一个快速路径到内建的数据类型,比如连对或者陈列。

#:fallbacks选项只可出现一次。用于定义保底的方法。

#:defined-table选项只可出现一次。若出现,则defined-table-id被定义成一个执行诀,可以接受通用接口的实例并返回一个不可变更的哈希表。这是个废弃的选项,使用#:defined-predicate替代。

#:derive-property可以出现任意次。用于指定结构类型辖属。

  • (struct exn:fail:support exn:fail () #:transparent)
  • (raise-support-error name v)抛出exn:fail:support异常
  • (define/generic local-id method-id)
  • (generic-instance/c gen-id [method-id method-ctc] …)
  • impersonate-generics
  • chaperone-generics
  • redirect-generics

5.5 Copying and Updating Structures

(struct-copy id struct-expr fld-id ...)

 
fld-id	 	=	 	[field-id expr]
 	 	|	 	[field-id #:parent parent-id expr]

5.6 Structure Utilities

  • struct->vector,打印struct:id以及每个子域的值。对应隐匿子域,多个子域可能只用一个opaguge-v表示。
  • struct?,如果struct-info能够爆出目标的结构类型则返回#t
  • struct-type?,对于结构类型标识符返回#t
  • struct-constructor-procedure?,对于struct或者make-struct-type生成的建构诀返回#t
  • struct-predicate-procedure?,对于struct或者make-struct-type生成的判定诀返回#t
  • struct-accessor-procedure?,对于struct或者make-struct-type或者make-struct-field-accessor生成的访问器返回#t
  • struct-mutator-procedure?,对于struct或者make-struct-type或者make-struct-field-mutator生成的变更器返回#t
  • prefab-struct-key,对于prefab结构,返回能够用于make-prefab-struct的短键名
  • make-prefab-struct,创建prefab结构类型的实例,其key可以是一个连对
  • prefab-key->struct-type,通过key和子域数目生成一个prefab结构的类型描述符
  • prefab-key?,对于能作为prefab结构类型键的值返回#t

5.6.1 Additional Structure Utilities

(require racket/struct)

  • make-constructor-style-printer,创建一个打印器
    • 通过unquoted-printing-string可打印关键字
  • struct->list,用于返回结构的子域们

5.7 Structure Type Transformer Binding

struct构造会将结构类型的名字绑定到一个转换器,用以记录其他在这个结构类型中绑定的标识符。这些信息可以通过syntax-local-value访问。

展开时的信息可以用六子连对表示:

  • 结构类型描述符的标识符
  • 结构类型建构诀的标识符
  • 结构类型判定诀的标识符
  • 子域访问符连对,如果最后一个元素为#f,则表示结构可能还有其他元素
  • 子域修订符连对,如果访问符连对有结尾的#f,那么此也要有单体的#f
  • 上级类型标识符,#t表示没有上级类型,#f表示上级类型未知

上述的信息可以通过make-struct-info或者struct:struct-info来建构。或者可以通过prop:struct-info结构类型辖属。其他相关:prop:struct-info,prop:procedure,make-set!-transformer, prop:struct-auto-info, prop:struct-field-info。

使用struct-info?来判定和识别上述信息,使用extract-struct-info来提取上述信息。

(require racket/struct-info)
  • struct-info?
  • check-struct-info?
  • make-struct-info
  • extract-struct-info
  • struct:struct-info
  • prop:struct-info
  • prop:struct-auto-info
  • struct-auto-info?
  • struct-auto-info-lists
  • prop:struct-field-info
  • struct-field-info?
  • struct-field-info-list

(本篇完)

Categories

Tags