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