【问题标题】:How to put Lisp/Scheme/Racket symbol at the end?如何将 Lisp/Scheme/Racket 符号放在末尾?
【发布时间】:2020-05-23 14:29:41
【问题描述】:

Lisp/Scheme/Racket 中的表单在第一个位置放置了符号。此代码适用于 Racket:

(define (? a b) (if a (display b) 0))
(? #t "Hello")

但我想在 C/C++ 中模拟 a? b:0 语句,并且问号(符号)应该在末尾,在 a 之后。

如何将?ab按这个顺序排列?

(define (a ? b) (if a (display b) 0))
(#t ? "Hello")

我需要使用define-syntax 之类的吗?

【问题讨论】:

    标签: functional-programming scheme lisp racket infix-notation


    【解决方案1】:

    我对你的问题有三个答案。

    1 不要那样做

    每种语言都有规则、约定和语用。如果你试图强迫它看起来像 C/C++,你的 Racket 体验会很痛苦。您将浪费时间在此类问题上,而不是学习在 Racket 编程模型中思考并使用 Racket 围绕该模型开发的工具。

    举个具体的例子,Racket 的规则是表单(表达式、定义、声明等)以 运算符 开头(如 displaylist+)或句法关键字(如defineif)。该规则消除了许多妨碍可扩展语法的复杂问题。例如,中缀语法与其他特殊形式的优先级是什么?在(lambda ? 5) 中,是lambda 形式还是(错误的)? 形式?

    澄清一下:Racket 绝对鼓励您在 S 表达式、运算符优先语法的范围内使用新的语法形式来扩展语言。

    2 部分解决方案

    Racket 的阅读器对“中缀语法”的支持形式有限。如果您在括号组中的单个术语周围加上点,则读者会将封闭的术语移到前面。所以以下两个术语被读者一视同仁:

    (1 . < . 2)
    (< 1 2)
    

    所以你可以写

    (#t . ? . "Hello")
    

    就我个人而言,我认为这通常会使代码更难阅读。

    3 一个开放的研究课题

    人们正在研究如何扩展 Racket 的语言构建框架,使其能够与基于非 S 表达式的语法很好地配合使用。一个例子是Honu;见论文"Honu: Syntactic Extension for Algebraic Notation through Enforestation。还有其他的,话题还在讨论中。

    【讨论】:

    • 可以想象使用特殊类型的括号来指示这种允许中缀的上下文。像例如{language_name ...... &lt;language code&gt; .... }。这将使它明确。
    • tks,我知道它破坏了规则,但只是尝试一下 :)
    【解决方案2】:

    让我通过覆盖应用程序语法#%app 来提供替代解决方案。以下是类 C 语言中三元运算符的示例:

    #lang racket
    
    (require syntax/parse/define
             (only-in racket [#%app racket:#%app]))
    
    (define-syntax-parser #%app
      [(_ test-expr {~datum ?} then-expr {~datum :} else-expr)
       #'(if test-expr then-expr else-expr)]
      [(_ xs ...)
       #'(racket:#%app xs ...)])
    
    > ((= 42 42) ? "a" : "b")
    "a"
    > ((= 42 0) ? "a" : "b")
    "b"
    

    因为应用语法的优先级最低,所以会优先考虑其他语法:

    > (define-simple-macro (discard-all xs ...) 1)
    > (discard-all ? 42 : 123)
    1
    > (if ? 1 : 2)
    if: bad syntax ;; because if should have exactly three subforms, but the above line has four.
    

    但正如 Ryan 所说,从某种意义上说,这不是一个“好的”Racket 代码,因为它违反了 Racket 约定,没有人(嗯,可能除了你之外)能够理解你的代码。

    【讨论】:

    • tks,这是我想要的语法
    • 当我尝试使用 define-syntax-parser 定义第二种语法时出现错误“模块:标识符的重复定义”
    • 我发现了,不能两次使用define-syntax-parser,将所有语法放在同一个define-syntax-parser块中
    猜你喜欢
    • 2020-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-10
    • 2013-01-28
    • 2014-08-09
    • 2012-06-28
    相关资源
    最近更新 更多