揭穿斯卡拉神话

时间:2010-10-13 16:53:47

标签: scala programming-languages

关于Scala语言最常见的误解是什么,以及这些存在哪些反例?

更新

我正在考虑更多关于我见过的各种声明,例如“Scala是动态类型”和“Scala是一种脚本语言”。

我接受“Scala是[Simple / Complex]”可能被认为是一个神话,但它也是一个非常依赖于上下文的观点。我个人的信念是,非常相同的功能可以使Scala看起来简单或复杂,这取决于谁在使用它们。最终,语言只是提供抽象,而这就是用来塑造感知的方式。

不仅如此,它还有一定的激烈争论的倾向,而且我还没有看到有人改变对该主题的强烈观点......

13 个答案:

答案 0 :(得分:40)

答案 1 :(得分:36)

神话:Scala支持运算符重载。

实际上,Scala只有非常灵活的方法命名规则和中缀语法用于方法调用,当中缀语法与'运算符'一起使用时,具有确定方法优先级的特殊规则。与真正的运算符重载(a C ++)相比,这种微妙的区别对于实用性和滥用此语言特征的可能性具有重要意义,正如James Iry对this question的回答中更详细解释的那样。

答案 2 :(得分:32)

我不同意Scala很难的论点,因为你可以使用非常高级的功能来完成它。 Scala的可伸缩性意味着您可以在Scala中编写DSL抽象和高级API,否则需要语言扩展。所以公平地说,你需要将Scala库与其他语言编译器进行比较。人们并没有说C#很难,因为(我认为,没有关于此的第一手资料)C#编译器非常难以理解。对于Scala来说,这一切都在公开场合。但我们需要明确一点,即大多数人不需要在这个级别上编写代码,也不应该这样做。

答案 3 :(得分:28)

我认为许多scala开发人员,EPFL(以及你自己,Kevin)的常见误解是“scala是一种简单的语言”。这个论点通常是这样的:

  • scala 很少的关键字
  • scala重用相同的少数构造(例如 PartialFunction语法用作catch块的主体)
  • scala有一些简单规则,它允许您创建库代码(可能看起来好像该语言具有特殊的关键字/构造)。我在想这里的含义;含有冒号的方法;允许的标识符号; X(a, b)a X b与提取器的等价性。等等。
  • scala的声明网站方差意味着类型系统不会让您失望。不再有通配符和? super T

我个人认为这个论点是完全彻底的虚假。 Scala的类型系统与implicits一起使用可以编写frankly impenetrable code for the average developer。无论上述“指标”可能引导您如何思考,任何其他建议都是荒谬的。 (请注意,那些我在Twitter和其他地方嘲笑Java的非复杂性的人恰好是超级聪明的类型,有时似乎在他们之前掌握了monad,functor和箭头穿短裤)。

反对这一点的明显论据是(当然):

  1. 你没有 来编写这样的代码
  2. 您不必迎合普通开发人员
  3. 其中,在我看来只有#2才有效。无论你是否编写与scalaz一样复杂的代码,我认为使用该语言(并继续使用它)并没有真正理解类型系统是愚蠢的。如何才能充分利用语言?

答案 4 :(得分:25)

神话:方法和功能是一回事。

实际上,函数是一个值(FunctionN类之一的实例),而方法则不是。 Jim McBeath explains the differences in greater detail。最重要的实际区别是:

  • 只有方法可以有类型参数
  • 只有方法可以采用隐式参数
  • 只有方法可以有命名和默认参数
  • 在引用方法时,通常需要使用下划线来区分方法调用和部分函数应用程序(例如str.length求值为数字,而str.length _求值为零参数函数。)< / LI>

答案 5 :(得分:20)

有一个神话认为Scala很难,因为Scala是一种复杂的语言。

这是错误的 - 通过各种指标,Scala并不比Java复杂。 (语法大小,代码行数或类数或标准API中的方法数等。)

但无可否认,Scala代码难以理解。如果Scala不是一种复杂的语言,怎么会这样呢?

答案是Scala是一种强大的语言。与Java不同,Java有许多特殊结构(如枚举)可以完成一件特殊的事情 - 并且需要你学习仅适用于那一件事的专用语法,Scala有很多非常通用的结构。通过混合和匹配这些结构,人们可以用非常少的代码表达非常复杂的想法。而且,不出所料,如果有人出现并且没有同样复杂的想法,并试图弄清楚你正在用这个非常紧凑的代码做什么,他们可能会发现它令人生畏 - 甚至比他们看到一对夫妇更令人生畏那些代码页面做同样的事情,从那以后至少他们会意识到有多少概念性的东西需要理解!

还有一个问题是事情是否比他们真正需要的更复杂。例如,集合库中存在的一些类型体操使得集合使用起来很愉快,但是难以实现或扩展。这里的目标并不是特别复杂(例如,子类应该返回它们自己的类型),但是所需的方法(更高级的类型,隐式构建器等)是复杂的。 (事实上​​,如此复杂,Java只是放弃而不是尝试,而不是像Scala那样“正确”地执行它。此外,原则上,希望未来会有所改进,因为该方法可以发展更接近地匹配目标。)在其他情况下,目标是复杂的; list.filter(_<5).sorted.grouped(10).flatMap(_.tail.headOption)有点混乱,但是如果你真的想把所有数字都小于5,然后在剩下的列表中取出每10个中的第二个数字,那么,这只是一个有点复杂的想法,而且代码几乎说明了如果你知道基本集合操作它会做什么。

总结:Scala并不复杂,但它允许您紧凑地表达复杂的想法。复杂思想的紧凑表达可能令人生畏。


有一种说法Scala是不可部署的,而且可以毫不犹豫地部署各种第三方Java库。

就这个神话存在而言,我怀疑它存在于那些不习惯将虚拟机和API与语言和编译器分离的人中。如果你认为java == javac == Java API,如果有人建议使用scalac而不是javac,你可能会有点紧张,因为你看到你的JVM运行得有多好。

Scala最终成为JVM字节码,加上自己的自定义库。没有理由担心在小规模上部署Scala或者作为其他大型项目的一部分,因为部署任何其他库可能会或可能不会与您喜欢的任何JVM保持兼容。当然,Scala开发团队并没有像Google集合或Apache Commons那么强大的支持,但它至少与Java Advanced Imaging项目一样重要。

答案 6 :(得分:16)

神话:

def foo() = "something"

def bar = "something"

是一样的。

不是;你可以调用foo(),但bar()尝试调用StringLike的apply方法而不带参数(导致错误)。

答案 7 :(得分:14)

与Actors库有关的一些常见误解:

  • Actors处理并行,多线程/针对线程池的传入消息(实际上,处理多个线程中的消息与actor概念相反并且可能导致竞争条件 - 所有消息在一个线程中顺序处理(基于线程的actor使用一个线程进行邮箱处理和执行;基于事件的actor可以共享一个VM线程执行,使用多线程执行程序来安排邮箱处理))
  • 未捕获的异常不会改变actor的行为/状态(实际上,所有未捕获的异常终止了actor)

答案 8 :(得分:14)

神话:你可以在计算类似于零的总和时使用reduce替换折叠。

这是Scala的新用户中常见的错误/误解,特别是那些没有事先编程经验的用户。以下表达式 not 等效:

seq.foldLeft(0)(_+_)

seq.reduceLeft(_+_)

这两个表达式在处理空序列方面有所不同:fold产生有效结果(0),而reduce则抛出异常。

答案 9 :(得分:12)

神话:Pattern matching doesn't fit well with the OO paradigm

Martin Odersky亲自揭穿here。 (另见本文 - Matching Objects with Patterns - Odersky等人)

答案 10 :(得分:9)

误区:this.type指的是this.getClass所代表的相同类型。

作为这种误解的一个例子,可以假设在以下代码中v.me的类型是B

trait A { val me: this.type = this }

class B extends A

val v = new B

实际上,this.type指的是其唯一实例为this的类型。通常,x.type是单例类型,其唯一实例为x。因此,在上面的示例中,v.me的类型为v.type。以下会议演示了原则:

scala> val s = "a string"
s: java.lang.String = a string

scala> var v: s.type = s
v: s.type = a string

scala> v = "another string"
<console>:7: error: type mismatch;
 found   : java.lang.String("another string")
 required: s.type
       v = "another string"

答案 11 :(得分:7)

Scala具有类型推断和细化类型(结构类型),而Java则没有。

James Iry的神话是busted

答案 12 :(得分:3)

神话:Scala具有高度可扩展性,无需限定哪种形式的可伸缩性。

Scala在表达更高级别指称语义的能力方面确实具有高度可扩展性,这使其成为一种非常好的实验语言,甚至可以在项目级别自上而下的扩展生产协调组合性。

然而,每个引用不透明的语言(即允许可变数据结构)是必要的(而不是声明性的),并且不会扩展到WAN 自下而上,不协调的组合性和安全性。换句话说,命令式语言是组合(和安全)意大利面条w.r.t.模块的不协调发展。我意识到这种不协调的发展可能目前被大多数人视为“管道梦”,因此可能不是一个高优先级。并且这并不是要贬低更高级别语义统一可以提供的组合性(即消除极端情况)的好处,例如, a category theory model for standard library

许多读者可能存在显着的认知失调,他们可能会在完全理解我提出的问题之前过早地按下“向下”投票,特别是因为存在关于命令性与陈述性的普遍误解(即可变对比。不可变的),(和eager vs. lazy,)例如monadic语义从来就不是必然的yet there is a lie that it is。是的,在Haskell中,IO monad是必不可少的,但是它必须与monad一样没有任何关系。

我在“Copute Tutorial”和“Purity”部分详细解释了这一点,这些部分位于主页或暂时位于this link

我的观点是,我非常感谢Scala的存在,但我想澄清一下Scala的规模以及什么不是。我需要Scala才能做得很好,对我而言,它是构建新的声明性语言的理想平台,但Scala本身并不是完全声明的,并且除了记住使用之外,Scala编译器不能强制执行参考透明度。 val无处不在。

我认为我的观点适用于关于Scala的复杂性辩论。我发现(到目前为止,主要是概念上,因为到目前为止我的新语言的实际经验有限),删除可变性和循环,同时保留diamond multiple inheritance子类型(Haskell没有),从根本上简化了语言。例如,Unit小说消失,而afaics,一系列其他问题和结构变得不必要,例如非范畴理论标准库,用于理解等。