50万奖金+官方证书,深圳国际金融科技大赛正式启动,点击报名 了解详情
写点什么

JVM 语言 Ioke:直观的语法,Lisp 与 Ruby 的力量

  • 2008-11-28
  • 本文字数:3268 字

    阅读完需:约 11 分钟

核心的 JRuby 开发者及书籍 Practical JRuby on Rails Projects 的作者 Ola Bini 为 JVM 开发了一种名为 Ioke 的新语言。这种强类型、动态、基于原型的面向对象语言的目标在于给予开发者 Lisp 与 Ruby 的力量,同时其拥有优雅、小巧及规则的语法。

Ola 解释了 Ioke 的基本特性

Ioke 是一个强类型、动态、基于原型的面向对象语言。它很容易理解并且内置了对几种宏的支持。对 Ioke 产生重要影响的语言有 Io Smalltalk Self Ruby Lisp (尤其是 Common Lisp )。 Ioke 目前构建在 JVM 上,但我现在正考虑将其编译为 JavaScript 并在 V8 上运行它。

对于 Ioke,我有几个目标,但最明确的一个是创建一种能将 Ruby 和 Lisp 中我所喜欢的那些特性组合起来的语言。结果我发现 Io 已经实现了我所期望的大多数特性,但有些地方实现的还不完美。我还需要一种适合表达内部 DSLs 的语言。我想要一种不会妨碍我,反而会助我完成工作的语言。根据以上几点,我设计出了一个宏系统,有些人可能会觉得这个系统很差劲。

就 Ioke 的设计 InfoQ 向 Ola Bini 提出了几个问题:

InfoQ:看起来 Ioke 的关键特性之一就是它使用了基于原型的继承。相比于占主导地位的基于类的继承,你认为这种继承方式更强大么?

是的,这是 Ioke 的一个特性,但我不确定它是否是一个关键特性。它在很大程度上改变了一些东西的设计。我对此感到很满意,我认为它实际上比基于类的系统要好,既然开发 Ioke 的主要目的是为了我自己的使用,那么我的感觉当然就很重要了。 在 Ruby 中,你可以使用单例类实现基于原型的 OO,同时我发现可以用这种方式清晰地对一些算法建模。从功能上来说这没有什么明显的问题,只要你想,你总可以根据规约实现基于类的 OO。

Ioke 的一个主要指导原则是我所采取的决定并不是为了获得大家的认可。仅仅因为基于类的 OO 占据着主导地位我就要使用它么? 不一定吧。确实有很多原因要求我们使用基于类的 OO,然而历史已经证明对很多应用来说这样做的意义并不大。因此在 Ioke 的开发过程中我尝试了各种可能。

InfoQ:因为在主流的语言中只有 JavaScript 采取了基于原型的继承,你认为这种形式会被大家所理解并应用到实践中么?

实际上我认为基于原型的 OO 要比基于类的 OO 更自然,也更容易理解。我觉得基于类的 OO 是需要学习的,而大多数人都会发现基于原型的 OO 更加直观,前提是他们并没有被人灌输基于类的 OO 的所谓优点。当然,JavaScript 可能并不是最好的参照物,因为语言的基于原型的本质很容易被掩盖在该语言模型的边边角角之下,这意味着大多数开发者实际上并不知道如何以正确的方式使用语言的这些特性。

InfoQ:看起来 Ioke 从一开始就被设计成一种 JVM 语言。你认为在最近一段时期内这会成为新语言的必经之路么?

我现在的想法是没必要从头构建一个新的虚拟机。例如,大多数新语言都带垃圾回收,但我不理解为什么创建这些新语言的人要编写自己的 GC 呢。这需要花费数月的时间,而它只是一项重复的工作而已。看看 Ruby GC 的那些问题吧。显然这种想法对很多其他的事情也适用——尤其是库。因此 Ioke 是一个 JVM 语言(但是 Ioke 的大部分内容是不依赖于 JVM 的。你可以在另一个平台上重新实现这些内容,这很简单。核心内容非常小)。我认为面向 JVM、CLR、Parrott 及 LLVM 的语言都应该这样。从头构建一个新的虚拟机几乎没有任何意义。

InfoQ:你为 Ioke 实现的条件(Condition)系统看起来与 Java 的异常处理系统很相似,但更灵活。你能否提供几个例子来更好的说明其价值呢?

你可以认为异常所具有的功能是条件系统的一个子集。有两点区别:其一是从协议和抽象的角度来看。异常所处理的东西不见得非得是异常或是错误,警告也行。大多数动态语言都有基于 ad-hoc 日志的警告系统。但是如果你想做其他事情呢?在 Ruby 中,你可以改变 warn 方法以抛出一个异常。然而这仍然表示警告和异常的处理方式存在着分歧。要么采取系统拦截、要么采取线程拦截。所有这一切仅仅是表面上的不同而已,本质上是一回事。 条件可以将这一切统一起来。他们为上面提到的那些事情提供了一致的协议。

条件所提供的功能是双重的。首先就是 restart,它实际上几乎是完全独立的。

所谓 restart 就是可以注册到块中的一些东西。它基本上就是调用 restart 时所执行的一些代码块。然后有一些方法会去调用命名的 restart,找到所有活动的 restart。restart 几乎可以看作是一种异常机制。从范围上来说它是动态的。

凭借条件我们可以为某些可能发生的事情注册处理器。当条件发生时,处理器可以选择去处理它或是把它交给下一个处理器处理。然而这并不是堆栈展开(unwinding the stack)(至少现在不是)。如果某个处理器想去处理某个条件(处理器也是一块代码),处理器上下文中相应的代码就会被执行,执行的位置是动态的,就在条件第一次发生的地方。这意味着几个方法从某个条件发生的地方所调用的处理器实际上可以在相应的上下文中进行叠加。

这没什么好奇怪的,你可以在纯 Ruby 环境下完成这件事。但如果标准库没有提供相应的支持,那效果就要大打折扣了。

在 Common Lisp 中,这非常强大。当你以交互的方式使用 Common Lisp 时,条件的默认处理器会将你带到调试器中。该调试器运行在错误发生的上下文中,同时它可以完成处理器所能完成的事情——包括为变量提供新的值等等。该调试器无需做任何特别的事情,实际上它只是条件系统一个具体的用例而已。

这实在是太强大了。

InfoQ:你认为 Ioke 符合维护和重构的标准么?它是动态的,又具有强类型,你是怎么看的?

这很难说。既然它很简洁,同时又为这种简洁性提供了强大的特性,那么它应该很容易维护。同样的原因,自动化的重构现在还不完善。 就像 Lisp 一样,Ioke 提供了语法抽象。有两种形式,第一种是宏,它就像是具有延迟参数的方法调用一样,这些参数可用特殊的方式计算出来。另一种是语法,它与 Common Lisp 的 defmacro 差不多。这两种方式为创建新的控制结构和定义新的抽象提供了可能。语言本身是足够强大的,你可以用其创建自己的方法类型。如果你不喜欢关键字参数,你可以定义一种新的不包含关键字参数的方法类型。当前 Ioke 中的 DefaultMethod 可以用纯 Ioke 实现出来,使用宏就行。

InfoQ:对于 Ioke 的语法来说,你遵循了 Lisp 和 Smalltalk 的方式,例如,space 的使用。一些人可能会觉得这么做会令那些熟悉 C 语言代码风格的开发者敬而远之。你觉得是这样的么?

很早以前我就已经是一个 C、C++ 及 Java 开发者了,我并没有觉得哪里不舒服。Ioke 的语法确实很麻烦,之前有很多人都觉得这对于强大的抽象来说是个绊脚石。当你有一个像以上那些语言的 AST 时,你会发现要想实现语法宏是多么的不方便。语法占很大的比重,因为他们很不统一。 因此大家可能在一开始会觉得它不那么自然,但我真的很喜欢它,我相信你也会的。比如我发现 Ioke 的可读性就非常好,而 Java 就不行了。Ioke 中没有太多的标点字符妨碍我们阅读。下面对 Java、Ruby 及 Ioke 进行了一下比较:

复制代码
Arrays.asList("foo", "bar", "quux")
.map(new Function<String, Pair<String, Int>>(){
public Pair<String, Int> call(String str){
return new Pair<String, Int>(str, str.length());
}}).select ..... // this gets too long, ok?
["foo", "bar", "quux"].map {|str| [str, str.length]}.select {|n|  n[1] > 3}
["foo", "bar", "quux"] map(str, [str, str length]) select(second > 3)

在这个例子中,Ruby 的区别不那么明显,但它实际上也有很大的差别。我发现当方法用空格分隔开时阅读起来会更方便。使用圆点来终止表达式同样会造成很大的差别。

因此,作为 Lisp 的使用者,这么说有点另类,但语法真的是很重要。我为 Ioke 设定的目标就是让其拥有 Lisp 和 Ruby 的力量,同时保持其语法优雅、小巧及规则。

如果你对 Ioke 的开发感兴趣,你可以从 Ola’s git 的仓库上得到其源码或者是访问其项目主页

你还可以从InfoQ 上得到关于编程语言 JVM Ruby方面的更多信息。

查看英文原文: The Ioke JVM Language: The power of Lisp and Ruby with an intuitive syntax

2008-11-28 11:412072
用户头像

发布了 88 篇内容, 共 271.9 次阅读, 收获喜欢 9 次。

关注

评论

发布
暂无评论
发现更多内容

计算机网络基础(十九)---传输层-TCP的拥塞控制

书旅

TCP 协议栈 网络层

Linux数据流重定向

wangkx

Linux linux操作

二叉树的遍历(前序、中序、后序)

申屠鹏会

算法 二叉树 Go 语言

TCP/IP学习(1):创建套接字

申屠鹏会

TCP 网络 TCP/IP

TypeScript 设计模式之观察者模式

Geek_z9ygea

typescript 大前端 设计模式

k8s-client-go源码剖析(一)

远鹏

开源 Kubernetes 容器 源码剖析 Go 语言

跟我一起基于 Karma 搭建一个测试环境 (中)

Jack Q

大前端 Karma 测试框架搭建

随着区块链技术的成熟,全球企业开始拥抱公共区块链

CECBC

区块链技术 公共区块链

开发者关系(DevRel)的新手指南

开发者关系

开发者关系 开发者运营 技术运营 开源社区

360 Atlas生产环境使用心得

心平气和

MySQL 分库分表 Proxy Atlas

突破内存限制的高性能排序

架构师修行之路

范型的下一步

申屠鹏会

翻译 Go 语言

troubleshoot之:GC调优到底是什么

程序那些事

性能分析 jvm调优 GC调优

Linux后台开发高频题目总结

我是程序员小贱

Linux之crontab命令

wangkx

Linux crontab

散列表高级应用之把用户访问记录优化到极致

架构师修行之路

哈希表 数据结构与算法

在龙门吊上,看到破浪而来的智能时代

脑极体

Mac JetBrains(IDE)常用快捷键

wangkx

JetBrains 快捷键

9个典型的开发者关系面试题

开发者关系

开发者关系 开发者运营 技术运营 开源社区

定义“开发者关系”

开发者关系

开发者关系 开发者运营 技术运营 开源社区

同行分析优化

誓约·追光者

Sparksql 优化

平时开发Git常用的小技巧

zui.zhang

git rebase

瀑布模型总结

我是程序员小贱

深挖502和504

书旅

nginx 服务器 HTTP 状态码

翻译:如何编写Golang代码(How to Write Go Code)

申屠鹏会

翻译 Go 语言

学习总结 -- Week 10

吴炳华

物流与区块链加供应链的现状与未来趋势

CECBC

行业资讯 区块链技术 供应链

RPC原理

石刻掌纹

今天给二叉树加个BGM,二叉树唱歌了!

我是程序员小贱

webbench源码阅读

我是程序员小贱

为什么你做的 Excel 表不好用?

Tony Wu

效率工具 产品设计 Excel ER图

JVM语言Ioke:直观的语法,Lisp与Ruby的力量_Java_Dionysios G. synodinos_InfoQ精选文章