如何为生成的语法提供绑定箭头?
How to provide binding arrow for the generated syntax?
这里是完整的源代码:https://gist.github.com/dannypsnl/d84af132553ab18328844bc1a41389a6
问题是我可以将 (-> a name)
中的 name
引用到 Car-name
吗?在 ->
形式中,它首先获取实例的 class,然后生成一个字符串 <class-name>-<field-name>
并将其转换为 accessor
的语法。最后产生#'(accessor instance)
得到最终结果
一般来说,这意味着我可以从生成的语法中引用原始定义吗?
像这样附加 class 名称和字段名称是一种脆弱的方法。如果我能建议另一种方法,最好使用 struct-field-info
。
如何使用 struct-field-info
的示例:
(define-for-syntax (get-accessor type-id field-symbol)
(define type-info (syntax-local-value type-id))
; both fields and accessors are reversed,
; but that's okay since they're consistent with each other
(define fields (struct-field-info-list type-info))
(define accessors (fourth (extract-struct-info type-info)))
(list-ref accessors (index-of fields field-symbol)))
并在您的 ->
宏中使用它:
(define-syntax-parser ->
[(_ instance field-name)
(define (class-of stx) ....)
(define accessor-id
(get-accessor (class-of #'instance) (syntax->datum #'field-name)))
(with-syntax ([accessor accessor-id])
#'(accessor instance))])
现在,你的实际问题是:
如何提供绑定箭头
假设您想要一个从 class
定义中的字段名称到 ->
表达式中的相同字段名称的绑定箭头,可以使用语法属性 'disappeared-binding
和 'disappeared-use
.
class
定义需要额外的语法 属性 'disappeared-binding
包含 field
标识符,
(define-syntax-parser class
[(_ name field ...)
(syntax-property #'(struct name (field ...))
'disappeared-binding
(stx-map syntax-local-introduce #'(field ...)))])
和 ->
表达式将需要 'disappeared-use
及其 field-name
标识符。
(define-syntax-parser ->
[(_ instance field-name)
(define (class-of stx)
(car (syntax-property (local-expand stx 'expression '()) 'type)))
(define accessor-id
(get-accessor (class-of #'instance) (syntax->datum #'field-name)))
(with-syntax ([accessor accessor-id])
(syntax-property #'(accessor instance)
'disappeared-use
(list (syntax-local-introduce #'field-name))))])
现在,从 (class Car name price)
中的 name
到 (-> a name)
中的 name
以及从 price
中的 price
都有蓝色的语法检查箭头(class Car name price)
到 (-> a price)
中的 price
。
但是,从 (class Car name price)
中的 price
到 (-> b price)
中的 price
有一个紫色问号检查语法箭头,其原因在函数定义(define (foo a b) (+ a (-> b price)))
中,不确定b
是什么类型,所以它并不知道price
是否指的是Car
价格。
这里是完整的源代码:https://gist.github.com/dannypsnl/d84af132553ab18328844bc1a41389a6
问题是我可以将 (-> a name)
中的 name
引用到 Car-name
吗?在 ->
形式中,它首先获取实例的 class,然后生成一个字符串 <class-name>-<field-name>
并将其转换为 accessor
的语法。最后产生#'(accessor instance)
得到最终结果
一般来说,这意味着我可以从生成的语法中引用原始定义吗?
像这样附加 class 名称和字段名称是一种脆弱的方法。如果我能建议另一种方法,最好使用 struct-field-info
。
如何使用 struct-field-info
的示例:
(define-for-syntax (get-accessor type-id field-symbol)
(define type-info (syntax-local-value type-id))
; both fields and accessors are reversed,
; but that's okay since they're consistent with each other
(define fields (struct-field-info-list type-info))
(define accessors (fourth (extract-struct-info type-info)))
(list-ref accessors (index-of fields field-symbol)))
并在您的 ->
宏中使用它:
(define-syntax-parser ->
[(_ instance field-name)
(define (class-of stx) ....)
(define accessor-id
(get-accessor (class-of #'instance) (syntax->datum #'field-name)))
(with-syntax ([accessor accessor-id])
#'(accessor instance))])
现在,你的实际问题是:
如何提供绑定箭头
假设您想要一个从 class
定义中的字段名称到 ->
表达式中的相同字段名称的绑定箭头,可以使用语法属性 'disappeared-binding
和 'disappeared-use
.
class
定义需要额外的语法 属性 'disappeared-binding
包含 field
标识符,
(define-syntax-parser class
[(_ name field ...)
(syntax-property #'(struct name (field ...))
'disappeared-binding
(stx-map syntax-local-introduce #'(field ...)))])
和 ->
表达式将需要 'disappeared-use
及其 field-name
标识符。
(define-syntax-parser ->
[(_ instance field-name)
(define (class-of stx)
(car (syntax-property (local-expand stx 'expression '()) 'type)))
(define accessor-id
(get-accessor (class-of #'instance) (syntax->datum #'field-name)))
(with-syntax ([accessor accessor-id])
(syntax-property #'(accessor instance)
'disappeared-use
(list (syntax-local-introduce #'field-name))))])
现在,从 (class Car name price)
中的 name
到 (-> a name)
中的 name
以及从 price
中的 price
都有蓝色的语法检查箭头(class Car name price)
到 (-> a price)
中的 price
。
但是,从 (class Car name price)
中的 price
到 (-> b price)
中的 price
有一个紫色问号检查语法箭头,其原因在函数定义(define (foo a b) (+ a (-> b price)))
中,不确定b
是什么类型,所以它并不知道price
是否指的是Car
价格。