文件名称:
Scala 讲座:献给追求创意兴奋的程序员(全)
开发工具:
文件大小: 201kb
下载次数: 0
上传时间: 2019-05-25
详细说明:
连载(5) Scala语言探险 三
博文链接:https://fineqtbull.iteye.com/blog/480538Scala讲座:献给追求创意兴奋的程序员(5)
Scala语言探险三
scala> val ssize=(s: String)=>s! ength)将函数赋值给变量
ssize: (String)=> Int=
scala> SSize(" Zhang fei")/用变量来调用函数
res: Int= 9
scala>List(" Zhang","Fei)map(s: String)=>s. length)/刈于列表每一项目都适用同一函数文本
res4: List[Int] =List(6. 3)
scala>List(" Zhang","Fei).map(size)∥对于列衣每项目都适用同函数变量
res5: ListlInt]= list(6. 3)
上述最后两个例了中使用了map函数,他对列表中的每项目都适用作为参数传入的函数之后将适用
结果作为列表返回。函数则是由函数文本(s: String)=> slength或函数变量size来指定的。这也是闭包
的一个例子,在 Scala中用函数来定义闭包。任意的数都可以作为参数来传给别的函数。
例如前面的bar函数如下所示
def bar(s: String, n: Int): Unit= for i<1 to n) print(s)
这也可以用匿名两数来定义,这次是有两个参数且返回值是Unit的函数
scala> val fo=(s String, n:Int)=> for i<- 1 to n)print(s)
f0:(String, Int)=> Unit= sfunction>
这个函数中用for语句进行了n次循环,其实还可以改写成如下形式。
def bar(s: String, n: Int): Unit= l to n foreach i=> print(s)
网数体中出现的i=> print(s)就是以匿名函数形式定义的闭包。1ton是1to(n)的简化形式,然后将闭
包作为参数传递给刚创建的 Range对象的 foreach方法(参数在闭包的函数体中并没有被使用,仅是为
了语法需要)。
5.在表达式中作为占位符的下划线
实际上, Scala中备有比匿名函数更筍洁的描述方式。
如下所示,对于“(s: String)=>s. length”来说,可以用“”以“(: String) length”形式来描述。还
有可以用“(:Int)+(:Int)”来定义类型为“〔Int,Int)=>Int”的加法表达式。
scala>((: String).length)("abcde)
res: Int 5
scala>((: Int)+(: Int))(3, 4)
res: Int =7
scala>((: String).length+(: Int))(abc! " ,4)
res 8: Int =7
6.部分函数的定义
Scala中不仅可以用到现在所看到的式子来定义,还可以通过将具体的实例一排排列出后,用类似于数
学中学到的映像图的形式米描述。声明了“f1:A=>B”之后可以认为是定义了将类型A映像为类型B的函数
f1。实际上这可以认为是将函数定义为类 Function1[A,B的实例(叉6-1)。
http://fineqtbull.javaeye.com/http://scalacn.comhttp:/lscalagroup.group.javaeye.com/It3/3
Scala讲座:献给追求创意兴奋的程序员(5)
Scala语言探险三
def f1: Symbol=>Int=i
case a=> 1
case
case 'c=> B
scala> f1(c
res Int= 3
scala> f1('d)
scala match Error :'d
at SanonfunSf1S1 apply(: 8)
at SanonfunSf1S1apply( 8)
at (: 10)
at ()
at RequestResults(: 3)
at Request Results. ()
at RequestResultSresult()
at sunreflect Native MethodAccessorImpl invoke(Native Method
at sun reflect. NativeMethodAccessorlmpl invoke(Unknown Source)
源值域
f1
目标值域
Symbo l
I nt
f1(
a
f1(‘b)
●2
b●
f1(‘c)
●3
●5
由于与’d和’e相对应的nt对象没有,所以f1是部分函数。如果具
有所有 Sybmo|元素x相应的(x)=>nt对的话,那就称为全函数。
冈6-1定义为源值域与目标值域映像的函数
函数本米不就因该是这样的吗?但是问题是,如果将函数定义域中没有的参数传给组1函数后将会抛出例
外。为了避免这种情况在对于某·值适用函数前可以先检下该值是否在定义域中。部分函数
( Partialfunction)定义为我们提供了这种结构。
def f2: Partial Function [Symbol, Int
icase'a=>1; case 'b=>2: casec=>33
scala> for(s < List('a, "b, 'c, 'd)) if(f2 is DefinedAt(s))println(f2(s))1
用部分函数定义了玛A=>B函数之后,就可以在适用函数前宄使用 isDefinedat(x:A)方法米确定定义域
http://fineqtbull.javaeye.com/http://scalacn.comhttp:/lscalagroup.group.javaeye.com/i4/4
Scala讲座:献给追求创意兴奋的程序员(5)
Scala语言探险三
。所谓的部分函数就是,对于反应源值域到口标值域的映射的函数f:A=>B,不一定存在对应于x ReturnTyp是以类
FunctionNLArgType1, rg TypeN, Return Type的实例形式被定义的。N是表小参数个数的正整数
如果是1个参数的话则是 Function1 ArgType1, ReturnTypel
def double(n: Int): Int=n *2
上述函数基本上与下述定义是等同的。
object double extends Function1 LInt, Int] i
def apply(n: Int): Int=n*2
scala> double(10)
s1: nt= 20
那么各个对象的方法也可以称得上对象吗?作为测试,试着将 MyFunctions对象的方法绑定于变量。
scala> val fl= MyFunctions foo
: 8: error: missing arguments for method foo in object My Functions
follow this method with if you want to treat it as a partially applied funct.
val f1= MyFunctions foo
看来光是方法原样是不能作为函数对象来处理的。实际上只要将方法简单地转换一下就可以作为对象来
使用了。在方法名后空格加上“”就可以了
scala> val f1= My Functions. foo
f1:(String, Int)=> Int=
ala>组1( abcde",3)
res13: Int=15
这样处理之后,我们就可以明白对象的方法乜可以像属性一样作为对象来统一处理了。 Scala语言在这
点上可以说比 Smalltalk那种纯面向对象语言还贯彻了面向对象的思想。
8.高阶函数和延迟评估参数
因为 Scala的函数是对象,所以不要做什么特殊处只要将他作为参数传给别的函数就自然而然地成为
使用高阶函数了。函数将别的函数作为参数来使用,所以称之为高阶函数。这时被传递的函数就称为闭包。
用于List统一操作的函数群就是髙阶函数的典型例ε下面的 foreach函数,接受了以O或形式定义的
闭包作为参数,然后将其逐一适用于接受者列表的所有元素。
scala> val list= List("Scala,"is","functional","language")
list: Listljava lang String]= List(Scala, is, functional, language)
http://fineqtbull.javaeye.com/http://scalacn.comhttp:/lscalagroup.group.javaeye.com/i5/5
Scala讲座:献给追求创意兴奋的程序员(5)
Scala语言探险三
scala> list. foreach ie=> printIn(e),
ala
functional
language
对于同一列表list适用map函数后,对于列表list的所有元素适用s=>s+“”函数后将适用结果以列
表的形式返冋。这里用空格代替了调用方法的“”,然后用(_+“”)替代(s=>s+“:”)也是可以的。
scala> list map(s =>s+"
res15: Listljavalang Stringl= List(Scala!, is!, functional!, language
scala> list map(+!")
res16: Listljavalang Stringl= List(Scala!, is!, functional!, language!)
进一步, Scala中除了有组1(pl:T1这种通常的“基于值的参数传递( by value parameter)”,还有表示为
P2D2=>12)的“基于名称的参数传递( by name parameter)”,后者用于参数的延时泮估。将这个结构
和高阶函数相混合后,就可以简单地定义新的语言控制结构了。下面是新语言结构 WhIle的定义和使
用例。
if(p)is, MyWhile(p (s)/ Is:=> Unit)(
def MyWhile (p:=> Boolean)(
scala>ⅴ ar i: Int=0
i: Int=o
scala> My While(i<3)li=i+1; print("World")3
Worldworldworld
scala> My While(true) iprint("World is unlimited,),
无限循环
像这样充分利用了函数式语言的特点之后,我们会惊奇地发现像定义DSL(特定领域语言)那样进行语
言的扩展是多么的容易和自由。
9.模式匹配
Scala的case语句非常强大,可以处理任何类型的对象。mach"内部列岀了case模式=>语句。为了
确保覆盖性可以在末尾加上
scala> val value: Any ="string
value: Any =string
scala> value match
case null=> println(null
case i: Int=> printIn (Int:"+
case s: String = println('String:"+s)
case_=> println(Others")
String: string
这次匹配一下 Person类的对象
http://fineqtbull.javaeye.com/http://scalacn.comhttp:/lscalagroup.group.javaeye.com/I6/6
Scala讲座:献给追求创意兴奋的程序员(5)
Scala语言探险三
scala> class Person(name: String)
defined class person
scala> val value: Any new Person("Zhang Fei)
value Any= Person e90097
scala> value match
case null = println(null! "
case i: Int=> println(Int:"+i)
case s: String = printIn('String:"+s)
case=> println("Others")
Others
10.Case类
在 Scala中模式匹配的不仅是对象,对象的属性和类型等也可以作为模式来匹配
例如,假设想匹配 Person类,一般情况下最多就是指定“: Person”米匹配属于 Person类的对象了。
scala> val value: Any new Person("Zhang Fei")
value: Any = Personle3c2c6
scala> value match
case_: Person = printIn("person: who)
case=> println("others: what")
person who
不过如果使用了Case类之后,对象内的公有属性变得也可以匹配了。定义类时只要把“cass"换成“case
class”之后,编译器就会自动定义和生成同名的单例对象。并且在该单例对象中自动定义了返回该类实例
的 apply方法,以及返回以构造函数的参数为参数的Some类型(范型)对象的 unapply(或 unapply Seq)
方法。并且,还自动定义了 equals、 hash Code和 tostring方法。
定义 apply方法的效果是,只要定义好果个Case类之后,就可以用“类名(参数列表)”的形式来创建
对象了。定义 unapply方法后的效果是,可以在case语句中以Case类的构造函数的参数(对象属性)
来作为匹配日标了。
scala> case class person(name: String)/定义Case类 Person
defined class person
scala> val value:Any= Person(" Zhang fei")∥不用new就可以创建对象
value: Any= Person(Zhang Fei)
scala> value match t
case Person(ns)=> println(" person:"+ns)以将 Person的属性作为匹配目标
case_=> printIn(others: what")
person: Zhang fei/ Person的属性name将会被抽取出来
下面是将将整数N(y)、AddQ,r)和Mult,r)组合后来变现四则运算Term。由于是以case形式定义的
类,请注意一下在创建Term对象时,不用new就可以直接调用N(5)、Add(.)、Mut(.)实现了。如此
使用 Scala的模式匹配功能后就可以很方便地实现对象的解析工作了。
abstract class term
http://fineqtbull.javaeye.com/http:/scalacn.comhttp:/scalagroup.group.javaeye.com/57/7
Scala讲座:献给追求创意兴奋的程序员(5)
Scala语言探险三
case class n(y: Int) extends Term
case class add( Term. r: Term) extends Term
case class mult(1: Term r Term) extends Term
def eval(t: Term): Int=t match i
case N(v)=>v
case Add(l r)=> eval(+ eval(r
case Mult( r)=> eval(* eval(r)
scala> eval(Mult(N (5). Add(N (3)N(4))
res7Int=35∥5*(3+4)
附带说一下,上述的Term类可以认为是作为N、Add和Mult类的抽象数据类型来定义的。
11.将模式匹配与for语句组合
下面就看一下将模式匹配与for语句组合在一起的技巧。
scala> val list=List(1,"a"),(2,"b"),(3,"c"),(1,"z"),(1,"a")
list: List[(Tnt, java. lang. String)]= List((1, a), (2, b),(3, c), (1, 7), (1, a))
这时在<前面写的是像(1,x)一样的模板。
scala> for( (1, x)<- list)yield (1, x)
res6: List[(nt, java. lang String)]= List((1, a), (1, z),(1, a)
而且非常令人惊奇的是<前面没有变量也是可以的。在<之前写上(1,“a”)之后,for语句也可以正常地
循环并且正确地返回了两个元素。
scala>for((1, "a")<-list )yield (1,"a
res: List[(Int, java. lang String)]=List((1, a),(1, a)
还有在使用 OptionIs类来避免判断nul的情況下,传入 ListlOption]类型的列表时,不用显示的判
断是否是Some还是None就可以一下子返回正确的结果了。
scala> val list= List(Some(1), None. Some(3). None. Some(5))
list: ListLOption[Int]=List(Some(1), none, Some (3), None, Some(5))
scala> for(Some(v)<- list)println(v)
接着用以下的例子看一下组合模式匹配和for语句之后所产生的威力。
scala> val list= List(1."two. Some(3).4."five".6.0.7)
list: ListLAny]=List(1, two, Some(8), 4, five, 6.0, 7)
对上述例表中的元素对象类型进行判别后再分类下吧。模式匹配里不仪可以使用值来作为模式,从下
例可知模式还具有对Some(x)形式中的ⅹ也起作用的灵活性
for(x <-list) x match
case x: Int=> println ("integer"+x)
case x' String = println(string"+x)
case Some(x)=> println("some"+x)
case = println(else "+ x)
http://fineqtbull.javaeye.com/http://scalacn.comhttp://scalagroup.group.javaeye.com/58/8
Scala讲座:献给追求创意兴奋的程序员(5)
Scala语言探险三
scala> for(x <-list( x matchi
case x: Int=> println("integer"+x)
case x String = printIn("string"+x)
case Some(x)=> printIn("some"+
case_-> println(else"+x)
Integer
string two
some 3
integer 4
string five
Ise 6.0
integer 7
12.结束语
看了本文之后大家觉得怎么样呀?应该享受了 Scala所具备的,将面向对象式和函数式语言功能充分融
合的能力,以及高阶价函数和模式匹功能了吧。
Scala话法的初步介绍就到本讲为止了,接下来的讲座将介绍一下 Scala语言更深入的部分。包括隐式
转换、范型和单子等有趣的话题。
http://fineqtbull.javaeye.com/http://scalacn.comhttp:/lscalagroup.group.javaeye.com/it9/9
(系统自动生成,下载前可以参看下载内容)
下载文件列表
相关说明
- 本站资源为会员上传分享交流与学习,如有侵犯您的权益,请联系我们删除.
- 本站是交换下载平台,提供交流渠道,下载内容来自于网络,除下载问题外,其它问题请自行百度。
- 本站已设置防盗链,请勿用迅雷、QQ旋风等多线程下载软件下载资源,下载后用WinRAR最新版进行解压.
- 如果您发现内容无法下载,请稍后再次尝试;或者到消费记录里找到下载记录反馈给我们.
- 下载后发现下载的内容跟说明不相乎,请到消费记录里找到下载记录反馈给我们,经确认后退回积分.
- 如下载前有疑问,可以通过点击"提供者"的名字,查看对方的联系方式,联系对方咨询.