2

我想用非常短的语法编写一个 DSL,用于我注意到对编程非常重要的两件事,函数和哈希。这是我的设计:

创建一个哈希:

(a:1 b:2 c:3)
Same as JavaScript's: {a:1,b:2,c:3}

创建有序哈希,省略键:

(x y 5) 
Same as JavaScript's: {0:'x', 1:'y', 2:5}

创建一个匿名函数:

(a?)
Same as JavaScript's: (function(x){ return x.a; })
Example application:
    ((test a? b?) (a:1 b:2 c:3))
    >> Outputs (test 1 2)

嵌套函数:

(a? a?') 
Same as JavaScript's: (function(obj1){ return function(obj2) { return [obj1.a,obj2.a]; }; })
Example double-application:
    (((a? a?') (a:1)) (a:2))
    Is reduced to: ((1 a?) (a:2))
    Then outputs: (1 2)

哪种语言适合实现这种 DSL?

4

1 回答 1

5

这听起来很像您想要一种具有强大宏系统的语言,例如某种 Scheme。宏恰好允许这种语法扩展,其中原始语言的代码片段可以嵌入到您提出的新形式中(我假设您希望能够说(a:1+1 b:2*2),等等)。此外,宏系统不会像外部预处理器那样使构建过程复杂化或破坏错误消息位置。

但是有一个坏消息,那就是我所知道的任何(非深奥)语言都没有足够的语法空间来提供您指定的确切语法。

这是我想出的语法:

哈希:

(: a 1 b 2 c 3)
; or, more clearly
(: (a 1) (b 2) (c 3))

索引键哈希:

(:lst 'x 'y 5)

(如果您允许在哈希的 RHS 上使用裸词,那么您将很难引用变量,所以我假设您不希望这样)

匿名属性访问函数:

(anon. a)

与前者一样,但通过对它们进行柯里化然后返回一个列表来获取多个参数:

(anon. a a)

好消息是,您不需要编写词法分析器或解析器,也不需要在构建系统中乱搞来将这种语法添加到 Scheme。就几行代码,导入语法就像导入函数一样。

第一个宏(名为:)写起来非常简单:

(define-syntax-rule (: (k v) ...)
  (make-hash `((k ,v) ...)))

第二个(名为:lst)更难,因为您需要生成索引。它可能不到十行代码,但我懒得写......

第三个宏 ( anon.) 有点不平凡,但很有趣,所以它是:

(define-syntax anon.
    (syntax-rules ()
      ((anon. attr attrs ...) 
       (lambda (x) (cons (hash-ref x 'attr) (anon. attrs ...) )))
      ((anon.)
        empty)))

(请注意,为了保持一致性,我假设您希望anon.始终返回一个列表;否则需要syntax-rules为特殊情况添加一个额外的子句。)我不确定这anon.是否真的是一个有用的宏,但那是在你和你的代码库之间。

如果你想用宏来破解,我建议你试试我最喜欢的 Scheme 风格,Racket。它有一个特别面向宏观的世界观(参见这篇博文,写在 Racket 被称为“PLT 方案”时)。

于 2012-09-05T04:47:19.393 回答