scala学习笔记二----交互式shell编程使用

来源:互联网 发布:软件调研方案模板 编辑:程序博客网 时间:2024/06/14 14:49

    今天接着学习scala,我是按照《scala编程中文版》这本书来进行学习的,感觉书中讲的很不错,也差不多都能弄明白,跟着书中的章节来一步一步的学下来,书中提到代码全部都是自己实践敲一遍,很多问题都是在不经意间出现,动手实践一方面可以加强自己对一门新的语言的学习理解程度,另一方面可以帮助自己体会语言的语法和书写方式,再者,也是最重要的就是自己在写每一句代码的时候不可能会全部按照书中的来写,那么就会产生一些新的东西了,这就是动手去实践的重要性,可以说,读研给我最大的收获之一吧,就是:遇事在没有自己动手去做之前都不敢轻易说不,遇上问题在没有动手去差很多资料解决之前不敢轻易说不会,这也是因为自己在本科的时候太过于安逸了吧,现在希望尽量去多学多做少说话。

    好了,扯远了,下面是今天的学习笔记,所有内容均来源于底部参考书籍,自己动手实践的时候加了东西,如有冒犯请告知。

1.Scala 里可以使用 new 实例化对象或类实例当你在 Scala 里实例化对象, 可以使用值和类型把它参数化: parameterize。 参数化的意思是在你创建实例的时候“设置” 它。通过把加在括号里的对象传递给实例的构造器的方式来用值参数化实例,如:实例化一个数字:val big = new java.math.BigInteger("12345")也可以使用类似于java中的数组方式赋值val str_list = new Array[String](4)等价于:val str_list: Array[String] = new Array[String](3)str_list(0) = "沂"str_list(1) = "水"str_list(2) = "寒"str_list(3) = "城"for (i <- 0 to 3)print(str_list(i))在这里需要注意的是()和[],这是一个scala区别于java的地方,使用()来存放数组、列表之类的元素下标当你用val定义一个变量如上面的str_list数组,那么这个变量就不能重新赋值,但它指向的对象却仍可以暗自改变,如str_list(0)是可以重新被赋予新的数值的,即数组本身是不能再变化的但是其中的每个具体的元素可以改变在scala的交互式shell也可以简单的像写python一样如下:scala> for(i<- 0 to 5)     | println(i)012345等价于:>>> for i in range(6):...     print i...012345个人觉得,至于简洁性不相上下Scala的一个通用规则:如果方法仅带一个参数,你可以不带点或括号的调用它。本例中的to实际上是带一个Int参数的方法。代码 0 to 2 被转换成方法调用(0).to(2)。从技术上讲,Scala没有操作符重载,因为它根本没有传统意义上的操作符。取而代之的是,诸如+,-,*和/这样的字符可以用来做方法名。因此,当第一步里你在 Scala 解释器里输入 1 + 2,你实际上正在 Int 对象 1 上调用一个名为+的方法,并把 2 当作参数传给它当对带有括号并包括一到若干参数的变量赋值时,编译器将把它转化为对带有括号里参数和等号右边的对象的 update 方法的调用则上面的语句等价为:val str_list = new Array[String](4)等价于:val str_list: Array[String] = new Array[String](3)str_list.update(0,"沂")str_list.update(1,"水")str_list.update(2,"寒")str_list.update(2,"城")for (i <- 0 to 3)print(str_list.apply(i))初始化一个字符串数组同样可以这样写:val str_list = Array.apply("沂", "水", "寒","城")如下:scala> val str_list=Array.apply("yi","shui","han","cheng")str_list: Array[String] = Array(yi, shui, han, cheng)2.方法不应该有副作用是函数风格编程的一个很重要的理念。方法唯一的效果应该是计算并返回值。用这种方式工作的好处就是方法之间很少纠缠在一起,因此就更加可靠和可重用。另一个好处(静态类型语言里)是传入传出方法的所有东西都被类型检查器检查,因此逻辑错误会更有可能把自己表现为类型错误。把这个函数式编程的哲学应用到对象世界里意味着使对象不可变。在scala中数组Array是可变的对象,而list却是不可变的,这个区别于java的可变的list创建一个list也很简单如下:scala> val num_list=List(23,45,67,89)num_list: List[Int] = List(23, 45, 67, 89)scala> var num_list0=List(12,34,56,78)num_list0: List[Int] = List(12, 34, 56, 78)scala可以将两个列表拼接到一起就像python中的一样如下:scala> val merge_list=num_list:::num_list0merge_list: List[Int] = List(23, 45, 67, 89, 12, 34, 56, 78)将num_list0拼在了num_list后面如果说操作符:::相当于python中的extend的话那么操作符::就相当于python中的append方法了如下:scala> val new_list=100::num_list0new_list: List[Int] = List(100, 12, 34, 56, 78)  将新数值100添加到了num_list0前面一个简单的需记住的规则:如果一个方法被用作操作符标注,如 a* b,那么方法被左操作数调用,就像 a.*(b)——除非方法名以冒号结尾。这种情况下,方法被右操作数调用。因此, 1 :: twoThree 里, ::方法被 twoThree 调用,传入 1,像这样: twoThree.::(1)由于定义空类的捷径是Nil,所以一种初始化新List的方法是把所有元素用cons操作符串起来, Nil作为最后一个元素,如下:scala> val new_list=100::99::88::77::66::55::44::33::22::11::Nilnew_list: List[Int] = List(100, 99, 88, 77, 66, 55, 44, 33, 22, 11)要在最后用到 Nil 的理由是::是定义在 List 类上的方法。如果你想只是写成 1 :: 2 :: 3,由于 3 是Int 类型,没有::方法,因此会导致编译失败为什么列表不支持 append?类List没有提供append操作,因为随着列表变长append的耗时将呈线性增长,而使用::做前缀则仅花费常量时间。如果你想通过添加元素来构造列表,你的选择是把它们前缀进去,当你完成之后再调用 reverse;或使用 ListBuffer,一种提供 append 操作的可变列表,当你完成之后调用 toList。3.元组: tuple与列表一样,元组也是不可变的,但与列表不同,元组可以包含不同类型的元素。而列表应该是List[Int]或List[String]的样子,元组可以同时拥有Int和String。元组很有用,比方说,如果你需要在方法里返回多个对象。Java里你将经常创建一个JavaBean样子的类去装多个返回值,Scala里你可以简单地返回一个元组。而且这么做的确简单:实例化一个装有一些对象的新元组,只要把这些对象放在括号里,并用逗号分隔即可,元组的实际类型取决于它含有的元素数量和这些元素的类型如下:scala> val new_tuple=("20123456","沂水寒城")new_tuple: (String, String) = (20123456,沂水寒城)访问元祖中的元素的话可以使用点号,下划线和一个基于 1 的元素索引访问它,如下:scala> println(new_tuple._1)20123456scala> println(new_tuple._2)沂水寒城不能用类似数组下标的方式访问元祖原因:因为 List 的 apply 方法始终返回同样的类型,但是元组里的或许类型不同,_N 数字是基于 1 的,而不是基于 0 的,因为对于拥有静态类型元组的其他语言,从1开始是传统的设定4.set和mapScala 致力于帮助你充分利用函数式和指令式风格两方面的好处,它的集合类型库于是就区分了集合类的可变和不可变。数组始终是可变的,而列表始终不可变。Scala 同样提供了可变和不可变的替代品,不过用了不同的办法。对于集和映射, Scala 把可变性建模在类继承中。Scala 的 API 包含了集的一个基本特质: trait,特质这个概念接近于 Java 的接口Scala 于是提供了两个子特质,一个是可变的集,另一个是不可变的集。三个特质都共享同样的简化名, Set。然而它们的全称不一样,因为每个都放在不同的包里。 如下:scala> var test_set=Set("沂", "水", "寒","城")test_set: scala.collection.immutable.Set[String] = Set(沂, 水, 寒, 城)scala> println(test_set.contains("ABC"))falsescala> test_set+="ABC"scala> println(test_set.contains("ABC"))true上述代码简单创建了一个缺省的不可变集合test_set,查询test_set是否包含某个元素,不包含的话将这个元素添加进去再次查询是否包含对于set的+:可变的和不可变的集都提供了+方法,但它们的行为不同。可变集将把元素加入自身,不可变集将创建并返回一个包含了添加元素的新集如果想显式地定义可变集可以这样写:import scala.collection.mutable.Set对,没看错,这个就是上面的代码在scala的交互式shell中创建了test_set之后返回值的类型相对的类型在mutable和immutable之间的差别如果你需要一个不可变的HashSet可以这么做:import scala.collection.immutable.HashSetval test_set0 = HashSet("张三", "李四","张飞","赵云","马岱")println(test_set0 + "关羽")如下:scala> import scala.collection.immutable.HashSetimport scala.collection.immutable.HashSetscala> val test_set0 = HashSet("张三", "李四","张飞","赵云","马岱")test_set0: scala.collection.immutable.HashSet[String] = Set(张飞, 李四, 马岱, 赵云, 张三)scala> println(test_set0 + "关羽")Set(张飞, 李四, 马岱, 赵云, 关羽, 张三)Map 是 Scala 里另一种有用的集合类。和集一样, Scala 采用了类继承机制提供了可变的和不可变的两种版本的 Mapscala.collection 包里面有一个基础 Map 特质和两个子特质 Map:可变的 Map 在scala.collection.mutable 里,不可变的在 scala.collection.immutable 里简单的代码演示如下:(1)可变版本的map创建import scala.collection.mutable.Mapval test_map = Map[String, String]()test_map("id_123")="刘备"test_map("id_124")="孙权"test_map("id_125")="曹操"test_map+=("id_001"->"吕布")test_map+=("id_002"->"关羽")test_map+=("id_003"->"张飞")结果如下:scala> import scala.collection.mutable.Mapimport scala.collection.mutable.Mapscala> val test_map = Map[String, String]()test_map: scala.collection.mutable.Map[String,String] = Map()                        scala> test_map("id_123")="刘备"scala> test_map("id_124")="孙权"scala> test_map("id_125")="曹操"scala> test_map+=("id_001"->"吕布")res10: test_map.type = Map(id_124 -> 孙权, id_001 -> 吕布, id_123 -> 刘备, id_125 -> 曹操)scala> test_map+=("id_002"->"关羽")res11: test_map.type = Map(id_124 -> 孙权, id_001 -> 吕布, id_123 -> 刘备, id_125 -> 曹操, id_002 -> 关羽)scala> test_map+=("id_003"->"张飞")res12: test_map.type = Map(id_124 -> 孙权, id_001 -> 吕布, id_003 -> 张飞, id_123 -> 刘备, id_125 -> 曹操, id_002 -> 关羽)上面简单的代码中使用了两种方式赋值,前三个使用的是类似于字典键值对的方式赋值,因为映射原理就是这个,在scala的交互式shell中前三个输入后均没有返回结果,后三个使用的是书中的赋值方式直接使用操作方法+来添加元素,可以看到:每一次的添加元素之后都有返回在添加完该元素后当下的map是什么内容(2)不可变版本的map创建不可变版本的map在scala中是缺省的也就是说默认的创建的map如果没有显式地指明类型(即导入模块)那么都认为是不可变的mapval test_map0=Map("id_123"->"刘备","id_124"->"孙权","id_125"->"曹操","id_001"->"吕布","id_002"->"关羽","id_003"->"张飞")结果如下:scala> val test_map_new=Map(3->"刘备",4->"孙权",5->"曹操",0->"吕布",1->"关羽",2->"张飞")test_map_new: scala.collection.immutable.Map[Int,String] = Map(0 -> 吕布, 5 -> 曹操, 1 -> 关羽, 2 -> 张飞, 3 -> 刘备, 4 -> 孙权)简单的实现遍历输出:scala> for (i<- 0 to 5)     | println (test_map_new(i))吕布关羽张飞刘备孙权曹操


参考书籍:

Scala编程中文完整版


    keep learning...

    上述提供的链接可以下载使用这本书,欢迎交流学习!

原创粉丝点击