当前位置: 首页 > 工具软件 > Fantom > 使用案例 >

为什么要创建Fantom语言[翻译]

卢知
2023-12-01

标题:WhyFantom 作者:Brian Frank 创建世界:6 Dec 07 版权:Copyright (c) 2007, Brian Frank and Andy Frank 许可:Licensed under the Academic Free License version 3.0


概述

我们真的需要另外一门编程语言吗?显然是,要不然我们也不会建立Fantom!Fantom被设计做为实用语言,让工作容易和有趣的完成。 它不是为了展示前沿理论的学术语言,而是基于坚实的实际经验。它的设计是为了解决我们在Java和C#实际编程中遇到的问题。 虽然我们有很重的Java背景,但是Java的C# .NET有着共同的问题。

移植性

最初我们创建Fantom的原因是为了软件能无缝的同时运行在Java VM和.NET CLR。 现实情况是很多软件组织致力于一个或者其他一些平台。不论你是内部软件开发,还是出售组件,你都倾向于选择一个阵营或者其他一些。

我们构建Fantom解决VM之间的可移植性。Fantom的源码编译为fcode——一种字节码可以方便地转为java字节码或者.NET IL。这个翻译工作是在运行时做的,这使得你可以部署Fantom模块做为单个文件,并且可以同时运行在两个平台。

但是让一个语言运行在Java和.NET是比较容易的部分,事实上已经有很多方案来解决这个问题。难的部分是有一个便携的跨平台API。Fantom提供了一组API来抽象Java和.NET平台。我们认为这是Fantom的主要优点,它给了我们一个机会去开发一套比Java和.NET更优雅和简单的API。

而且,移植性不只是Java和.NET,我们也编译Fantom为浏览器上用的JavaScript,也包括有很多标准库。

因为Fantom被设计来抹平移植性,移植到新平台也很容易。将来的目标平台可能包括iPhone开发的Objective-C,LLVM编译器后端,Parrot虚拟机

优雅的API

美是在观众眼中的,但是我们痴迷于制作美的Fantom API。Java and .NET API很多年开发导致有点纠缠和混乱。 有些API直接就是烂,Java的Calendar类就是典型,用起来很痛苦。你不得不用这些怪异的C风格常量,月份从0开始,星期几从1开始。

一些是本来很繁琐,但更多的Java和.NET API是设计哲学问题。两个平台都倾向于使用很多扩散的小类型,过于抽象也很低效。 Fantom则遵循了不同的哲学——用非常少但很强大的类。一个好的例子是'java.io’包,它包含和60个类和接口。使用的时候需要三四个类,如果你忘记了使用带缓冲的流,那性能就到地狱了。 并且即便用了所有的类,逐行读取一个文本文件你还是要做很多基本工作。 Fantom分解'java.io’包的功能到四个类中:sys::File, sys::Buf, sys::InStream, and sys::OutStream. IO流类默认是被缓冲的,既支持二进制也支持文本,还有很多便利方法。

强类型VS动态类型

工业界开发分裂为强类型和动态类型。坦白说,在我们看来两者都很极端。因此Fantom走在路中间,温和的对待类型系统。

在强类型方面,Fantom要求你去标明字段和方法类型。我们觉得这是好的。编程就是构造各组件之间的良好契约。 类型系统虽然不是完美的,但在自文档化和定义契约方面很好。如果我想写一个方法,需要Str输入,返回Int,应该在代码上表现出来。

除了字段和方法签名类型外,Fantom在其他类型申明方面很自由。类型推断经常被用在本地变量和集合字面量中。

有时候你真的很需要动态类型。Fantom有个关键的特性是能够调用方法用强或动态的方式。 如果你用”.”操作符调用则受到编译器检查和编译为操作指令。如果你用“->”操作符则是动态调用,这时跳过了编译时检查,能用来实现鸭子类型。 “->”操作符实际上是路由到'Obj.trap’方法,能够被重载来做各种花哨的动态设计。

范型

有趣的是Fantom尝试让程序有少的强类型,而Java C#则更多的是强类型。范型阐释了这个意图,这个要素添加到Java C#在不久前。全参数化类型系统引入了很多复杂性,我们很难在价值和复杂性间去发现一个正确的平衡点

当前Fantom用了一个有限制的范型。不支持用户定义范型。但是有三个内建类型'List', 'Map', and 'Func’,能够参数化通过特殊语法。例如,Int列表被声明为'Int[]’,这是一个熟悉的Java C#数组语法。这个权衡刚好,有范型的感觉而没有扩大到所有类型系统。

混入

构造软件经常是个建模问题,怎样映射领域模型到代码。一个面向对象语言,典型地使用类和接口。 Java和C#都使用了相似的途径:类支持单继承,既是类型也有实现。接口支持继承多接口,不支持继承实现代码。

写过Java或者C#的人经常纠结于使用类还是接口。一旦你选择了类,就只能是实现继承。 如果你有一个复杂的领域模型,接口变成了必须,但最终忙碌于写很多通用实现代码。 接口也有版本化的风险,因为你不能添加一个方法而不破坏所有的实现代码。

有很多原因Java C#最终用了类/接口模式。多继承很有力,但有很大的复杂性和肮脏的陷阱。 Fantom使用了一个中间的途径叫做mixin.混入本质上是Java C#接口带有方法实现。 为了避免一些真正多继承的缺陷,混入限制了一些特性,字段不能有实际存储状态。 混入是Fantom工具箱中非常漂亮的特性,当你开始设计你的面向对象模型时。

模块化

软件模块化设计是你在计算机101课程中学到的概念——基本的设计准则。模块化软件让你很容易的分割你的程序为可复用块, 能容易的版本化,移动,和通过清楚依赖关系与其他模块组合。

所谓模块管理在Java中就是JAR文件,基本上就是说Java没有任何模块管理。有个新的JSR可能解决这个问题,但是在过去的十年里,我们生活在类路径地狱中。Java错误的营销决策导致庞然大物J2SE 1.6有44MB。这个庞然大物在子集化到J2ME的进程非缓慢。考虑到辉煌的Java核心技术,很难明白为什么有些要素能成为核心,就是缺少模块化。

.NET设计有模块化,高层次设计为版本化,GAC等。尽管如此,在细节上,.NET遗落了很多需求。 Java选择ZIP作为简单、可扩展的方法打包文件。.NET使用不透明的DLL文件和各种Windows特殊的凌乱东西,让.NET模块文件很难处理。还需要一个单独的,没有任何文档的调试pdb文件获取有意义的堆栈跟踪。

Fantom的模块化叫做pod,Fantom的设计都是围绕他。Pod是版本化单元和部署单元。他们通过明确的依赖关系组合在一起。 像Java一样只是个ZIP文件,容易查看。

命名空间VS部署单元

Java和.NET轻度分离了命名空间和部署单元的概念。例如Java包是用来组织代码到命名空间,但是JAR文件是组织代码为了部署。问题是这两者没有任何的一致性。这加剧了类路径地狱——如果你缺少一个类,但是类名字不能给你任何的线索关于哪一个JAR文件里面有这个类。

整体上对比命名空间和部署单元,能否提供了一个可扩展的,但也没有不必要的复杂性。 Fantom用简单的方法管理命名空间,用一个固定的三层结构"pod::type.slot”.第一层命名空间也就是pod名,同时也是部署单元版本化机制。这个一致性对通过组合pod和类型来构建大系统很重要。例如,给定一个序列化类型"acme::Foo”,很容易的发现你需要那个pod。

面向对象

一个很重要的交换是Java的原始类型,原始类型不是对象,各种难看的特殊情况导致很怪异。 另一方面,原始类型在达到像C一样性能方面很重要,尤其是数值应用。Java也补了一个自动装箱的布丁,但类型系统仍然是断裂的。

.NET对这个问题有非常优雅的值类型,他们是特殊的类型,有原始类型一样的性能,但是仍然清楚的继承自'System.Object'.

Fantom按照.NET值类型模式,有三个特殊的类型'Bool', 'Int', and 'Float’是值类型。 这些类型有相同的性能角色,相对于Java C#中的’boolean','long', and 'double’。 和Java不同的是,类型是干净的继承自’Obj’,有一个统一的继承结构。编译器会在需要时自动实现装箱、解箱。

函数式编程

Java和.NET都提供了一点对函数式编程的支持。.NET提供了委托,函数在Java中被限制到接口,和有一个准闭包支持通过内部类。两个语言也正在向正真闭包和第一类函数迈进。但是他们遗留了巨大的API和代码,这些在没有任何函数式编程思维下设计的。

Fantom被设计为在根本上支持函数式和函数作为第一类对象。闭包是一个语言的关键特性,所有的API使用恰当地函数式和闭包的方法设计。

声明式编程

我们经常需要声明数据结构在我们的代码里面。普通的例子是包括声明list和map。在Java和C#中这么简单的事情却包含很多噪音,非常丑陋冗长。因为这个原因,你经常发现声明有时被Java和C#应用放入XML文件。

Fantom包含声明式编程进入语言。Fantom支持字面量语法对lists, maps, ranges, uris, and durations.Fantom也包含人类可读写的文本序列化语法。序列化语法是干净的编程语言子集——因此你能粘贴一个序列化文件到你的源码作为一个表达式。

并发

很多主要的流式语言今天用共享状态的模型——所有的线程共享相同的内存空间,程序员必须小心的加锁避免竞争条件。如果锁用的不恰当,那么死锁就会发生。这是一个相当低层次的管理并发方法。这也很难去创建可组合的软件组件。

Fantom处理并发用了两种技术:

  • 不可变对象被内建在语言中(线程安全类)
  • Actors模型来传递消息(Erlang风格的并发)

小的改进

一个漂亮的新语言给你一个清洁板去对付所有烦人的小事情(我们构建Fantom去给自己挠痒)。其他Java中让人失望的小东西我们包含在Fantom中:

  • 默认参数:方法能有默认参数——不需要再写样板代码和便利方法了。

  • 类型推断: 本地变量用类型推断,避免所有Java中的噪音。

  • 字段进入(即getter、setter):字段存取被隐式定义——另外一个Java的惯用法导致的噪音。

  • 可空类型: 声明你的意图,参数或返回值中null是否是合法值,而不是指望文档说明。

  • 受检异常:受检异常是邪恶的语法盐。受检异常不可扩展,不能版本化,不允许组合系统——所有的原因见Anders Hejlsberg C#中也不包含受检异常。

  • 数值精度: Fantom不包含支持32-bit, 16-bit,and 8-bit整形和浮点型。只有64位整形和64位浮点型。 这消除了很多和精度有关的问题,例如,文件长度,Unicode支持,非常大的列表。 尽管很多Java和C#实现内部是16位字符和32位整形,但是Fantom API是为未来设计的。

原文地址:http://fantom.org/doc/docIntro/WhyFantom 译文地址:http://my.oschina.net/chunquedong/blog/504229

转载于:https://my.oschina.net/chunquedong/blog/504229

 类似资料: