如何在方案中实现Racket风格的结构?

时间:2017-11-04 09:07:52

标签: struct scheme racket

在Racket中,您有机会创建和使用您的结构类型

(define-struct example (a b))

(define var (make-example 1 2))

(example? var)

(example-a var)

我试图在使用宏的方案中实现类似这样的东西,但我在创建具有(make-example 1 2)组合名称的过程时遇到问题,而不是示例可以绝对没事。 有没有办法用这样的名称或其他方法来定义程序来解决这个问题?

1 个答案:

答案 0 :(得分:3)

是否需要为Scheme实现?

无需查看已存在的功能的其他语言。它只有一个不同的名称:记录

它在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是首选。