4、Scala函数式基础-创新互联

一、内置控制结构

遂溪ssl适用于网站、小程序/APP、API接口等需要进行数据传输应用场景,ssl证书未来市场广阔!成为创新互联公司的ssl证书销售渠道,可以享受市场价格4-6折优惠!如果有意向欢迎电话联系或者加微信:028-86922220(备注:SSL证书合作)期待与您的合作!

    1、if表达式


        val filenameNice = if (!args.isEmpty) args(0) else "default.txt"

    2、while循环


        不管是while还是do...while,我们都不能叫做表达式,而应该叫做循环,因为它们不会计算出一个新值。它们的值类型是Unit,在scala中Unit和()是相等的

        def gcdLoop(x: Long, y: Long): Long = {

       var a = x

       var b = y

       while (a != 0) {

        val temp = a

        a = b % a

        b = temp

       }

       b

      }

    do...while...表达式

        var line = ""

      do {

       line = scala.io.StdIn.readLine()

       println("Read: " + line)

      } while (line != "")

        在scala中给var重新赋值,永远都是返回()(即Unit)

      () != ""将永远返回true

      var tempLine = ""

      while ((tempLine = scala.io.StdIn.readLine()) != "") // This doesn't work!

       println("Read: " + tempLine)


      因为while循环不计算出值,所以while的代码不那么的函数式,一般都会含有var变量,

      scala选择保留while是因为有些场景使用while的代码的可读性还是很强的

      采用递归来消除掉var

      def gcd(x: Long, y: Long): Long =

       if (y == 0) x else gcd(y, x % y)

    3、for表达式


         用for表达式迭代一个任意集合

       val filesHere = (new java.io.File(".")).listFiles

      for (file <- filesHere)

       println(file)

      for表达式中的过滤

      for (

       file <- filesHere

       if file.isFile

       if file.getName.endsWith(".scala")

      ) println(file)


        嵌套迭代(nested iteration)

      def grep(pattern: String) =

       for (

        file <- filesHere

        if file.getName.endsWith(".scala");

        line <- fileLines(file)

        if line.trim.matches(pattern)

       ) println(file + ": " + line.trim)

         可以在迭代的过程中,绑定中间值到一个变量

      上面的()可以换成{},这样每一个语句后面的分号就可以省略

      def grepBindValue(pattern: String) =

       for {

        file <- filesHere

        if file.getName.endsWith(".scala")

        line <- fileLines(file)

        trimmed = line.trim

        if trimmed.matches(pattern)

       } println(file + ": " + trimmed)

      for ... yield ... 可以生成一个新的集合

      //返回的是Array,是因为filesHere的类型是Array

      def scalaFiles: Array[File] =

       for {

        file <- filesHere

        if file.getName.endsWith(".scala")

       } yield file


      val forLineLengths: List[Int] =

       for {

        file <- filesHere.toList

        if file.getName.endsWith(".scala")

        line <- fileLines(file)

        trimmed = line.trim

        if trimmed.matches(".*object.*")

       } yield trimmed.length

    4、异常处理


        scala中抛异常使用throw关键字,异常的捕获用catch关键字。捕获到异常后,可以计算并返回一个值

          val n = 5

          val half: Int =

           if (n % 2 == 0)

            n / 2

           else

            throw new RuntimeException("n must be even")

          println(half)


        try {

           //val f = new FileReader("input.txt") //这个会抛FileNotFoundException

           // Use and close file

           throw new IOException("test")

          } catch {

           case e @(_: FileNotFoundException | _: IOException) => {

            // Handle missing file

            println("All Exception = " + e.getMessage)

           }

           case ex: Exception => {

            // Handle other I/O error

            println("IOException = " + ex.getMessage)

           }

          }


          val file = new FileReader("input.txt")

          try {

           // Use the file

          } finally {

           file.close() // Be sure to close the file

          }

    5、break和continue


            非得使用break的话,我们可以使用scala.util.control中的break

              import scala.util.control.Breaks._

              import java.io._

              val in = new BufferedReader(new InputStreamReader(System.in))

              breakable {

               while (true) {

                println("? ")

                if (in.readLine() == "") break

               }

              }

二、函数

    1、本地函数。定义在函数内部的函数为本地函数,智能被此函数内部调用。


     def processFile(filename: String, width: Int) = {

      //本地函数

      def processLine(line: String) = {

       if (line.length > width)


        println(filename + ": " + line.trim)

      }


      val source = Source.fromFile(filename)

      for (line <- source.getLines())

       processLine(line)

     }

    2、first class function  函数可以作为函数的参数进行传递

    3、函数的参数

        不定长参数

        def echo(args: String*) =

          for (arg <- args) println(arg)


        使用参数名字来给参数设置值

         def speed(distance: Float, time: Float): Float =

          distance / time

         speed(distance = 100, time = 10)


         默认参数值

        def printTime(out: java.io.PrintStream = Console.out) =

          out.println("time = " + System.currentTimeMillis())

         printTime()

         printTime(Console.err)

    4、函数闭包

    函数捕获一个自由变量而变成一个闭包。 每次调用函数的时候都产生一个新的闭包。

        var more = 1

        val addMore = (x: Int) => x + more //函数捕获一个自由变量而变成一个闭包

        addMore(10)


    当自由变量的值改变的时候,闭包对自由变量的改变也是可以捕获的到

        more = 9999

        addMore(10)


        val someNumbers = List(-11, -10, -5, 0, 5, 10)

        var sum = 0

        someNumbers.foreach(sum += _)

        println(sum)

    5、尾递归

        什么是尾递归呢?如果调用自身方法的动作是函数体的最后一个动作的话,那么这个递归就是一个尾递归

        递归:更函数式、简洁以及没有var,但是函数的调用可能会消耗点时间。while循环是命令式编程,可能会更高效的,因为没有方法的调用。但是如果是尾递归的话,编译器是会优化的,其效率和while循环是一样的

        可以使用注解tailrec来标志是否为尾递归

         @tailrec

         def boom(x: Int): Int =

           if (x == 0) throw new Exception("boom!")

           else boom(x - 1)


        尾递归的限制,以下递归,不会进行尾递归优化,因为jvm的指令集使得尾递归的优化受限

        递归调用的函数不是函数体所在的函数

          def isEven(x: Int): Boolean =

           if (x == 0) true else isOdd(x - 1)

          def isOdd(x: Int): Boolean =

           if (x == 0) false else isEven(x - 1)


三、高阶函数及函数柯里化

  高阶函数(high-order functions)就是用函数作为参数的函数。高阶函数可以减少冗余代码,高阶函数可以使得客户端代码简洁。

    def filesEnding(query: String) =

      for (file <- filesHere; if file.getName.endsWith(query))

       yield file


     def filesContaining(query: String) =

      for (file <- filesHere; if file.getName.contains(query))

       yield file


    改造后:

    private def filesMatching(matcher: String => Boolean) =

      for (file <- filesHere; if matcher(file.getName))

       yield file

    柯里化


  //柯里化函数(curring function)

  def curriedSum(x: Int)(y: Int) = x + y

  curriedSum(1)(2)

  //说明柯里化的过程

  def first(x: Int) = (y: Int) => x + y

  val second = first(1)

  second(2)

  示例:自定义循环控制语句

     var i = 10

     while (i == 0) {

      i -= 1

      println(i)

     }


     until(i == 0) {

      i -= 1

      println(i)

     }


     def until(condition: => Boolean)(block: => Unit) {

      if (!condition) {

       block

       until(condition)(block)

      }

     }


    by name by value


  by name 执行的时候才执行,by value调用就执行

    //by-name parameter

  def byNameAssert(predicate: => Boolean) =

   if (assertionsEnabled && !predicate)

    throw new AssertionError

  byNameAssert(5 > 3)

  //by-value parameter

  def boolAssert(predicate: Boolean) =

   if (assertionsEnabled && !predicate)

    throw new AssertionError

  boolAssert(5 > 3)

另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


网页标题:4、Scala函数式基础-创新互联
链接分享:http://scyanting.com/article/ccpcpp.html