您现在的位置是: 首页 > 排行榜 排行榜

scala_scala语言_1

ysladmin 2024-07-27 人已围观

简介scala_scala语言       最近有些日子没和大家见面了,今天我想和大家聊一聊“scala”的话题。如果你对这个领域还比较陌生,那么这篇文章就是为你而写的,让我们一起来探索其中的奥秘吧。1.Sca

scala_scala语言

       最近有些日子没和大家见面了,今天我想和大家聊一聊“scala”的话题。如果你对这个领域还比较陌生,那么这篇文章就是为你而写的,让我们一起来探索其中的奥秘吧。

1.Scala代码编写中常见的十大陷阱

2.为什么选择Scala

3.Scala语言的主要应用领域与作用?

4.scala 交互模式 代码怎么提示

scala_scala语言

Scala代码编写中常见的十大陷阱

        对于支持并发和分布式处理 高可扩展 基于组件的应用程序来说 Scala的功能是很强大的 它利用了面向对象和函数式程序设计的优点 这种基于Ja虚拟机的语言在宣布Twitter正使用它时受到了最多的冲击(相关 CTO评论 从Scala进驻Twitter看多语言混杂系统的前景) 如果使用正确 Scala可以大量减少应用程序对代码的需求

        对于Scala编程 我们收集了这些常见代码编写中的陷阱 这些技巧来自于Daniel Sobral 一个曾参加过FreeBSD项目和Ja软件开发工程的Scala狂热爱好者

         语法错误

        认为? yield 像 return 一样 有人会这样写

         for(i < to ) {

       

         ? if (i % == )

         ? yield i

         ? else

         ? yield i

         }

        正确的表示应该是

         for(i < to )

         yield {

         ? if (i % == )

         ? i

         ? else

         ? i

         }

         误用和语法错误

        滥用scala xml XML loadXXX 这个的语法分析器试图访问外部的DTD strip组件或类似的东西 在scala xml parsing ConstructingParser fromXXX中有另一个可选的语法分析器 同时 在处理XML时忘记了等号两端的空格 比如

         val xml=<root/>

        这段代码真正的意思是

         val xml $equal$less(root) $slash$greater

        

        这种情况的发生是由于操作符相当随意 而且scala用这样一种事实 字母数字字符与非字母数字字符通过下划线可以结合成为一个有效的标识符 这也使得 x+y 这样的表达式不会被当成一个标识符 而应该注意 x_+ 是一个有效的标识符 所以 赋值标识符的写法应该是

         val xml = <root/>

         用法错误

        为那些根本不是无关紧要的应用加入Application特征

         object MyScalaApp extends Application {

         ? // body

         }

        示例部分的问题在于 body部分在单元对象初始化时执行 首先 单元初始化的执行是异步的 因此你的整个程序不能与其它线程交互 其次 即时编译器(JIT)不会优化它 因此你的程序速度慢下来 这是没有必要的

        另外 不能与其它线程的交互也意味着你会忘记测试应用程序的GUI或者Actors

         用法错误

        试图模式匹配一个字符串的正则表达式 而又定该正则表达式是无界的

         val r = (\d+) r

         val s = > <

         s match {

         ? case r(n) => println( This won t match )

         ? case _ => println( This will )

         }

        此处的问题在于 当模式模式匹配时 Scala的正则表达式表现为如同开始于 ^ 结束于 $ 使之工作的正确写法是

         val r = (\d+) r

         val s = > <

         r findFirstIn s match {

         ? case Some(n) => println( Matches to +n)

         ? case _ => println( Won t match )

         }

        或者确保模式能匹配任意前缀和后缀

         val r = *(\d+) * r

         val s = > <

         s match {

         ? case r(n) => println( This will match the first group of r +n+ to )

         ? case _ => println( Won t match )

         }

         用法错误

        把var和val认为是字段(fields)

        Scala强制使用统一访问准则(Uniform Access Principle) 这使得我们无法直接引用一个字段 所有对任意字段的访问只能通过getters和setters val和var事实上只是定义一个字段 getter作为val字段 对于var则定义一个setter

        Ja程序员通常认为var和val是字段 而当发现在他们的方法中它们共享相同的命名空间时 常常觉得惊讶 因此 不能重复使用它们的名字 共享命名空间的是自动定义的getter和setter而不是字段本身 通常程序员们会试图寻找一种访问字段的方法 从而可以绕过限制 但这只是徒劳 统一访问准则是无法违背的 它的另一个后果是 当进行子类化时val会覆盖def 其它方法是行不通的 因为val增加了不变性保证 而def没有

        当你需要重载时 没有任何准则会指导你如何使用私有的getters和setters Scala编译器和库代码常使用私有值的别名和缩写 反之公有的getters和setters则使用fullyCamelNamingConventions(一种命名规范) 其它的建议包括 重命名 实例中的单元化 甚至子类化 这些建议的例子如下

        重命名

         class User(val name: String initialPassword: String) {

         ? private lazy var encryptedPassword = encrypt(initialPassword salt)

         ? private lazy var salt = scala util Random nextInt

        

         ? private def encrypt(plainText: String salt: Int): String = { }

         ? private def decrypt(encryptedText: String salt: Int): String = { }

        

         ? def password = decrypt(encryptedPassword salt)

         ? def password_=(newPassword: String) = encrypt(newPassword salt)

         }

        单例模式(Singleton)

         class User(initialName: String initialPassword: String) {

         private object fields {

         var name: String = initialName;

         var password: String = initialPassword;

         }

         def name = fields name

         def name_=(newName: String) = fields name = newName

         def password = fields password

         def password_=(newPassword: String) = fields password = newPassword

         }

        或者 对于一个类来说 可以为相等关系或hashCode自动定义可被重用的方法

         class User(name : String password : String) {

         ? private case class Fields(var name: String var password : String)

         ? private object fields extends Fields(name password )

        

        

         ? def name = fields name

         ? def name_=(newName: String) = fields name = newName

         ? def password = fields password

         ? def password_=(newPassword: String) = fields password = newPassword

         }

        子类化

         case class Customer(name: String)

        

         class ValidatingCustomer(name : String) extends Customer(name ) {

         ? require(name length < )

        

         ? def name_=(newName : String) =

         ? if (newName length < ) error( too short )

         ? else super name_=(newName)

         }

        

         val cust = new ValidatingCustomer( xyz )

         用法错误

        忘记类型擦除(type erasure) 当你声明了一个类C[A] 一个泛型T[A]或者一个函数或者方法m[A]后 A在运行时并不存在 这意味着 对于实例来讲 任何参数都将被编译成AnyRef 即使编译器能够保证在编译过程中类型不会被忽略掉

        这也意味着在编译时你不能使用类型参数A 例如 下面这些代码将不会工作

         def checkList[A](l: List[A]) = l match {

         ? case _ : List[Int] => println( List of Ints )

         ? case _ : List[String] => println( List of Strings )

         ? case _ => println( Something else )

         }

        在运行时 被传递的List没有类型参数 而List[Int]和List[String]都将会变成List[_] 因此只有第一种情况会被调用

        你也可以在一定范围内不使用这种方法 而用实验性的特性Manifest 像这样

         def checkList[A](l: List[A])(implicit m: scala reflect Manifest[A]) = m toString match {

         ? case int => println( List of Ints )

         ? case ja lang String => println( List of Strings )

         ? case _ => println( Something else )

         }

         设计错误

        Implicit关键字的使用不小心 Implicits非常强大 但要小心 普通类型不能使用隐式参数或者进行隐匿转换

        例如 下面一个implicit表达式

         implicit def string Int(s: String): Int = s toInt

        这是一个不好的做法 因为有人可能错误的使用了一个字符串来代替Int 对于上面的这种情况 更好的方法是使用一个类

         case class Age(n: Int)

         implicit def string Age(s: String) = Age(s toInt)

         implicit def int Age(n: Int) = new Age(n)

         implicit def age Int(a: Age) = a n

        这将会使你很自由的将Age与String或者Int结合起来 而不是让String和Int结合 类似的 当使用隐式参数时 不要像这样做

         case class Person(name: String)(implicit age: Int)

        这不仅因为它容易在隐式参数间产生冲突 而且可能导致在毫无提示情况下传递一个隐式的age 而接收者需要的只是隐式的Int或者其它类型 同样 解决办法是使用一个特定的类

        另一种可能导致implicit用法出问题的情况是有偏好的使用操作符 你可能认为 ~ 是字符串匹配时最好的操作符 而其他人可能会使用矩阵等价(matrix equivalence) 分析器连接等(符号) 因此 如果你使用它们 请确保你能够很容易的分离其作用域

         设计错误

        设计不佳的等价方法 尤其是

        ◆试着使用 == 代替 equals (这让你可以使用 != )

        ◆使用这样的定义

         def equals(other: MyClass): Boolean

        而不是这样的

         override def equals(other: Any): Boolean

        

        ◆忘记重载hashCode 以确保当a==b时a hashCode==b hashCode(反之不一定成立)

        ◆不可以这样做交换 if a==b then b==a 特别地 当考虑子类化时 超类是否知道如何与一个子类进行对比 即使它不知道该子类是否存在 如果需要请查看canEquals的用法

        ◆不可以这样做传递 if a==b and b ==c then a==c

         用法错误

        在Unix/Linux/*BSD的系统中 对你的主机进行了命名却没有在主机文件中声明 特别的 下面这条指令不会工作

         ping `hostname`

        在这种情况下 fsc和scala都不会工作 而scalac则可以 这是因为fsc运行在背景模式下 通过TCP套接字监听连接来加速编译 而scala却用它来加快脚本的执行速度

         风格错误

        使用while 虽然它有自己的用处 但大多数时候使用for往往更好 在谈到for时 用它们来产生索引不是一个好的做法

        避免这样的使用

         def matchingChars(string: String characters: String) = {

         ? var m =

         ? for(i < until string length)

         ? if ((characters contains string(i)) && !(m contains string(i)))

         ? m += string(i)

         ? m

         }

        而应该使用

         def matchingChars(string: String characters: String) = {

         ? var m =

         ? for(c < string)

         ? if ((characters contains c) && !(m contains c))

         ? m += c

         ? m

         }

        如果有人需要返回一个索引 可以使用下面的形式来代替按索引迭代的方法 如果对性能有要求 它可以较好的应用在投影(projection)(Scala )和视图(Scala )中

         def indicesOf(s: String c: Char) = for {

         ? (sc index) < s zipWithIndex

         ? if c == sc

lishixinzhi/Article/program/Ja/hx/201311/26022

为什么选择Scala

        Scala编程语言近来抓住了很多开发者的眼球 如果你粗略浏览Scala的网站 你会觉得Scala是一种纯粹的面向对象编程语言 而又无缝地结合了命令式和函数式的编程风格 Christopher Diggins认为

        不太久之前编程语言还可以毫无疑义地归类成 命令式 或者 函数式 Scala代表了一个新的语言品种 它抹平了这些人为划分的界限

        根据Did Rupp在博客中的说法 Scala可能是下下一代Ja 这么高的评价让人不禁想看看它到底是什么东西

        Scala有几项关键特性表明了它的面向对象的本质 例如 Scala中的每个值都是一个对象 包括基本数据类型(即布尔值 数字等)在内 连函数也是对象 另外 类可以被子类化 而且Scala还提供了基于mixin的组合(mixin based position)

        与只支持单继承的语言相比 Scala具有更广泛意义上的类重用 Scala允许定义新类的时候重用 一个类中新增的成员定义(即相较于其父类的差异之处) Scala称之为mixin类组合

       

        Scala还包含了若干函数式语言的关键概念 包括高阶函数(Higher Order Function) 局部套用(Currying) 嵌套函数(Nested Function) 序列解读(Sequence Comprehensions)等等

        Scala是静态类型的 这就允许它提供泛型类 内部类 甚至多态方法(Polymorphic Method) 另外值得一提的是 Scala被特意设计成能够与Ja和 NET互操作 Scala当前版本还不能在 NET上运行(虽然上一版可以) 但按照将来可以在 NET上运行

        Scala可以与Ja互操作 它用scalac这个编译器把源文件编译成Ja的class文件(即在JVM上运行的字节码) 你可以从Scala中调用所有的Ja类库 也同样可以从Ja应用程序中调用Scala的代码 用Did Rupp的话来说

        它也可以访问现存的数之不尽的Ja类库 这让(潜在地)迁移到Scala更加容易

        这让Scala得以使用为Ja 或者 编写的巨量的Ja类库和框架 Scala会经常性地针对这几个版本的Ja进行测试 Scala可能也可以在更早版本的Ja上运行 但没有经过正式的测试 Scala以BSD许可发布 并且数年前就已经被认为相当稳定了

        说了这么多 我们还没有回答一个问题 为什么我要使用Scala? Scala的设计始终贯穿着一个理念

        创造一种更好地支持组件的语言 (《The Scala Programming Language》 Donna Malayeri)

        也就是说软件应该由可重用的部件构造而成 Scala旨在提供一种编程语言 能够统一和一般化分别来自面向对象和函数式两种不同风格的关键概念

        藉著这个目标与设计 Scala得以提供一些出众的特性 包括

        * 面向对象风格

        * 函数式风格

        * 更高层的并发模型

        Scala把Erlang风格的基于actor的并发带进了JVM 开发者现在可以利用Scala的actor模型在JVM上设计具伸缩性的并发应用程序 它会自动获得多核心处理器带来的优势 而不必依照复杂的Ja线程模型来编写程序

        * 轻量级的函数语法

        o 高阶

        o 嵌套

        o 局部套用(Currying)

        o 匿名

        * 与XML集成

        o 可在Scala程序中直接书写XML

        o 可将XML转换成Scala类

        * 与Ja无缝地互操作

        Scala的风格和特性已经吸引了大量的开发者 比如Debasish Ghosh就觉得

        我已经把玩了Scala好一阵子 可以说我绝对享受这个语言的创新之处

lishixinzhi/Article/program/Ja/hx/201311/26873

Scala语言的主要应用领域与作用?

       类型安全

       强大的并发特性

       尽管Python和PHP支持进程创建,但是他们都没有轻量级的并发特性,比如“真正的”多线程编程。Coursera的框架具有多样性和复杂性的特点,要求能够具备和多种数据库和不同服务交互的能力。Play的reactive core和异步编程库能够和一些强大的并发库进行无缝连接(比如说Akka中的actor模型)。这些特性的融合能够使得异步编程像是同步编程代码那样容易理解。程序猿可以使用这些框架编写可读、可维护、高效的代码,而不是难以理解的无穷无尽的回调。

       成熟的生态系统

       JVM生态系统是现在组成熟的生态系统,而Scala就是在JVM和Ja生态系统上构建的,因此可以从Ja的工具库中获益。当前很多大数据的组件比如Hadoop、Spark以及Cassandra都是在JVM生态系统内,这使得使用Scala编程的框架可以直接调用他们的库。并且,相对PHP或者Python,Scala和Play只需要在节点上安装JVM,这省去了很多繁琐的部署和维护步骤。JVM还是一个特性完整的虚拟机,堆容器、GC机制、实时编译等都十分成熟,加速了开发过程。

scala 交互模式 代码怎么提示

       Scala的特性

       1.面向对象特性

       Scala是一种纯面向对象的语言,每一个值都是对象。对象的数据类型以及行为由类和特征(Trait)描述。类抽象机制的扩展有两种途径。一种途径是子类继承,另一种途径是灵活的混入(Mixin)机制。这两种途径能避免多重继承的种种问题。

       2.函数式编程

       Scala也是一种函数式语言,其函数也能当成值来使用。Scala提供了轻量级的语法用以定义匿名函数,支持高阶函数,允许嵌套多层函数,并支持柯里化。Scala的CaseClass及其内置的模式匹配相当于函数式编程语言中常用的代数类型(AlgebraicType)。

       更进一步,程序员可以利用Scala的模式匹配,编写类似正则表达式的代码处理XML数据。在这些情形中,顺序容器的推导式(comprehension)功能对编写公式化查询非常有用。

       由于JVM不支持尾部递归,Scala也不能完全支持尾部递归优化。不过,在简单的情况下,Scala编译器可以把尾部递归优化成循环。

       4.静态类型

       Scala是具备类型系统,通过编译时的检查,保证代码的安全性和一致性。类型系统具体支持以下特性:

       泛型类,型变注释(VarianceAnnotation),类型继承结构的上限和下限,把类别和抽象类型作为对象成员,复合类型,引用自己时显式指定类型,视图,多态方法。

       5.扩展性

       Scala的设计承认一个事实,即在实践中,某个领域特定的应用程序开发往往需要特定于该领域的语言扩展。Scala提供了许多独特的语言机制,可以以库的形式轻易无缝添加新的语言结构:

       任何方法可用作前缀或后缀操作符,可以根据预期类型自动构造闭包。联合使用以上两个特性,使你可以定义新的语句而无须扩展语法也无须使用宏之类的元编程特性。

       5.使用Scala的框架

       Lift是一个开源的Web应用框架,旨在提供类似RubyonRails的东西。因为Lift使用了Scala,所以Lift应用程序可以使用所有的Ja库和Web容器。

       scala语言主要应用领域

       cala运行于JVM之上,并且它可以访问任何的ja类库并且与ja框架进行互操作,scala也大量重用了ja类型和类库。

       大数据的开发语言是Scala的原因:

       1:大数据的本身是计算数据,而Scala即有面向对象组织项目工程的能力,又有计算数据的功能。

       2:现在大数据事实上的计算标准框架Spark,它是用Scala开发的,因为计算数据,Scala它是函数式编程,它实现算法非常简洁优雅。

       例:kafka,它是一个消息中间件,如果外部数据要流进大数据中心,我们一般都要用kafka作适配器,那如果大数据中心的数据流到外部,也是用kafka(如Spark计算的数据要交给HBASE或MySql,期间我们都会用kafka),很多的大数据组件都是用的Scala编写的,所以,如果你想成为一个较高级的大数据开发高手,你一定要掌握Scala。

       Scala提供了很多学习材料帮助你学习核心语言内容,有很多在线的教程、示例和项目可以去研究。但是Scala提供的最重要的一个工具是交互模式(REPL)。REPL是一个交互式解释器,可以即时编译、运行代码并返回结果。定你已经在机器上装好了Scala,也设置了正确的路径,那么在命令行下运行scala命令就可以启动Scala REPL。启动Scala REPL后屏幕上会输出如下内容:

       后面的代码示例中,我会用scala>提示这是输入到REPL的内容。接下来的一行是REPL的输出。我们在REPL里快速做几个例子,看看会得到什么输出。

       你应该注意到了在我们输入解释器的每个语句后,它会输出一行信息,类似res0: ja.lang.String = Hello。输出的第一部分是REPL给表达式起的变量名。在这几个例子里,REPL为每个表达式定义了一个新变量(res0到res3)。输出的第二部分(:后面的部分)是表达式的静态类型。第一个例子的类型是ja.lang.String,最后一个例子的类型则是scala.util.matching.Regex。输出的最后一部分是表达式求值后的结果的字符串化显示。一般是对结果调用toString方法得到的输出,JVM给所有的类都定义了toString方法。

       图2.1 REPL的返回值

       如你所见,REPL是一种测试Scala语言及其类型系统的强有力手段。不仅如此,大部分构建工具都提供了机制让你能加载当前工程的classpath,然后启动REPL。这意味着你可以在REPL里访问工程中引用的库和你自己的代码。你能够在REPL里调用API和访问远端服务器。这是很棒的快速测试Web服务或REST API的方法,也导向我称为实验驱动开发(Experiment Driven Development)的方法。

       2.1.1 实验驱动开发

       实验驱动开发就是开发者在写测试或生产代码前,先花点时间在交互环境或REPL里做实验。这可以给你时间全面理解你需要打交道的软件或库的外部接口,并对其API的优点和缺点得到点切身体会。这是学习新发布的Web服务或RESTful API或最新的Apache库的极好办法,甚至可以用来学习你同事刚刚写出来的东西。在理解了API是怎么工作后,你就能更好地写自己的代码,或者开始写测试,如果你遵循测试驱动开发的话。

       现在推动开发人员拥抱测试驱动开发(TDD)的呼声很高。TDD要求开发者先写单元测试,然后写实现类。在你开始写测试前,你并不总是很清楚自己的API要定义成什么样的。TDD的一个组成部分就是通过写测试来定义API,这样你可以在(用户的)上下文里来看你的代码,可以感觉一下你自己愿意不愿意用你自己写的API。由于表达力(较差)的原因,强类型语言在应用TDD时可能会比动态语言碰到更多麻烦。实验驱动开发将“定义API”这个步骤向前期推动一步,提前到了写测试代码之前。REPL帮助开发者确保其设计的API在类型系统里能表达得出来。

       Scala是一种语法非常灵活的强类型语言,因此有时候需要用点手段欺骗类型系统才能达成你真正想要的API设计。因为很多开发者缺乏强类型理论基础,所以经常需要更多的实验。实验驱动设计(Experiment Driven Design)让你在REPL里结合类型系统进行实验,以便为你的API提炼出最有效的类型定义。实验驱动设计主要用在给代码里添加大特性或领域对象的时候,不适合在添加新方法或者修bug时使用。

       实验驱动设计在你定义领域特定语言时(DSL)也能帮上大忙。领域特定语言是用于特定领域的伪编程语言,这种语言专门用来解决手头的某个领域,比如说,从数据库里查询数据。DSL可以是内部的,在很多Scala库里都能看到的;也可以是外部的,比如SQL。在Scala社区,库开发者圈子里非常流行为自己的库创建一种DSL。比如Scala的actors库定义了一种线程安全的发送和接收消息的DSL。

       用Scala定义DSL的挑战之一在于有效地利用类型系统。设计良好的类型安全的DSL不仅应该富有表达力、易读,而且应该能在编译期而不是运行期捕捉到很多编程错误。同时静态类型信息也可以极大地提高性能。REPL不仅能用来实验怎样表达一个特定领域,而且能帮助你确定你得表达式是否能编译。进行Scala开发时,有些人用下面这种创造性的流程。

       在REPL里实验API设计。

       把能工作的API拷贝到项目文件。

       为API写单元测试。

       修改代码直到测试通过。

       有效地使用实验驱动开发能够极大地提高你的API的质量。也会帮你在推进过程中更适应Scala的语法。不过这种做法有个大问题,就是并非所有能用Scala表达的API都能在REPL里表达。这是因为REPL是积极(eagerly)解析输入,即时解释执行的。

       2.1.2 绕过积极(eaglerly)解析

       Scala REPL尝试尽可能快地解析输入。这个特点加上其他一些限制,意味着有些东西很难甚至是无法在REPL里表达的。其中一个难以表达的重要的功能是伴生对象和伴生类。

       伴生对象和伴生类是一组用完全一样的名字定义的对象和类。用文件编译的方式很容易实现,就像这样简单的声明对象和类:

       这些语句在REPL里也能执行,但是它们不会像真的伴生类那样起作用。为证明这一点,我们来做一些只有伴生对象能做,普通对象做不了的事:访问类的私有变量。

       为了解决这个问题,我们需要把这些对象嵌入解释器里某个能访问到的其他作用域里。我们现在来把它们放入某个作用域里,以便能同时解释/编译类和伴生对象。

       我们在这创建了一个holder对象。这给了我们一个可访问的作用域,也把REPL的编译推迟到holder对象关闭的时候。这样我们就可以在REPL里测试/定义伴生对象了。

       即使绕过了积极解析,也还有一些语言特性无法在REPL里重现。大多数这种问题都跟包、包对象、包可见性约束等问题有关。尤其是你无法像在源代码文件里一样有效地在REPL里创建包和包对象。这也意味着其他跟包有关的语言特性,特别是使用private关键字实现的可见性限制也无法在REPL里表达。包通常用来为你的代码设定命名空间,以便与你可能使用的其他类库分开。通常情况下你不需要在REPL里用到它,但是可能有些时候你需要把玩一些Scala的高级特性,比如包对象和隐式解析(implicit resolution),这时你可能会想做点实验驱动开发。但是这种场景下,你无法在REPL里去表达。

       请不要绝望。如我之前说过的,大部分构建工具可以让你启动一个针对你当前工程的Scala REPL。作为最后的手段,你可以在Scala文件里把玩那些高级概念,重编译然后重启REPL会话。

       另外还有个工具叫做JRebel,它可以动态地在运行中的JVM里重载类文件。JRebel团队非常慷慨地为Scala中的使用提供了免费许可。利用这工具结合某种形式的持续编译—大部分Scala构建工具都提供的这一特性—你可以在修改工程文件后立刻在REPL会话里得到修改后的行为。对于men-scala-plugin。Simple Build Tool提供了CC任务来做持续编译。不管用哪种构建工具都必须和JRebel类加载器集成以便实现动态类重载。这个技巧有点过于细节,而且可能会变,所以如果需要帮助请参考你用的构建工具的文档或者JRebel网站。

       在尝试创建大而复杂的系统前,你可以先利用REPL来实验Scala代码,获得一些真实的感觉。软件开发中,在开发一个新特性前,对当前系统得到一个稍微深入一些的理解(而不只是草草看过)往往是很重要的。Scala REPL可以让你投入最少的时间达成对系统的理解,还可以提高你的开发技巧。本书全文穿插着很多REPL的例子,因为它是教学Scala的最好工具。我经常完全通过REPL运行示例,而不是用Ja开发时的标准做法,先写main方法或者单元测试。

       REPL也是开始学习面向表达式编程的极佳方法。

       今天关于“scala”的探讨就到这里了。希望大家能够更深入地了解“scala”,并从我的答案中找到一些灵感。