scala系列知识点总结(变量与普通函数)
写在前面:scala是一种函数式编程&完全的面向对象语言(百度“函数式编程”更精彩),它是与指令式编程语言相对应的,前者强调函数的计算比指令的执行重要(事实上指令不能达到完全的面向对象,也会产生很多冗余的代码)。它最大的特点在于函数式编程思想。在scala里面,一切都是对象,函数被当做一等公民对待,可以像基本数据类型一样自由的使用。
当然scala还有其他很多有趣的特性,包括使用换行作为结束符(当然也支持分号,不过不推荐使用),抛弃了return命令(同样支持不推荐),lambda表达式(有兴趣可百度“λ推演”,它可以说是计算机的起源,不过需要较高的数学水平才能看懂。),高阶函数,闭包等。话不多说,进入正题。
首先给出scala中的关键字,我觉得学习的步骤可以就根据关键字来,把所有关键字的用法熟悉了,就算初步入门了:
1.变量声明
变量声明:var name:ClassType[=value],例:
var myVar2:Int=1
var myVar3:Float=0.15F (不加F就默认为Double类型的)
var myVar3:Float=0.15F (不加F就默认为Double类型的)
也可以不指定类型,其类型可以通过初始值推断出来:
var myVar=0
var myVar1="hello world"
var myVar1="hello world"
多变量连续声明:
var x,y=100
元组声明:
var pair:(Int,String)=(1,"wonking")
2.函数
在数学里面,函数是一种映射,即将一个(或一组)数据映射为另外一个数据的过程(多输入,单输出)。映射中有一个完全映射和不完全映射的概念,所以这里也就有一个偏函数和完全函数的概念
普通的方法都是“完全函数”,f(i:Int)={}是将所有Int类型作为参数的,是对整个Int集的映射
写成{case x=>y}这种形式的叫做“偏函数”,必须用大括号"{}",使用"()"会报错,case里面只能实现部分数据集的映射,所以叫偏函数
有了这样一个印象之后再来看函数是怎么定义和使用的
最标准的写法: def funcName(a:Int , b:Int):returnType={}
1.如果去掉":returnType",编译器会根据函数中最后执行的一段代码自动推断函数的返回结果,例:
def noArgu={
println("test no argument")
10 //返回10
}
println("test no argument")
10 //返回10
}
2.如果去掉":returnType=",编译器会返回Unit,相当于Java中的Void(如果你的函数有返回值一定不能省掉=),例:
def printMe(){
println("hello world")
}
以上写法也等价于下面的(不过这是画蛇添足):
def printMe():Unit = {
println("hello world")
}
println("hello world")
}
3.如果函数体只有一行,可以去掉{},例:
def printMe()=> println("hello world")
4.如果没有参数,还可以去掉"(a:Int,b:Int)",就像这样
def printMe=> println("hello world")
def printMe=> println("hello world")
温馨提示:scala中函数定义的语法比较宽松,形式自由,所以大家看到有其他什么形式的函数定义不要吃惊,先敲到编译器里面试一试,能通过就表示这种方法是可行的
3.传名调用 PK 传值调用
先讲一下“惰性计算”的概念。“惰性计算”是指表达式不是绑定到变量时立即计算的,而是在需要用到的时候实时执行的,这样做的好处是,不需要担心由无穷计算所导致的out-of-memory的错误,因为如果是立即绑定的话,可能出现递归计算,导致栈溢出。
“传名调用“就是scala里面的”惰性计算“,例:
object Test {
def main(args: Array[String]) {
delayed(time());
}
def time() = {
println("获取时间,单位为纳秒")
System.nanoTime
}
def delayed( t: => Long ) = { //=>表示作传名处理
println("在 delayed 方法内")
println("参数: " + t)
t
}
}
def main(args: Array[String]) {
delayed(time());
}
def time() = {
println("获取时间,单位为纳秒")
System.nanoTime
}
def delayed( t: => Long ) = { //=>表示作传名处理
println("在 delayed 方法内")
println("参数: " + t)
t
}
}
可以把这个敲出来看一下运行结果是什么。怎么样?有没有看到C++里面内联函数的影子
”传值调用“的话不用作特殊处理默认都是传值调用
4.其他函数写法
函数传参顺序:一般情况下函数调用参数,就按照函数定义时的参数顺序一个个传递。但是我们也可以通过指定函数参数名,并且不需要按照顺序向函数传递参数,例:
object Test {
def main(args: Array[String]) {
printInt(b=5, a=7); //这里参数顺序与定义的不一样,但指定了参数名
}
def printInt( a:Int=0, b:Int=0 ) = { //设置默认参数值
println("Value of a : " + a );
println("Value of b : " + b );
}
}
object Test {
def main(args: Array[String]) {
printInt(b=5, a=7); //这里参数顺序与定义的不一样,但指定了参数名
}
def printInt( a:Int=0, b:Int=0 ) = { //设置默认参数值
println("Value of a : " + a );
println("Value of b : " + b );
}
}
可变参数:scala 通过在参数的类型之后放一个星号来设置可变参数,例:
object Test{
def main(args:Array(String)){
printStrings("wonking","alise","coco")
}
def printStrings(args:String*){
var i=0
for(arg <- agrs){
println("value["+i+"]="+arg)
++i;
}
}
}
object Test{
def main(args:Array(String)){
printStrings("wonking","alise","coco")
}
def printStrings(args:String*){
var i=0
for(arg <- agrs){
println("value["+i+"]="+arg)
++i;
}
}
}