我想用一个非常短的语法编写一个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?
答案 0 :(得分: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。它有一个特别以宏观为导向的世界观(见this blog post,当Racket被称为“PLT计划”时写回。)