Marvin's Blog【程式人生】

Ability will never catch up with the demand for it

25 Feb 2021

The Scheme Programming Language读书笔记【八】

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)

(本篇完)

Categories

Tags