Struct 如何在Racket中为编译时提供结构元数据的同时重写结构构造函数?
这可能类似于或之类的问题。但这些问题都不能解决(通过提供)将重载标识符传递出模块边界的问题 例如,假设我有一个要重载构造函数的结构:Struct 如何在Racket中为编译时提供结构元数据的同时重写结构构造函数?,struct,racket,Struct,Racket,这可能类似于或之类的问题。但这些问题都不能解决(通过提供)将重载标识符传递出模块边界的问题 例如,假设我有一个要重载构造函数的结构: (struct fish (weight scales)) (define (make-fish [weight 5] [scales 'blue]) (fish weight scales)) 现在我想提供新的构造函数,使其具有结构的名称,以使其使用完全透明: (provide (except-out (struct-out fish) fish)
(struct fish (weight scales))
(define (make-fish [weight 5] [scales 'blue])
(fish weight scales))
现在我想提供新的构造函数,使其具有结构的名称,以使其使用完全透明:
(provide
(except-out (struct-out fish) fish)
(rename-out (make-fish fish)))
这将在大多数情况下起作用。但也会出现一些细微的小错误
不能再继承结构,也不能使用match
:
(require animals/fish)
(struct shark fish (teeth)) ;; ERROR: parent struct type not defined
(define (describe-animal animal)
(match animal
[(fish weight scales) ;; ERROR: syntax error in pattern
(format "A ~a pounds fish with ~a scales" weight scales)]
[_ "Not a fish"]))
失败:使用匹配扩展器
创建匹配扩展器(链接问题中接受的解决方案)。它无法工作,因为无法将匹配扩展器导出为结构
#lang racket/base
(require
(for-syntax
racket/base
syntax/transformer)
racket/match)
(provide
(except-out (struct-out fish) fish)
(rename-out (make-fish fish)))
(struct fish (weight scales)
#:name private-fish
#:constructor-name private-fish)
(define (make-fish [weight 5] [scales 'blue])
(private-fish weight scales))
(define-match-expander fish
(lambda (stx)
(syntax-case stx ()
[(_ field ...) #'(private-fish field ...)]))
(make-variable-like-transformer #'private-fish))
您将得到以下错误:
结构输出:标识符未绑定到结构类型信息在:鱼
输入:(结构输出鱼) 问题:
那么,我们如何更改结构的构造函数,但仍然允许它在其他结构中作为父结构提供和使用?使用元数据结构,它只是在编译时定义的结构,您可以在编译时将结构定义封装成一个值,该值可用于
匹配和继承
#朗格球拍/球座
(要求
(用于语法)
球拍/球座
球拍/结构信息
语法/转换器)
球拍/比赛)
(提供
(构造出鱼)
(结构鱼(体重秤)
#:命名私人鱼
#:构造函数名称(私人鱼)
(定义(使鱼【重量5】【鱼鳞呈蓝色】)
(私人鱼体重秤)
(从语法开始
我们定义了一个只在编译时存在的结构
;并且可以封装标识符
(结构元数据(结构信息)
#:属性属性:过程(结构字段索引)
#:属性属性属性:结构信息(lambda(self)(元数据结构信息self)))
(定义语法fish;;编译时可以像初始结构一样使用此变量
(元数据)
(设定)变压器程序
(使变量类似于变压器#“使鱼”)
(提取结构信息(语法局部值#'private-fish)))
此结构必须具有特定属性:prop:procedure
,这样它仍然可以作为构造函数使用,prop:struct info
,这样match
和struct
可以在编译时获取结构信息
注
请注意,在Racket的下一个版本中,多亏了Alex Knauth的公关,set-transformer过程将不再需要,您只需调用make variable like transformer