Scala语言初入门
来源:互联网 发布:美元霸主地位知乎 编辑:程序博客网 时间:2024/05/17 04:51
scala介绍
- Scala语言来自于Scalable(可伸缩的)既可以写一些小的脚本,又可以写一写复杂的服务器端的程序。
- Scala是一门纯正的面向对象语言,具有OO特征。
- Scala是一门函数式语言,可以用函数式思想来编写代码
- Scala是构建于JVM之上的,与java可以无缝互操作。
函数式编程思想
函数式编程基本名词介绍
纯函数来编写程序。
- 纯函数(Pure Function),或函数的纯粹性(Purity)没有副作用(side Effect)
- 副作用是状态的变化
- 例子
- 修改全局变量
- 抛出异常
- IO读写
- 调用有副作用的函数
var x = 1def XplusY_V1(y:Int) = x + ydef XplusY_V2(y:Int) = {x += y;x}
上面第一个函数是输入一个int类型的y,第二个函数是输入一个int类型的y返回值是x。
第二个函数相对于第一个函数对变量x产生了副作用。改变了x的值。
* 引用透明(Referential Transparency)对于相同的输入,总能得到相同的输出。
如果f(x)的参数x和函数体都是引用透明的,那么函数f是纯函数。
违反引用透明
- 不变性(Immutability)为了获得引用透明性,任何值都不能发生变化。
函数是一等公民(First-class Function)一切都是计算,函数式编程中只有表达式,变量、函数都是表达式。
函数也可以作为参数或者返回值。表达式求值策略:严格求值和非严格求职。
Call By Value属于严格求值
Call By Name属于非严格求职- 惰性求值(Lazy Evaluation)当定义这个变量时不会立即求值,只有在使用到这个变量时才会求值。
- 递归函数(Recursive Function)
在函数式编程中没有循环语句,所有的循环都要用递归来实现。
递归有个性能问题。容易堆栈溢出。
* 尾递归(Tail Recursion)
函数式编程的优点
- 生产效率高
同样的功能,Lisp(世界上第一个函数式编程语言)代码长度可能是C代码长度的七到十分之一。 - 易于推理
- 并行编程
因为是纯函数,所以不会引起线程紊乱。 - 多核计算、云计算
搭建scala环境
安装JDK
下载JDK最新版本,将环境变量添加到配置文件中
安装Scala的运行环境和包
从http://www.scala-lang.org/download上下载了Scala的最新版本,将环境变量添加到配置文件中就可以用了。
REPL(Read Evaluate Print Loop)就是scala命令行的运行环境。
在linux命令行输入scala就可以直接进入到scala REPL中。
devil@devilshome:~$ scalaWelcome to Scala 2.12.0-M4 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_60).Type in expressions for evaluation. Or try :help.scala> println("Hello World")Hello Worldscala>
println()函数在所有Scala代码中都可用。
scala> val x =1x: Int = 1scala> var x = 1x: Int = 1scala>
var 和 val 的区别稍后解释。
使用eclipse开发scala
在http://scala-ide.org/download/sdk.html下载专为scala的eclipse
- new一个Scala Project
- new 一个Scala Worksheet
worksheet是可以在IDE中直接进行代码的运行和结果的获得,是交互式的。
默认直接生成一个Object
object worksheet { println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet val x = 1 //> x : Int = 1 println(x) //> 1}
输入代码以后保存,会直接把输出的结果打印在右边。
新建一个package demo01
在package中新建一个scala app
package demo01object Greeting extends App {println("Hello,"+args(0)+"!")}
运行时设置main class和参数,main class的格式为包名.类名。
在控制台查看打印输出的结果
Hello,Devil!
使用命令行编译scala
在文件夹中新建一个.scala文件,如Greeting.scala
在命令行中键入
devil@devilshome:~/example$ scalac Greeting.scala
编译完成后,原文夹下多了一个Greeting.class文件,这个就是编译后的字节码文件。
再对这个字节码文件进行使用。
devil@devilshome:~/example$ scala Greeting JackHello,Jack!devil@devilshome:~/example$ scala Greeting DevilHello,Devil!
变量和表达式
变量
- var 自动生成读写接口,代表的是一个可变的有类型的存储单元。可以在定义变量时为它指定数据,而且可以在任何时间重新赋值。
- val 只生成了只读接口是一个不可变得、有类型的存储单元。可以在定义值时为它指定数据,不过不允许重新赋值,代表是一种函数式的思维。val蕴含了final的语义。
- lazy val 定义惰性求值的常量。
可以不显示指定变量的类型,因为Scala会自动进行类型推导。
scala> val x=10x: Int = 10scala> val y :Int =20y: Int = 20scala> x+xres0: Int = 20scala> res0res1: Int = 20scala> res0*res1res2: Int = 400scala> z=200<console>:16: error: reassignment to val z=200 ^//val的值不能被修改scala>
scala> val d = 20d: Int = 20scala> val e = 30e: Int = 30scala> lazy val f = d * ef: Int = <lazy>scala> f * 10res3: Int = 6000scala> fres4: Int = 600scala>
精度问题
scala> val b :Byte = 10b: Byte = 10scala> val x :Long = 10x: Long = 10scala> val y :Long = by: Long = 10scala> val z : Byte = x<console>:12: error: type mismatch; found : Long required: Byte val z : Byte = x ^scala>
- 字符类型
scala> val q = 'X'q: Char = X
- Unit类型
Scala中的Unit类型类似于java中的void。主要的不同是在Scala中可以有一个Unit类型值,也就是(),然而java中是没有void类型的值的。除了这一点,Unit和void是等效的。一般来说每一个返回void的java方法对应一个返回Unit的Scala方法。
scala> val u : Unit=()u: Unit = ()scala> val p = ()p: Unit = ()
- Nothing
对于一个函数而言,如果返回值是nothing,则表名该函数发生了异常。
scala> def foo() = throw new Exception("error occurred")foo: ()Nothing
- String
构建于java的String之上。
新增了字符串插值(interpolation)的特性
scala> val name = "devil"name: String = devilscala> s"my name if ${name}"res5: String = my name if devil
- Block
在scala中,代码块用于组织多个表达式,block也是一个表达式,其最终的求得的值是最后一个表达式的值。
函数
object func_wxamples { def hello(name: String): String = { s"hello,${name}" } //> hello: (name: String)String hello("devil") //> res0: String = hello,devil def hello2(name: String) = { s"hello,${name}" } //> hello2: (name: String)String hello2("devil") //> res1: String = hello,devil def add (x:Int,y:Int) = x+y //> add: (x: Int, y: Int)Int add(5,3) //> res2: Int = 8}
if表达式
在scala中,if是表达式,而不是语句。
object fun_if_example { if (true) 1 else 2 //> res0: Int = 1 if (false) 3 else 4 //> res1: Int = 4 val a = 1 //> a : Int = 1 if (a == 1) a //> res2: AnyVal = 1 if (a != 1) "不是1" //> res3: Any = () if (a != 1) "不是1" else a //> res4: Any = 1}
for循环
object fun_for_examples { val l = List("elisa", "sin", "satoshi") //> l : List[String] = List(elisa, sin, satoshi) for ( s <- l //用s循环遍历l中的元素 ) println(s) //> elisa //| sin //| satoshi for ( s <- l if (s.length > 3) ) println(s) //> elisa //| satoshi val result_for = for { s <- l s1 = s.toUpperCase() if (s1 != "") } yield (s1) //> result_for : List[String] = List(ELISA, SIN, SATOSHI)}
yield (s1)的意思是将s放入一个新的collection中。
try表达式
try{}catch{}finally{}//无论有没有发生异常,我们都会执行finally这个代码块
match表达式
exp match{ case p1 => val1 case p2 => val2 … case _ => valn}
object func_match_example { val code = 3 //> code : Int = 3 val result_match = code match{ case 1 => "one" case 2 => "two" case _ => "three" } //> result_match : String = three}
求值策略
scala里有两种求值策略(Evaluation Strategy)
- Call By Value 对函数实参求值,且仅求值一次
- Call By Name 对函数实参每次在函数体内被用到时都会求值。
scala通常使用 Call By Value
如果函数性参类型以 => 开头,那么会使用Call By Name
def foo(x:Int) = x //Call By Valuedef foo(x:=>Int) = x //Call By Name
scala> def bar(x:Int,y: => Int)=1bar: (x: Int, y: => Int)Intscala> def loop(): Int = looploop: ()Intscala> bar(1,loop)res6: Int = 1scala> bar(loop,1)
第二个bar(loop,1)在进行死循环,因为x是Call By Value的需要对所有表达式求值才能进行下一步运算。
高阶函数
scala中函数是第一等公民
Scala语言支持:
1. 把函数作为实参传递给另外一个函数
2. 把函数作为返回值
3. 把函数赋值给变量
4. 把函数存储在数据结构中
在scala中,函数就像普通变量一样,同样也具有函数类型。
- 在scala中,函数类型的格式为 A=>B,表示一个接收类型A的参数,并返回类型B的函数。
高阶函数
用函数作为形参或返回值的函数,成为高阶函数
匿名函数
就是函数常量,也成为函数文字量。
在scala里,匿名函数的定一个是为(形参列表)=>{函数体}
柯里化
柯里化函数把具有多个参数的函数转换为一条函数链,每个节点上是单一参数。
eg:下面两个函数的定义是等价的
def add(x: Int,y: Int) = x+y
def add(x: Int)(y: Int) = x+y
递归函数
递归函数在函数式变成中是实现循环的一种技术。
def factorial(n: Int): Int = if (n<=0) 1 else n* factorial(n-1)
尾递归
尾递归函数中所有递归形式的调用都出现在函数的末尾。
当编译器检测到一个函数调用是尾递归的时候,它就覆盖当前的活动记录而不是在栈中去创建一个新的。
避免堆栈溢出
@annotation.tailrec //告诉scala编译器,对这个递归进行尾递归优化 def factorial(n: Int,m: Int): Int = if (n<=0) m else factorial(n-1,m*n) factorial(5,1)
在上面这个案例增加了一个m,m其实是保留了n*n-1*n-2……这样一个累乘器。
m永远拿到都是过去几次累乘的结果。
- Scala语言初入门
- Scala语言编程初入门
- 炼数成金Scala语言入门
- Scala语言开发入门
- scala语言入门
- 炼数成金Scala语言入门
- scala语言基础入门(1)
- scala入门初介
- Scala入门到精通——第一节 Scala语言初步
- Scala入门到精通——第一节 Scala语言初步
- Scala入门到精通——第一节 Scala语言初步
- Scala语言入门之环境配置
- Scala入门
- scala 入门
- scala入门
- scala 入门
- scala入门
- Scala入门
- ArcGIS连接局域网另一台电脑上的SQLServer数据库
- [转]Linux GCC常用命令
- 第十六周项目一 d阅读程序(3)
- 5710 Digit-Sum(找规律)
- 真机中ssh连接virtualBox中的虚机
- Scala语言初入门
- Android Handler 机制
- Android onSaveInstanceState与onRestoreInstanceState
- Linux下搭建本地yum源,rpm 安装,源码安装
- leetcode笔记--Minimum Depth of Binary Tree
- Android 面试精华题目总结
- Docker Blog List
- 运输问题(最小费用流)
- 《剑指offer》:[32]从1到n整数中1出现的次数