锡兰可能只是唯一一种使无效的(JVM)语言

再来一次。 那个话题

但是等一下 您每天都不会看到这里讨论的方法(以及用锡兰语言)。 同时,它非常狡猾。

空值被烤成语言

…大概看起来。 确实,在锡兰,就像在Kotlin (以及可能的许多其他语言)中一样,有一个特殊的“注释”类型,您可以将其后缀为任何引用类型,以使其可为空。 例如:

String firstName = "Homer";
String? middleName = "J";
String lastName = "Simpson";

在上面的示例中, firstNamelastName都是强制性值,永远不能为null ,而middleName是可选的。 然后,大多数支持上述内容的语言都会附带特殊的运算符以访问可选值,例如.? 在锡兰Kotlin

// Another optional value:
Integer? length = middleName.?length;

// A non-optional value:
Integer length = middleName.?length else 0;

那么,锡兰如此平稳地工作又是什么呢?

锡兰说得很对的事情是,以上所有都是语法糖,它是:

  • 易于使用
  • 很好地映射了我们的思维方式,即null仍然是一个问题
  • 可以与Java互操作
  • 不引入认知摩擦

对于我们Java的人来说,我们仍然可以假装null是一种可以避免的难事( 就像我们在此Blog之前所声称的那样 )。 但是,实际上什么 null ? 是缺少价值吗? 未知值? 未初始化的值?

Java只有一个null的事物,它被所有先前的事物所用(滥用),并且从理论上讲,它实际上只是未初始化的值,仅此而已。 另一方面,当使用JDBC(因此使用SQL)时,它隐式表示未知值( 带有所有相关的警告 )。

但是在Ceylon中, Null是一种特殊类型 ,类似于Java中的Void 。 可以分配给Null类型的唯一null

// Ceylon
Null x = null;

// Java
Void x = null;

但是最大的区别是,不能将null分配给任何其他类型! 等待。 我们不能将null分配给String? ……? 当然,在锡兰,可能会发生以下情况:

String? x = null;

但是为什么这可能呢? 因为String? 只是String|Null联合类型)的语法糖,即,它是String类型还是Null类型。

呵呵,工会类型是什么?

让我们更仔细地看一下。 在jOOQ API中,当您想使用SQL函数和表达式时,总是会有大量的重载为您提供标准版本和便捷的版本,您可以在其中传递绑定变量。 以equals运算符为例:

interface Field<T> {
    Condition eq(Field<T> field);
    Condition eq(T value);
}

上面的重载使您可以编写如下内容,而无需考虑SQL表达式和Java绑定变量(最终还是SQL表达式)之间的区别:

// Comparing a column with bind variable
.where(BOOK.ID.eq(1))

// Comparing a column with another column expression
.and(BOOK.AUTHOR_ID.eq(AUTHOR.ID))

实际上,还有更多的重载,因为比较操作的右侧也可以具有其他表达式,例如:

interface Field<T> {
    Condition eq(Field<T> field);
    Condition eq(T value);
    Condition eq(Select<? extends Record1<T>> query);
    Condition eq(QuantifiedSelect<? extends Record1<T>> query);
}

现在,需要重复相同的一组重载,而不是等于,大于,大于或等于,等等。将这种“右侧”东西表达为单个可重用类型不是很好吗? ? 即上述所有类型的联合类型?

interface Field<T> {
    Condition eq(
        Field<T>
      | T
      | Select<? extends Record1<T>>
      | QuantifiedSelect<? extends Record1<T>> thingy
    );
}

甚至

// This is called a type alias. Another awesome
// Ceylon language feature (pseudo syntax)
alias Thingy => 
    Field<T>
  | T
  | Select<? extends Record1<T>>
  | QuantifiedSelect<? extends Record1<T>>;

interface Field<T> {
    Condition eq(Thingy thingy);
}

毕竟,这也是SQL语言的定义方式。 哎呀,这就是任何BNF表示法定义语法元素的方式。 例如:

<predicate> ::=
    <comparison predicate>
  | <between predicate>
  | <in predicate>
  | <like predicate>
  | <null predicate>
  | <quantified comparison predicate>
  | <exists predicate>
  | <unique predicate>
  | <match predicate>
  | <overlaps predicate>

好吧,理所当然,句法元素与类型并不完全相同,但直觉却是相同的。

哦,Java也有联合类型!

简短的启示是,Java 7专家组在异常处理中添加了对联合类型的支持。 您可以编写如下内容:

try {
    ...
}
catch (IOException | SQLException e) {
    // e can be any of the above!
}

返回锡兰和空

锡兰正确地使Null 。 因为从历史上看,可空类型是可以是“实”类型或“空”值的类型。 我们想要那个。 我们Java开发人员渴望这一点。 没有这种选择的舒缓选择,我们就无法生存。

但是这种方法的优点在于它是可扩展的。 如果我真的需要区分“未知”,“未初始化”,“未定义”,“ 42”怎么办? 我可以。 使用类型。 这是一个可以对所有上述“特殊值”进行建模的字符串:

String|Unknown|Uninitialised|Undefined|FortyTwo

如果太冗长,我只给它起一个名字

interface TheStringToRuleThemAll
  => String|Unknown|Uninitialised|Undefined|FortyTwo;

但这不能为Null 。 因为我不想让它成为那样的价值,所以那就是一切,一无所有。 你说服了吗? 我敢打赌,你是。 从现在开始:

不要相信任何假装Option(al)monad是对null建模的体面方法的语言。 不是。

- 我。 现在

为什么? 让我举例说明。 使用elvis运算符的Kotlin / Ceylon / Groovy样式语法糖(无论支持空null语义如何):

String name = bob?.department?.head?.name

Optional单子相同:

Optional<String> name = bob
    .flatMap(Person::getDepartment)
    .map(Department::getHead)
    .flatMap(Person::getName);

而且,如果您一次将map()与flatMap()混合在一起,就会很可怜!

有人声称:

使用工会类型就像在您婆婆坐在副驾驶席上驾驶崭新的法拉利那样。

艾尔维拉(Elvira)

当然。 但我声称:做得好,锡兰。 希望我们也可以在catch块之外获得Java中的联合类型!

翻译自: https://www.javacodegeeks.com/2016/03/ceylon-might-just-jvm-language-got-nulls-right.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值