-1

该程序是:

object Hello extends App {
    
    val a: List[Int] = List(1, 3, 4, 5, 8, 10, 11, 22, 33)
    for (i <- 0 to 11)
        println(a(i))

}

输出是:

1
3
4
5
8
10
11
22
33
java.lang.IndexOutOfBoundsException: 9 // continues as a long error message.

它如何在编译时没有检测到索引将超出范围?编译语言不应该这样做吗?如果没有,您能否分享一下编译时检查中包含的内容和不包含的内容?

作为一个新手,我总是听说,编译语言很棒,它们在编译时发现错误,因此更健壮。

4

2 回答 2

5

您不应该将编译 语言(或静态类型语言)与依赖类型语言混淆。不长于n元素的集合是依赖类型的典型示例。正在编译的语言意味着除了运行时检查之外还有编译时检查。是否进行特定检查(如检查集合长度)运行时或编译时是您的选择(或语言设计者的选择或标准库设计者的选择)。即使检查是编译时的,是否将其编码为类型或使用不同的工具也是一种选择。

解释与编译:有用的区别?

每种语言都可以分类为编译型还是解释型?

每种语言都可以编译吗?每种语言都能被解释吗?

什么是依赖类型?

scala 不明确支持依赖类型的任何原因?

Shapeless:静态已知大小的集合

import shapeless.Sized
import shapeless.nat._

val a: Sized[List[Int], _9] = Sized[List](1, 3, 4, 5, 8, 10, 11, 22, 33)

a(10) // doesn't compile

斯卡斯蒂

于 2020-11-20T16:23:19.740 回答
4

这里的主要问题是for在 Scala 中的含义与在其他语言中的含义不同。问题中的代码相当于

(0.to(11)).foreach(i => println(a.apply(i))

编译器必须检查许多不同的方法并推断它们的行为,以确定该apply方法是否会引发异常。

但是编译语言的主要优点是性能,而不是错误检查。提供更好的错误检测的是强类型语言(通常是编译的)。

于 2020-11-20T14:58:39.780 回答