在Racket中,您有机会创建和使用您的结构类型
(define-struct example (a b))
(define var (make-example 1 2))
(example? var)
(example-a var)
我试图在使用宏的方案中实现类似这样的东西,但我在创建具有(make-example 1 2)
组合名称的过程时遇到问题,而不是示例可以绝对没事。
有没有办法用这样的名称或其他方法来定义程序来解决这个问题?
答案 0 :(得分:3)
无需查看已存在的功能的其他语言。它只有一个不同的名称:记录!
它在SRFI-9 Defining record types中定义,最新的R7RS包含向后兼容性,因此即使在R5RS中也可以选择它。许多R5RS实现都包含它们。 R6RS具有不同的记录实现,这些记录不兼容,此时应该避免使用。
#!r6rs
;; You want to use SRFI-9 rather than the d\included define-record-type
(import (except (rnrs) define-record-type)
(srfi :9))
(define-record-type :example
(make-example a b)
example?
(a example-a set-example-a!)
(b example-b set-example-b!))
(define var (make-example 1 2))
(example? var) ; ==> #t
(example-a var) ; ==> 1
然后最好的方法是尝试自己解决这个问题。要创建一个使用连锁标识符的宏,您无法使用define-syntax
,因为它无法执行此操作。在不作弊的情况下这样做可以让您更好地理解宏。在R6RS中,syntax-case
位于包含的库中,您可以使用datum->syntax
创建标识符:
#!r6rs
(import (rnrs)
(rnrs syntax-case))
(define-syntax make-predicate
(lambda (stx)
(define (s->p sym)
(string->symbol (string-append (symbol->string sym) "?")))
(syntax-case stx ()
[(_ name)
(with-syntax
([predicate (datum->syntax #'name (s->p (syntax->datum #'name)))])
#'(define (predicate v)
(and (pair? v)
(eq? (car v) 'name))))])))
(make-predicate circle)
predicate? ; ==> #<procedure-predicate?>
(predicate? '(predicate x)) ; ==> #t
如果你这样做是#lang racket
而不是标准方案,我认为syntax-case
存在且与此兼容。另外,我建议您阅读Greg Hendershott's fear of macros了解更多球拍特定功能。
好。如果您查看它提供的SRFI-9 spec实现,甚至只需查看#lang racket
implementation of struct at github,或者只需右键单击DrRacket中的符号并选择“打开定义文件”即可打开源代码任何其他文件。这没有秘密,但它可能比你讨价还价的要复杂一些。
注意:请注意,define-struct
不再是#lang racket
中的首选表单,但仅提供向后兼容性。 struct
是首选。