事先说明,本人刚接触 Groovy 不久,如果有可以优化的地方或者更好的想法,欢迎评论。
昨天看到国外大神写的一篇博客,内容大致是在 Python 中实现 C-style for loop,令人叹为观止。C-style for loop 本身就十分精巧,这激起了我的好奇心,还有没有其他用一种语言的特性来实现另一种语言的语法的例子呢?
于是我瞄上了 Groovy,之前学 Gradle 的时候接触过,了解了 Groovy 的函数如果只有一个参数,调用时不需要加括号。我立刻想到这应该能实现 Python-style for loop。
设想
首先 Python 的 for loop 看起来是这样的:
for a in b:
...
for
和 in
是 Groovy 中的关键字,所以用 _for
和 _in
代替。目标是让这段 Groovy 代码运行起来:
_for 's' _in 'abcde' {
print s + ', '
}
期望输出:
a, b, c, d, e,
但是我翻了下 Groovy 的语法文档,发现这个大括号是一个 Closure
闭包函数(没错我是现学的),而 'abcde' { println s + ', ' }
啥也不是。只能加个冒号,写成 'abcde': { println s + ', ' }
,把这一段作为一个映射传进 _in
方法了。
最终期望的代码:
_for 's' _in 'abcde': {
print s + ', '
}
开搞
边翻文档边查资料边敲代码搞了一个多小时,总算搞出来了。虽然说 Groovy 有些特性非常灵活好用,但是 Java 写习惯了总想用 Java 的语法写 😆。
class _InvokeIn {
String contextArgName
_InvokeIn(contextArgName) {
this.contextArgName = contextArgName
}
def _in(LinkedHashMap<Object, Closure> iterable) {
Map.Entry entry = iterable.entrySet()[0]
entry.value.setResolveStrategy(Closure.DELEGATE_FIRST)
Map map = [:]
entry.value.delegate = map
for (a in entry.key) {
map.put(contextArgName, a)
entry.value.call()
}
}
}
static def _for(String contextArgName) {
return new _InvokeIn(contextArgName)
}
_for 'a' _in 'abc': {
println a + ' --- ' + a.getClass()
}
Gridea 用的库好像没有 Groovy 的语法高亮,所以用了 Java 的
完美运行,虽然编译器找不到变量 a 的定义一直在报警告,但这无伤大雅。真正的不足之处在于这种写法的映射的键只能是字符串,函数调用不让过编译。我写完 range
方法才发现这个坑。还有去不掉的大括号。
2023-02-08