Ioke 允许覆盖文字,但不允许新的定义。其工作方式是将文字简单地转换为消息发送,然后您可以像其他任何方法一样覆盖相应的方法。
例如,这是Dict
具有两个条目的 a 的“文字语法”,一个映射 aSymbol
到 a Text
,另一个映射 aSymbol
到 a Number
:
{ :name => "Jörg", :age => 31 }
这实际上被转换为消息发送,对于名为{}
(顺便说一句:列表的工作方式相同,它们对应的消息是[]
)的消息。它完全等同于(如果你愿意,可以这样写):
{}(:name => "Jörg", :age => 31)
现在,=>
实际上只是一个为几乎所有对象定义的运算符,它简单地返回 a Pair
,键(第一个元素)是接收者,值是参数。现在,运营商也只是消息发送,所以这相当于:
{}(:name =>("Jörg"), :age =>(31))
表示文字符号的:
印记也被翻译成消息发送:
{}(:("name") =>("Jörg"), :("age") =>(31))
文本文字被翻译成发送internal:createText
消息:
{}(:("name") =>(internal:createText("Jörg")), :("age") =>(31))
【注:很明显,这里的写法会导致无限递归。事实是,参数internal:createText
显然不是 Ioke Text
,而是平台字符串。即ikj
,对于 Ioke 的 JVM 实现,它实际上是一个java.lang.String
,对于ikc
CIL 实现,它是一个System.String
. 我在这里用三引号表达了这一点。]
{}(:("name") =>(internal:createText("""Jörg""")), :("age") =>(31))
这只是给我们留下了号码,你猜对了,它也是一个消息发送:
{}(:("name") =>(internal:createText("""Jörg""")),
:("age") =>(internal:createNumber("""31""")))
由于一切都是消息发送,因此您可以随意自定义字面量的行为,只需实现相应的方法即可。这是交互式 Ioke REPL 的简短记录iik
:
iik> "Hello"
+> "Hello"
iik> internal:createText = method(raw, super(raw) upper)
iik> "Hello"
+> "HELLO"
Converge 允许强大的编译时元编程,包括称为DSL Blocks的功能。DSL 块是不使用 Converge 语法的代码块。DSL 块如下所示:
$<<xml>>:
<xml>
<literal>here</literal>
</xml>
$<<
其工作方式是和之间的字符串是一个函数的名称,该函数在编译时>>
被调用并作为字符串传递整个 DSL 块(以及一些源代码元数据,如行号、文件名等.) 并返回 Converge Abstract Syntax Tree 的片段。因此,在这种特殊情况下,会有这样的函数:
func xml(dsl_block, src_infos):
// implement an XML parser here ...
return ast
因子允许定义解析词,这些词是影响同一范围内其他词的解析方式的词。Factor 实际上有一个XML 库实现,它使用解析词来获取看起来很像 Scala 的 XML 文字但只是普通的 Factor 代码的语法:
: feed>xml ( feed -- xml )
[ title>> ]
[ url>> present ]
[ entries>> [ entry>xml ] map ] tri
<XML
<feed xmlns="http://www.w3.org/2005/Atom">
<title><-></title>
<link href=<-> />
<->
</feed>
XML> ;
[Factor 简介::
定义一个新词,即第一行定义一个名为的词feed>xml
,它接受一个参数并产生一个结果。单词的前三行从提要对象中提取标题、URI 和条目,并将它们放在堆栈中。<XML
是打开 XML 模式并XML>
再次关闭它的解析词。在 XML 代码中,<->
从堆栈中获取一个值并将其插入 XML。]
通用 Lisp
Common Lisp Reader Macros允许您进入阅读阶段,即接受字符串并生成嵌套列表然后将它们交给编译器/评估器的阶段。它们要求您选择一个唯一的一或两个字符前缀,并且它们是全局的。第一个问题不大,因为我们可以简单地选择<
字符作为前缀,让它看起来很自然。
Perl 6 应该允许您在程序运行时更改语法。Perl 6 具有动态可变语法,这意味着代码在执行时被解析,并且可以更改语法,以便文件中更靠后的其他代码使用新语法进行解析。
奥美达/可乐
在Ian Piumarta 的 COLA 系统之上运行的 Alessandro Warth 的 OMeta 语言允许他们所谓的“特定于情绪的语言”。即,其规范和实现非常轻量级的语言,您可以将它们用于程序中间的一行,然后再次切换到不同的语法。
它被用于Alan Kay 的观点研究所的发明基本新计算技术。一个示例用法是通过设计一种语法与 IETF RfC 中使用的 ASCII 艺术图和另一种用于编写网络协议状态机的语言相同的语言,仅用 200 行代码实现整个 TCP/IP 网络堆栈。然后,网络堆栈的实现简单地包括从 RfC 复制和粘贴 ASCII 图,并将英语状态机描述从 RfC 转换为状态机语言。
(哦,如果您想知道:这 200 行不只是用于 ASCII 图和状态机。它还包括两种语言的解析器和编译器。)
π 编程语言可能也很有趣。