zoukankan      html  css  js  c++  java
  • Scheme语言自定义语法结构时的Literal identifier

    Scheme语言允许用户使用let-syntax等机制自定义特殊的语法结构。定义这种语法结构时使用的Pattern language里有一个不太显眼的Literal identifier,就是下面语法中的<literals>:

    (syntax-rules <literals> <syntax rule> ... )

    Scheme标准R5RS里对Literal identifier的阐释比较晦涩难懂。我根据自己的理解写了一个小例子,大概可以起到补充说明的作用:

    ;;; 不使用Literal identifier时定义语法z
    (define-syntax z
      (syntax-rules ()
        ((z (+ x y)) (+ x y))))
    ;;; 下面一行的结果是 7
    (z (+ 3 4))
    ;;; 下面一行的结果是 -1,在局部改变意义后的加号起了作用
    (let ((+ -)) (z (+ 3 4)))

    ;;; 使用Literal identifier时定义语法z
    (define-syntax z
      (syntax-rules (+)
        ((z (+ x y)) (+ x y))))
    ;;; 下面一行的结果仍是 7
    (z (+ 3 4))
    ;;; 下面这一行报错:z: bad syntax in: (z (+ 3 4))
    ;;; 与定义语法时含义不同(其实是绑定不同)的加号无法应用到这样的语法中
    (let ((+ -)) (z (+ 3 4)))

    有了上面这个例子,R5RS里提到的那个较复杂的例子就比较好理解了:

    (define-syntax cond
      (syntax-rules (else =>)
        ((cond (else result1 result2 ...))
         (begin result1 result2 ...))
        ((cond (test => result))
         (let ((temp test))
           (if temp (result temp))))
        ((cond (test => result) clause1 clause2 ...)
         (let ((temp test))
           (if temp
               (result temp)
               (cond clause1 clause2 ...))))
        ((cond (test)) test)
        ((cond (test) clause1 clause2 ...)
         (let ((temp test))
           (if temp
               temp
               (cond clause1 clause2 ...))))
        ((cond (test result1 result2 ...))
         (if test (begin result1 result2 ...)))
        ((cond (test result1 result2 ...)
               clause1 clause2 ...)
         (if test
             (begin result1 result2 ...)
             (cond clause1 clause2 ...)))))

    在上面这样的cond定义基础上,下面的代码

    (let ((=> #f))
      (cond (#t => 'ok))) ;  =) ok

    将被解释为(这里的=>被视为变量而不是语法元素)

    (let ((=> #f))
      (if #t (begin => 'ok)))

    而不是

    (let ((=> #f))
      (let ((temp #t))
        (if temp ('ok temp))))

    因为局部的=>已经被改变了含义,不能匹配到包含=>的语法规则了。

  • 相关阅读:
    文章用手,产品用心
    斌哥的 Docker 进阶指南
    你是想做个安静的程序员,还是去创个业呢?
    Java 8怎么了:局部套用vs闭包
    Cloud Insight支持阿里云一键接入了,so what?
    Nagios 快速实现数据可视化的几种方式
    uniapp 组件传参
    Vue的Key属性,v-for和v-if,v-if/v-show,v-pre不渲染,v-once只渲染一次
    Vue的Key属性,v-for和v-if,v-if/v-show,v-pre不渲染,v-once只渲染一次
    Vue绑定事件,双向数据绑定,只是循环没那么简单
  • 原文地址:https://www.cnblogs.com/xiaomaohai/p/6157254.html
Copyright © 2011-2022 走看看