我希望我们在Java中拥有十大锡兰语言功能

当Hibernate“完成”并且功能完善并且需要新的挑战时,该怎么办? 对。 人们创建了一种新的JVM语言,称为Ceylon

2013年11月12日, Ceylon 1.0.0终于发布了 ,我们祝贺Red Hat的整个团队在看起来非常有希望的新JVM语言方面所取得的成就。 锡兰与Scala的竞争将是一个小挑战,但是有许多非常有趣的功能使它与众不同。

实际上,这种语言具有许多有趣的功能,因此很难撰写有关10个最有趣的功能的博客文章。 选择哪一个? 在Google Plus上,我与加文·金(Gavin King)进行了简短的交谈,加文·金( Kavin King)也带来了我们的冬眠罗斯·泰特Ross Tate )也参与了JetBrains的Kotlin的研究卢卡斯·里兹Lukas Rytz )是EPFL Scala的博士研究生和提交人,现在在Google Dart工作 。 我希望那些语言Uberdesigners可以帮助我找到他们拥有的10种最激动人心的语言功能,而我们的Java开发人员则没有。 现在我有20个有趣的。 我一定会为此写一篇后续文章。

我观察到加文·金(Gavin King)和其他人非常热情和知识渊博。 在我于2013年2月在瑞士伯尔尼的 JUGS上的StéphaneÉpardaud第一次听说锡兰时,我就已经有了这种印象,他是RedHat另一位热情的工程师( 请参阅此处的演示幻灯片 )。

无论如何,足够多的人是谁。 这是我希望在Java中获得的个人十大锡兰语言功能列表:

1.模块

在Java中, Jigsaw已被推迟了约34次,而我们现在才关闭Java 8 GA! 是的,我们有OSGi和Maven,它们在运行时(OSGi)或编译时(Maven)的依赖关系管理方面都工作得很好。 但是,使用Apache Felix比较这个黑魔法Maven / OSGi配置…

<plugin>
  <groupId>org.apache.felix</groupId>
  <artifactId>maven-bundle-plugin</artifactId>
  <version>2.1.0</version>
  <extensions>true</extensions>
  <executions>
    <execution>
      <id>bundle-manifest</id>
      <phase>process-classes</phase>
      <goals>
        <goal>manifest</goal>
      </goals>
    </execution>
  </executions>
  <configuration>
    <supportedProjectTypes>
      <supportedProjectType>
        jar
      </supportedProjectType>
    </supportedProjectTypes>
    <instructions>
      <Bundle-SymbolicName>
        org.jooq
      </Bundle-SymbolicName>
      <Export-Package>*</Export-Package>
      <Import-Package>
        javax.persistence;resolution:=optional,
        org.apache.log4j;resolution:=optional,
        *
      </Import-Package>
      <_versionpolicy>
        [$(version;==;$(@)),$(version;+;$(@)))
      </_versionpolicy>
    </instructions>
  </configuration>
</plugin>

……锡兰的这幅画:

"The second best ever ORM solution!"
license "http://www.gnu.org/licenses/lgpl.html"
module org.hibernate "3.0.0.beta" {
    import ceylon.collection "1.0.0";
    import java.base "7";
    shared import java.jdbc "7";
}

最后,可以在jar级别上控制事物,包括程序包的可见性。 仅用几行代码。 Java,请集成Ceylon的强大模块支持

值得一提的是Fantom是另一种具有集成模块支持的语言。 参见JodaTime在2011年Devoxx上的Stephen Colebourne的演讲: “ Scala的Fantom光年还 吗?” 。 Stephen还为我们带来了ElSql,这是一种用于Java模板的新外部SQL DSL。

2.顺序

这是我第一次看到这种对类型安全语言的序列的一流支持。 锡兰不仅提供了各种收集文字,而且还知道这些构造的类型。 具体来说,您可以这样声明一个Iterable:

{String+} words = { "hello", "world" };

注意文字的符号。 它的类型为{String+} ,表示它至少包含一个元素。 该类型与{String*}赋值兼容,后者表示可能为空的序列。 很有意思。

通过这样支持数组文字来继续:

String[] operators = [ "+", "-", "*", "/" ];
String? plus = operators[0];
String[] multiplicative = operators[2..3];

…或元组文字:

[Float,Float,String] point = [0.0, 0.0, "origin"];

还要注意范围文字2..3 ,它允许从原始数组中提取子数组。 锡兰有如此多的序列优势!

还要注意String?问号String? ,这是锡兰宣布…的方式

3.可空类型

尽管Scala 知道Option类型,Haskell知道Maybe类型,并且Java 8试图通过添加新的,不可执行的Optional类型进行竞争 ,但是Ceylon对可为空的东西有一个非常简单的概念。 如果类型后面有问号,则它可以为空。 否则,它不为null。 总是。

为了将可为空的类型转换为不可为空的类型,您必须显式检查:

void hello() {
    String? name = process.arguments.first;
    String greeting;
    if (exists name) {
        greeting = "Hello, ``name``!";
    }
    else {
        greeting = "Hello, World!";
    }
    print(greeting);
}

注意exists运算符。 它定义了一个新的作用域,在该作用域中, name变量不为null,即从String?提升String?String 。 卢卡斯·里兹(Lukas Rytz)认为,这种局部作用域类型的提升通常称为流敏感类型化,这已在Whiley语言中被观察到。

如果您省略exists检查,那么在那里的字符串内插会出现编译错误。 还有其他有用的构造可以执行临时类型转换:

String greeting = "Hello, " + (name else "World");

else子句的行为类似于SQL COALESCE()函数,甚至可以链接。 阅读有关锡兰的可为空的善意的更多信息。

4.默认参数

OMG,我希望我们能用Java做到这一点。 我们认为,每次我们重载方法时,为什么不仅仅支持默认参数,例如PL / SQL?

void hello(String name="World") {
    print("Hello, ``name``!");
}

我无法想到为什么语言不会具有PL / SQL之类的命名和默认参数的单一原因:

-- One of the parameters is optional
CREATE PROCEDURE MY_PROCEDURE (
  P1 IN NUMBER,
  P2 IN VARCHAR2 := 'ABC',
  P3 IN VARCHAR2
);

-- Calling the procedure
MY_PROCEDURE(
  P1 => 1,
  P3 => 'XYZ'
);

因此,这是在大多数情况下避免方法重载的一种方法。 当我们要处理替代的,不兼容的类型时,方法重载仍然很繁琐。 但是锡兰不知道,在锡兰不是……

5.联合类型

好的,这有点深奥。 Ceylon的创建者真的很想摆脱方法重载,部分原因是Ceylon也可以编译为JavaScript ,而JavaScript不知道函数重载。 实际上,根本无法在Ceylon中重载方法。 为了能够与Java互操作,需要引入联合类型。 联合类型String|Integer可以是String或Integer。 那里有方法重载!

void printType(String|Integer|Float val) { ... }

printType("hello");
printType(69);
printType(-1.0);

为了“解开”联合类型,您可以通过执行类似于Java的instanceof类型检查来再次利用val参数的流敏感类型

void printType(String|Integer|Float val) {
    switch (val)
    case (is String) { print("String: ``val``"); }
    case (is Integer) { print("Integer: ``val``"); }
    case (is Float) { print("Float: ``val``"); }
}

在此范围内,例如,编译器知道val的类型为String 。 这继续允许疯狂的东西,例如枚举类型 ,其中一个类型可以同时是一个或另一个东西:

abstract class Point()
        of Polar | Cartesian {
    // ...
}

请注意,这是由多重继承,其中这样一个非常不同的Point两个 Polar Cartesian 。 但这还不是全部。 锡兰也有……

6.交叉点类型

现在,您可能已经猜到了,这是联合类型的确切逆,而Java的泛型实际上也支持这种类型。 在Java中,您可以编写:

class X<E extends Serializable & Comparable<E>> {}

在上面的示例中, X仅接受Serializable Comparable类型参数。 在锡兰,这很疯狂,您可以在其中为本地声明的交叉点类型分配值。 事实并非如此! 在我们的聊天中,Gavin向我指出了这一令人难以置信的语言功能,其中联合/交叉点类型可以与流敏感类型交互以形成以下内容( 由于Ceylon 1.2引起 ):

value x = X();
//x has type X
if (something) {
    x = Y();
    //x has type Y
}
//x has type X|Y

有道理吧? 所以我问他,是否可以再与Z相交,加文说,是的! 可以完成以下操作:

value x = X();
//x has type X
if (something) {
    x = Y();
    //x has type Y
}
//x has type X|Y
if (is Z x) {
    //x has type <X|Y>&Z
}

之所以这样,是因为类型交集也以非常有趣的方式与泛型交互。 在某些情况下, X<A>&X<B>可以与X<A&B> 。 换句话说,交集(和并集)与泛型一起分布 ,就像加法与乘法一样(在对“就像”的非正式理解中)。 如果您愿意为此目的研究语言规范,请参见§3.7.2主体实例化继承

现在,联合和相交类型会变得非常讨厌并且难以重用。 这就是锡兰拥有……

7.输入别名

有没有其他编程语言想到过这个很棒的功能? 即使您不支持联合和/或交叉点类型,这也是如此有用。 考虑一下Java的泛型。 随着泛型的出现,人们开始写类似以下内容的东西:

Map<String, List<Map<Integer, String>>> map = // ...

可以说两件事:

  • 泛型对于Java库非常有用
  • 执行上述操作时,泛型变得非常冗长

这就是类型别名起作用的地方。 看看这个例子:

interface People => Set<Person>;

这里的要点是,即使某些冗长的类型经常被重用,您也不需要为上述内容创建显式的子类型 。 换句话说,您不想滥用子类型多态性作为“简化”通用多态性的捷径

可以将别名视为一个可扩展的宏,该宏可以相互分配兼容。 换句话说,您可以编写:

People?      p1 = null;
Set<Person>? p2 = p1;
People?      p3 = p2;

因此,正如“别名”一词所暗示的那样,您并不是在创建新的类型。 您只是给复杂类型一个更简单的名称。 但是比类型别名更好的是……

8.类型推断

许多其他语言都具有这种功能,Java在一定程度上也是如此,至少就涉及泛型而言。 Java 8在允许使用泛型进行类型推断方面又走了一步 。 但是Java与Scala或Ceylon之类的语言对本地变量的处理方式相去甚远:

interface Foo {}
interface Bar {}
object foobar satisfies Foo&Bar {}
//inferred type Basic&Foo&Bar
value fb = foobar; 
//inferred type {Basic&Foo&Bar+}
value fbs = { foobar, foobar };

因此,此示例显示了许多组合的功能,包括类型约束,序列类型,联合类型。 使用如此丰富的类型系统,支持此级别的类型推断非常重要,其中value关键字指示您不想(或您不能)显式声明类型。 我真的很想在Java 9中看到这一点!

阅读有关Ceylon出色的类型推断功能的更多信息。

9.申报地点差异

现在,此功能可能很难理解,因为Java的泛型已经非常难以理解。 我最近阅读了Ross Tate,Alan Leung和Sorin Lerner的一篇非常有趣的论文,内容涉及通配符给Java泛型带来的挑战: 在Java的Type System中驯服通配符 。 泛型仍然是一个非常活跃的研究主题,无论是研究人员还是语言设计人员都无法完全同意使用站点的差异(如Java)还是声明位置的差异(如C#,Scala或Ceylon)对于主流程序员而言确实更好。 谈论差异的较旧语言是EiffelOCaml

Microsoft已在C#中引入了声明站点差异。 我会引用Wikipedia中示例 ,它很容易理解。 在C#中, IEnumerator接口具有协变泛型类型参数:

interface IEnumerator<out T>
{
    T Current { get; }
    bool MoveNext();
}

这只是意味着以下将起作用:

IEnumerator<Cat> cats = ...
IEnumerator<Animal> animals = cats;

这与Java的使用站点差异完全不同,在Java中,上述内容无法编译,但以下内容可以编译:

Iterator<Cat> cats = ...
Iterator<? extends Animal> animals = cats;

声明站点协方差的主要原因是简单的事实,即在使用站点上冗长程度大大降低了。 通配符是Java开发人员的主要苦恼,它们引发了许多Stack Overflow问题,因为这是有关本地范围的通配符的问题:

// Given this interface:
public interface X<E> {
    E get();
    E set(E e);
}

// This does not compile:
public void foo(X<?> x) {
    x.set(x.get());
}

在Ceylon语言之旅中可以看到, Ceylon泛型支持声明站点差异 ,就像C#和Scala一样。 有趣的是,由于两种类型的方差支持都有其优缺点,因此这些事情如何演变,同时Ross Tate提倡混合站点方差 ,这对于Java语言而言确实是一个很好的补充!

现在这有点复杂,所以让我们看一下一个简单却很棒的功能来汇总……

10.功能和方法

斯特凡·埃帕多(StéphaneÉpardaud)概述的主要内容之一是,锡兰语言是一种非常普通的语言。 在考虑Ceylon如何对待函数(和方法,它们是类型成员函数)时,这一点尤其明显。 我可以在任何地方放置函数。 考虑以下示例:

Integer f1() => 1;
class C() {
    shared Integer f2() {
        Integer f3() => 2;
        return f3();
    }
}

print(f1());
print(C().f2());

在以上示例中,

  • f1()是包级函数(非常类似于Java中的“全局”静态函数)
  • f2()C类的常规方法
  • f3()f2()方法中的局部函数

有了Java 8对lambda表达式的支持,这些事情会变得更好一些,但是能够以几乎相同的语法在任何地方声明函数不是很棒吗?

结论:与锡兰一起玩

现在就这样。 不久之后,我们可能会发布有关锡兰更深奥的语言功能的后续文章。 无论如何,您都可以在Eclipse中通过一流的IDE支持免费下载这种有趣的JVM语言。 您还可以访问Ceylon文档网站,并使他们的网站将Ceylon代码编译为JavaScript以在浏览器中执行。

访问社区并与RedHat和Serli的语言设计师进行互动,完成后,在我们的jOOQ博客上分享此帖子,并帮助JCP认识到这种美妙的语言具有Java 9的两个非常有趣的功能或10个路线图!


翻译自: https://www.javacodegeeks.com/2013/12/top-10-ceylon-language-features-i-wish-we-had-in-java.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值