struct是Racket中的宏吗?

struct是Racket中的宏吗?,racket,Racket,我记得我在某个地方读到过,它不是宏,而是内置在核心语言中的。类似的事情,我不确定,因为我已经记不起从哪里读到的了。那么struct是否是Racket中的宏呢?如果没有,为什么它内置在核心语言中?宏结构rkt具有 (定义语法(struct stx) (定义(配置有名称?配置) (续) [(syntax?config)(配置有名称?(syntax-e config))] [(pair?config)(或(eq?(syntax-e(car-config))'#:构造函数名称) (eq?(syntax-

我记得我在某个地方读到过,它不是宏,而是内置在核心语言中的。类似的事情,我不确定,因为我已经记不起从哪里读到的了。那么
struct
是否是Racket中的宏呢?如果没有,为什么它内置在核心语言中?

宏<代码>结构rkt具有

(定义语法(struct stx)
(定义(配置有名称?配置)
(续)
[(syntax?config)(配置有名称?(syntax-e config))]
[(pair?config)(或(eq?(syntax-e(car-config))'#:构造函数名称)
(eq?(syntax-e(汽车配置))#:额外的构造函数名称)
(配置有名称?(cdr配置))]
[else#f]))
(带有语法([orig stx])
(语法大小写stx()
[(\uid super id fields.config)
(和(标识符?#'id)
(标识符?#'超级id))
(如果(不是(配置有名称?#'config))
(语法/loc stx)
(定义结构/派生源(id super id)字段#:构造函数名称id.config))
(语法/loc stx)
(define struct/derived orig(id super id)fields.config))]
[(\uid fields.config)
(标识符?#'id)
(如果(不是(配置有名称?#'config))
(语法/loc stx)
(定义结构/派生源id字段#:构造函数名称id.config))
(语法/loc stx)
(define struct/derived orig id fields.config))]
[(id.rest)
(标识符?#'id)
(语法/loc stx)
(定义结构/派生源id.rest))]
[事物]
(raise语法错误#f
“需要结构类型名称的标识符”
stx
#“东西”)

在Racket IDE中,您可以使用
打开定义文件
功能定位源代码(如果可用)。

除了usepla的精彩答案之外,我还想补充:

  • 在Racket文档中,“蓝框”的右上角有一个短语,如
    过程
    语法
    。因为它说的是
    语法

  • 如果您考虑一下
    struct
    的作用,它定义了从struct的名称派生的命名函数。因此
    (struct foo(ab))
    将定义
    foo?
    谓词和访问器
    foo-a
    foo-b
    。普通函数不能定义这样的新命名对象,因此,它必须是宏


  • 我以前回答这个问题时,似乎误解了这个问题。这是对这个问题的回答,意思是:

    结构是内置的和原始的;它们是实施的基础。事实上,大约在2007年,Matthew Flatt评论说,在PLT方案中(当时称为Racket),从某种意义上说,一切都是一个结构:

    >2007年5月31日星期四16:45:25-0700,YC写道:
    >出于好奇-PLT方案是否实际使用struct作为基础
    >复合类型,即在结构顶部实现闭包/etc

    在我看来,一切都是一个结构,但有些东西使用 特殊情况表示,因为它们足够重要。(修订) 极端情况是一个固定值)

    但一个同样有效的答案是:不,不是所有的复合类型都使用 与结构构造函数中的值相同的表示形式

    --


    (define-syntax (struct stx)
    ;
         ; Function that creates compound names using syntax objects
         (define (make-name id . parts)
           (datum->syntax
             id
             (string->symbol
               (apply string-append
                      (map (lambda (p)
                             (if (syntax? p)
                               (symbol->string (syntax-e p))
                               p))
                            parts)))
             id))
    ;
      (syntax-case stx ()
    ;
          ; parse the input and extract the name and variable
          ; this version uses only one variable for simplicity (3)
          [(_ id avar)
    ;
           ; guard to ensure we have an identifier
           (identifier? #'id) 
    ;
           ; Create the names (1)
           (let ((? (make-name #'id #'id "?"))
                 (v (make-name #'id #'id "-" #'avar)))
    
             ; Generate code to define the various functions associated with
             ; the new struct (2)
             #`(begin
                 (define id (lambda (vx) (list id vx)))
                 (define #,? (lambda (x) (eq? (car x) id)))
                 (define #,v (lambda (x) (second x)))))]
             ))
    
    1) 我们必须创建我们将定义的名称:但我们需要使用语法对象来这样做

    2) 我们生成的代码将定义全局命名空间中与新对象关联的所有函数


    3) 在实际版本中,大多数代码处理可用于结构定义的属性。真正的版本还需要处理任意数量的变量、替代形式、默认值等。

    谢谢您的回答。顺便问一下,这个打开的定义文件在DrRacket中位于哪里?在定义窗口中,右键单击源代码中的单词struct。该选项应出现在关联菜单中。如果Racket无法正确解析源代码,它有时就不起作用,因此请在语法正确的s-expr上使用它。请注意,struct扩展为
    define struct/derived
    。新问题:
    define struct/derived
    是宏还是原语?@soegaard:这就是我想问的实际问题。在收到@uselpa完美的答案后,我才意识到我问错了问题。因此,正确的问题应该是构造结构类型的方法是否使用宏实现。我发现答案是否定的。我从
    struct
    一路追踪。您已经到达了定义结构/派生的
    define struct/derived
    ,它也是文件define struct.rkt中定义的宏。@soegaard:查看它的定义,您会发现一个名为
    make struct type
    的过程,该过程在中定义。我想这意味着它是核心语言中的一个原语。我认为OP的问题不是宏与过程,而是宏与内置。啊,我现在明白了。所以我刚刚发布了另一个答案。:)Racket中很少有语法形式不是宏:下面是非宏的完整列表:你认为Flatt持有这种观点是因为
    struct foo
    创建了类型检查函数,
    foo?
    ,考虑
    整数?
    布尔?
    ,没有什么明显的优势,作为一种根本不同的功能,Matthew花了几十年的时间思考概念和实现,所以我不太愿意说出他的话。如果你在邮件列表上问他会更好。:)话虽如此,Racket结构提供聚合、封装、继承和应用程序。康塞