Scala2.11.7学习笔记(二)函数定义

鲁春利的工作笔记,好记性不让烂笔头


函数定义

def 函数名(参数列表) : 返回类型 = {函数体}

说明:

    返回类型默认为空(Unit,类似于Java的void);

    函数体中默认最后一行为该函数的返回值;

    函数如果有返回值,则=号是必须的,否则可以省略等号;

    如果函数有返回值但返回类型指定为Unit,则任然无返回值;

    函数体中是不建议使用return语句的,但如果出现了return语句,则必须指定返回类型。


1、无返回值的函数举例

package com.lucl.scala

/**
 * @author lucl
 */
object ClassWithUnitFunc {
  def sayHi (name : String) {    // 无返回值,=号被省略
    println("hello, " + name);
  }
  
  def main (args : Array[String]) {
    sayHi("luchunli");    // hello, luchunli
    println("sayHi return , " + sayHi("luchunli"));    // sayHi return , ()
  }
}

    说明:Unit为无返回值,调用时返回()

2、有返回值的函数举例

package com.lucl.scala

/**
 * @author lucl
 */
object ClassWithReturnValFunc {
  def sayBye (name : String) {
    "bye, " + name;
  }
  
  def sayOk (name : String) = {
    "ok, " + name;
  }
  
  // 有return必须给定返回类型
  def sayGood (name : String) : String = {
    // method sayGood has return statement; needs result type
    return "good, " + name;
  }
  
  def main (args : Array[String]) {
    println(sayBye("luchunli"));    // ()
    println(sayOk("luchunli"));    // ok, luchunli
    println(sayGood("luchunli"));    // good, luchunli
  }
}


3、方法调用

    无参方法调用时可以省略括号;

    有参方法调用时必须带括号及参数。

package com.lucl.scala

/**
 * @author luchunli
 */
object FuncTest {
  // 无参函数
  def greet () {
    println("greet");
  }
  
  // 有参函数
  def hello (name : String) {
    println("hello, "  + name);
  }
  
  // 函数只有一条语句,{}也可以省略
  def goodbye = println("good bye");        
  
  def main (args : Array[String]) {
    greet;                      // 无参函数调用时可以省略()
    greet();                    // 
    hello("luchunli");          // 有参函数不可省略
    println(greet() == ());     // true
    goodbye;                    // good bye
  }
}


4、默认参数

有些情况下我们不需要给出全部参数,可以使用默认参数,但需要知道参数顺序或者参数名称。

package com.lucl.scala

/**
 * @author luchunli
 */
object FuncDefaultArguments {
   def sayHi (word : String, name : String = "luchunli") {
     println(word + ", " + name);
   }
   def main (args : Array[String]) {
     sayHi("hello");                // hello, luchunli
     // 通过名称指定参数
     sayHi(word="hello");           // hello, luchunli
     sayHi(word="hi", "zhangsan");  // hi, zhangsan
   }
}


5、变长参数

实现一个可以接受可变长度的参数列表的函数。

package com.lucl.scala

/**
 * @author lucl
 */
object FuncWithVarargs {
  def vsum (args : Int*) {
    var result = 0;
    for (arg <- args) {
      result += arg;
    }
    println("The result " + result);    // The result 15
  }
  
  def sayHi (args : String*) {
    print("Hi, ");
    args.foreach {print};    // luchunlizhangsanlisi
    println;
  }
  
  // 在递归中我们同样可以使用这种方式,Scala编译器不能推断递归函数的返回类型,必须给定。
    def sum2(args : Int*) : Int = {
    if(args.length == 0 ) {
      0  
    } else { 
      // 序列的head是参数args的首个元素,而tail是所有其它的元素序列
      args.head + sum2(args.tail: _*) 
    }
   }       
  
  def main(args : Array[String]) {
    vsum(1, 2, 3, 4, 5);
    // 实现一个序列作为参数传入,需要追加 _*,告诉编译器希望把这个参数当做序列处理。如:
    vsum(1 to 5 : _*);    // 将1到5当做参数序列处理
    sayHi("luchunli", "zhangsan", "lisi");
    // 
    println(sum2(1 to 5 : _*));    // 15
  }
}

    实际上Java中也支持这种动态参数:

package com.lucl.apps.web.sample;
/**
 * @author luchunli
 *
 */
public class JavaDynamicParams {

    public void sayHi (String ...params) {
        for (String str : params) {
            System.out.print(str + ", ");    // luchunli, zhangsan, lisi, 
        }
        System.out.println("");
    }
    
    // 
    public static void main(String[] args) {
        JavaDynamicParams dy = new JavaDynamicParams();
        dy.sayHi("luchunli", "zhangsan", "lisi");
    }

}


6、局部函数

实际上就是在函数里面再定义一个函数。

package com.lucl.scala

import scala.io.Source
import java.io.File

/**
 * @author luchunli
 */
object FuncWithPart {
  
  def processFile  () {
    val file = new File("F:\\ftpfile\\ip.txt");
    var source = Source.fromFile(file);
    
    for (line <- source.getLines()) {
      processLine (line);
    }
    // 定义局部函数,只在当前函数范围内有效
    def processLine (x : String) {
      if (null == x || "".equals(x.trim)) {  // 去掉空行
        // ...
      }
      if ((x indexOf "*") != -1) {           // 去掉无效的数据行
        // ......
      }
      println("Line : " + x);
    }
  }
  
  def main(args : Array[String]) {
    processFile();
  }
}


7、匿名函数

Scala把函数当作内置的值,也就是说函数可以放进var或val中,并和其他任何值所受的对待毫无二致,被称为函数字面值或匿名函数。

定义函数字面值,关键是箭头=>,定义格式如下:

(函数参数列表) => {作为代码块的函数体}

package com.lucl.scala

/**
 * @author luchunli
 */
object FuncOfAnonymity {
  
  // 省略代码块的{}
  var doubler = (x : Int) => x * 2;
  
  // 匿名函数传入n之后得到的仍然是个匿名函数
  // 即函数的函数,接收一个值并返回一个新的函数字面值:
  val adder = (n : Int) => {
      (x : Int) => x + n; 
  }
  
  // 无参匿名函数
  var noParam = () => println("Hello World!");
  
  // 函数作为参数,格式为def 函数名(函数名:(参数类型, 参数类型, ...) => 返回值, 其他参数)
  def processNum (f : (Int, Int) => Int, m : Int, n : Int) {
    println(f (m, n));        // 5
  }
  
  
  def main (args : Array[String]) {
    println(doubler(3));      // 6
    println(adder(3));        // <function1>  
    var plug = adder(3);      // 获得一个函数
    println(plug(2));         // 5
    noParam();                // Hello World!,而noParam表示的为()
    
    val add = (a : Int, b : Int) => a + b;
    processNum(add, 2, 3);  
  }
}


你可能感兴趣的:(function,scala2.11.7)