The Scheme Programming Language 读书笔记,chapter 8, 9.

Chapter 8. Syntactic Extension

语法扩展(syntactic extensions)也就是宏(macros)用于扩展程序的语法,消除重复模式。

语法扩展形式多为(keyword subform ...)。语法扩展识别关键字,然后将其关联到具体的转换器(transformer)。定义语法扩展可以使用define-syntaxlet-sntax以及letrec-syntax。转换器可以使用syntax-rules来创建,生成的转换器允许使用模式识别来扩展语法。转换器也可以是普通的执行诀,接受一个参数,然后执行某些计算。这种情况下,syntax-case通常用于解构输入,syntax通常用于构建输出。

identifier-syntax以及make-variable-transformer执行诀可以用来创建这样的转换器,它们接受单例标识符,并且支持向这些标识符赋值。前者允许简单的基于syntax-rules的模式,后者允许任意计算。

语法扩展在求值的时候会被语法展开器展开成核心语法形式。展开的过程支持文法作用域。

本章描述的语法扩展机制属于"syntax-case"系统的一部分。一个可移植的实现在http://www.cs.indiana.edu/syntax-case/可以获取。

Section 8.1. Keyword Bindings

  • 语法(define-syntax keyword expr),其中expr的求值结果必须是一个转换器。
  • 语法(let-syntax ((keyword expr) ...) form1 form2 ...)
  • 语法(letrec-syntax ((keyword expr) ...) form1 form2 ...)

Section 8.2. Syntax-Rules Transformers

  • 语法(syntax-rules (literal ...) clause ...)
  • 语法_
  • 语法...
  • 语法(identifier-syntax (id1 tmpl1) ((set! id2 e2) tmpl2))

Section 8.3. Syntax-Case Transformers

syntax-case是比syntax-rules更通用的转换器定义语法,它甚至可以用来扭曲文法作用域。所有syntax-rules都可以用syntax-case来定义。

syntax-case机制下,转换器是一个单参数的执行诀。这个参数叫做syntax boject,用于表示待处理的形式。返回的值是一个语法对象,用于表示输出形式。

一个语法对象可以是下列任意形式:

  • 一个类型非对子,串列,名号的值

  • 一对语法对象

  • 一串语法对象

  • 一个wrapped对象

  • 语法(syntax-case expr (literal ...) clause ...)

  • 语法(syntax template)

  • 语法#'template等价于上一条

  • 执行诀:(identifier? obj)

  • 执行诀:(free-identifier=? identifier1 identifier2)

  • 执行诀:(bound-identifier=? identifier1 identifier2)

  • 语法(with-syntax ((pattern expr) ...) body1 body2 ...)

  • 语法(quasisyntax template ...)

  • 语法#``template

  • 语法(unsyntax template ...)

  • 语法#,template

  • 语法(unsyntax-splicing template ...)

  • 语法#,@template

  • 执行诀(make-variable-transformer procedure)

  • 执行诀(syntax->datum obj)

  • 执行诀(datum->syntax template-identifier obj)

  • 执行诀(generate-temporaries list)

思考,所谓语法,就是将一些词赋予组织意义,用来黏合句子。

Section 8.4. Examples

Chapter 9. Records

如何定义record类型。

Section 9.1. Defining Records

define-record-type用于创建record类型,例如:(define-record-type point (fields x y)),会自动创建以下寒素:

  • (make-point x y)
  • (point? obj)
  • (point-x p)
  • (point-y p)

字段默认是不可改的,如果要将它们设为可改的,需要明确说明:

(define-record-type point (fields (mutable x) y))

然后就可以使用(point-x-set! p x)来做修改。

相关语法:

  • (define-record-type record-name clause ...)
  • (define-record-type (record-name constructor pred) clause ...)

相关子句

  • (fields field-spec ...)
  • (parent parent-name)
  • (nongenerative)
  • (nongenerative uid)
  • (protocol expression)
  • (sealed #t)
  • (opaque #t)
  • (parent-rtd parent-rtd parent-rcd)

语法:

  • fields
  • mutable
  • immutable
  • parent
  • protocol
  • sealed
  • opaque
  • nongenerative
  • parent-rtd

思考:语法,即在语义之前解析的一层规则

Section 9.2. Procedural Interface

(make-record-type-descriptor)也可以用来创建新record类型。这个执行上的接口比语义上的接口更灵活,但是可能会降低可读性和有效性。

执行诀:

  • (make-record-type-descriptor name parent uid s? o? fields)
  • (record-type-descriptor? obj)
  • (make-record-constructor-descriptor rtd parent-rcd protocol)
  • (record-type-descriptor record-name)
  • (record-constructor rcd)
  • (record-predicate rtd)
  • (record-accessor rtd idx)
  • (record-mutator rtd idx)

Section 9.3. Inspection

如何从记录类型表述符获取信息。

相关执行诀:

  • (record-type-name rtd)
  • (record-type-parent rtd)
  • (record-type-uid rtd)
  • (record-type-generative? rtd)
  • (record-type-sealed? rtd)
  • (record-type-opaque? rtd)
  • (record-type-field-names rtd)
  • (record-field-mutable? rtd idx)
  • (record? obj)
  • (record-rtd record)

(本篇完)