Frostbyte:来自ZeroTurnaround的新JVM语言
ZeroTurnaround很荣耀地发布了Frostbyte ,一种新的基于JVM栈的语言。该语言在出于使用标准Java软件栈与工具的无奈下产生的。此语言很有希望成为过去多年来大量的JVM语言的答案。我们有些许信心并相信Frostbyte将会一并解决软件开发者处理的社会与工程问题。
Frostbyte作为一个基于栈的语言最关键的创新是使用了带括号的波兰表达式语法。取代了以往先将指令压入栈然后再执行一条命令的方式,我们让你能够使用另外一种方式编码,一种让你感觉更加自然的方式。
Frostbyte代码映射非常接近Java字节码,任何代码的系统开销都表现得非常明显。我们择优的挑选了一些能够兼顾语言简洁与功能强健,让你能够替换了大多数的Java程序。
示例
先看看最基本的hello world例子:
fun main := (call echo „Hello World!“)
Frostbyte允许你定义二进制块,它总是用内联方式调用。例如,以下就是一个使用标准库echo二进制块的例子:
chunk echo := (with System (with (get out) (call println ...)))
扩展hello world以后:
fun main := (with System (with (get out) (call println „Hello World!“)))
Frostbyte使用Ropes作为主要的文本类型来取代String,但是Ropes会被转换为String,例如实现已有的Java代码:
fun main (args: Rope[]) := (echo (with „Hello, “ (call concat (args head))))
如果上面的代码保存为hello.fb文件,你可以用fb命令执行它:
> fb hello Jim Hello, Jim
Frostbyte语言是完全国际化的语言。事实上,内建的默认语言是Estonian(爱沙尼亚语),但是语言会被从每一个源文件中检测到。其他的语言提供简单的转换文件--英语(英国)与俄语被默认支持了。例如:
Köis=Rope esik=main kaja=echo võttes=with kutsu=call jätka=concat head=pea
Estonian(爱沙尼亚语)表达的hello.fb如下:
fun esik(argumendid: Köis[]) := (kaja (võttes „Hello, “ (kutsu jätka (võttes argumendid (kutsu pea)))))
你可以为你自己的代码提供翻译映射--转义将会作为声明存储在.class文件中。Frostbyte IDE(即将推出)将会懂得这些转义并根据你选择的语言给与代码自动完成功能。
当然,一个语言介绍没有处理Fibonacci问题是不完整,一下我们有几种方式可以处理。使用if语句与递归是一种方法。我们尝试免去使用if语句,因为它确实是一种退化的模式匹配形式。在Frostbyte一种模式匹配的方法是在函数参数中描述模式并为每一种情况提供分离的函数体。
fun fib (0) := 0 fib (1) := 1 fib (n) := + (call fib (- n 1)) (call fib (- n 2))
正如你所看到的,例如+与*操作符需要call关键字。你也可以用op关键字穿件自己的操作符。
模式匹配也可以以表达式的方式出现在函数体内,一下是一个Estonian(爱沙尼亚语)的示例。我们将要介绍代码块,循环/闭包 和 let(olgu) 关键字。
// get current time as Aeg (Time) type amps praegu: Aeg := pööra (võttes System (kutsu currentTimeMillis)) Aeg // Funktsioon, mis leiab raamatukogust laenutatud raamatud, // mille tagastamisega on hilinetud või mis on rikutud fun leiaHilinenudRaamatud := ( olgu raamatud := võttes Andmebaas (kutsu leiaLaenutatudRaamatud); võttes raamatud (kutsu koonda ( raamat -> ons? (< (võta tähtaeg) (kutsu praegu)) -> (uus Hilinemine raamat) ons? (võta rikutud?) -> (uus Rikkumine raamat) )) )
为了让Estonian(爱沙尼亚语)能看懂,下面列出了翻译映射:
amps=chunk praegu=now Aeg=Time pööra=convert olgu=let koonda=collect (filter + map) ons?=case (introduce a pattern) uus=new raamatud=books raamat=book tähtaeg=due date etc.
复杂示例
让我们来看看更加复杂的关于类的介绍:
class Vector2(x: Double, y: Double) := // dot product op ·(that: Vector2) := + (* (get this x) (get that x)) (* (get this y) (get that y))
我们可以将(get this x)写为(with this (get x)),但是我们也with关键字来缩短:
op ·(that: Vector2) := (with this ( + (* (get x) (get that x)) (* (get y) (get that y)) ))
但更重要的是,如果我们编写 with X or Y,那么X和Y的元组将被放入栈中,任何访问这些域或者方法将会在X和Y两者间交替。
op ·(that: Vector2) := (with this or that ( + (* (get x) (get x)) (* (get y) (get y)) ))
我们可以再看看一切循环的模式,然后将其循环减少:
(with this or that ( + (* dup (get x)) (* dup (get y)) ))
dup 关键字将复制接下来的二进制码指令,但是结合this or that使用意味着第一个(get x)将会 变成 this.x并且下一个(get x将会编程that.x),这是多么屌的特性啊。
二进制码
我敢打赌你一定对Frostbyte生成的二进制码很好奇。让我们再看看展开了的hello world吧。
fun main := (with System (with (get out) (call println „Hello World!“)))
javap将生成这些:
0: getstatic #16; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #22; //String Hello World! 5: invokevirtual #24; //Method java/io/PrintStream.println:(Ljava/lang/String;) 8: return
确实这个转换相当地直接:with System(get out)在这种情况下转换为getstatic。然后“Hello World”变成ldc,然后call
invokevirtual。call总是被转换为invokestatic,invokevirtual或者invokespecial ,除了当它被用来扩充一个chunk ,在这种情况下它会被chunk替换,任何的参数将会被插入到bitemarks(例如在echo chunk中,...便是一个bitmark)
chunk echo := (with System.out (call println ...))
Frostbyte 1.0发展蓝图
该语言仍在发展壮大中,但是我们工作已经很接近第一个公测版了。为了做好1.0版,我们有一些很牛逼的计划:
- First class co-monads
- Kabanov-Raudjärv type inference
- Lazy chunks
- goto statement with labels
然而,我们仍在不断努力的为公用版奋斗着。以下是一些让你能够熟悉该语言以及大版本更新的一些链接: