zoukankan      html  css  js  c++  java
  • Scala核心编程_第05章_函数式编程

    函数式编程基础

    • 函数定义/声明
    • 函数运行机制
    • 递归//难点 [最短路径,邮差问题,迷宫问题, 回溯]
    • 过程
    • 惰性函数和异常

    函数式编程高级

    • 值函数(函数字面量)
    • 高阶函数
    • 闭包
    • 应用函数
    • 柯里化函数,抽象控制...

    函数式编程定义

    注释: 我想写函数点

    一.什么是函数式编程?

    函数式编程思想来源于伟大数学家阿隆佐设计的lambda验算,是指用函数来解决与计算相关的几乎所有问题。

    和面向对象编程以对象为模块的思想一样,函数式编程是以函数为核心来组织模块的,这种组织方式更有利于写出模块化的代码。

    二.函数式编程的基本准则

    1.函数是"一等公民"

    所谓一等公民是指,函数与我们平时所使用的其他数据类型地位一样:

    (1)可以赋值给一个变量

    (2)可以作为参数进行传递

    (3)可以作为别的函数的返回值

    (4)函数的创建不用依赖于类或者对象,而是和对象同级别,或者说函数本身就是一种对象。(python 就是这样)

    在学习Scala中将方法、函数、函数式编程和面向对象编程明确一下:

    2.尽量写"纯函数"

    所谓纯函数是指,给定相同输入总能得到相同输出的函数。纯函数需要同时满足下面两个条件:

    (1)函数的结果只依赖于输入的参数且与外部变量和环境无关——只要输入相同,返回值总是不变的。

    (2)除了返回值外,不修改程序的外部状态(比如全局变量、入参)——FP中所有的变量都是final的,这样设计的原因是因为lambda验算只关心计算的结果而不关心每个状态的值。

    总之,纯函数,就是指这样一个函数,对于相同的输入,永远得到相同的输出,它不依赖外部环境,也不会改变外部环境。如果不满足以上几个条件那就是非纯函数。

    scala函数

    scala函数的定义

    基本语法

    def 函数名 ([参数名: 参数类型], ...)[[: 返回值类型] =] {
    语句...
    return 返回值
    }
    1. Scala语法中任何的语法结构都可以嵌套其他语法结构(灵活),即:函数中可以再声明/定义函数,类中可以再声明类 ,方法中可以再声明/定义方法
    2. 函数声明关键字为def (definition)
    3. [参数名: 参数类型], ...:表示函数的输入(就是参数列表), 可以没有。 如果有,多个参数使用逗号间隔
    4. 函数中的语句:表示为了实现某一功能代码块
    5. 函数可以有返回值,也可以没有
      • 返回值形式1: :T= 返回值类型 是T
      • 返回值形式2: 直接 = 表示返回值类型不确定,使用类型推导完成
      • 返回值形式3: Unit表示没有返回值,即使有return也 不生效
      • 如果没有return ,默认以执行到最后一行的结果作为返回值

    函数返回值:

    1. 返回值列表的数据类型可以是值类型和引用类型。
    2. Scala中的函数可以根据函数体最后一行代码自行推断函数返回值类型。那么在这种情况下,return关键字可以省略
    3. 因为Scala可以自行推断,所以在省略return关键字的场合,返回值类型也可以省略
    4. 如果函数明确使用return关键字,那么函数返回就不能使用自行推断了,这时要明确写成 : 返回类型 = ,当然如果你什么都不写,即使有return 返回值为()
    5. 如果函数明确声明无返回值(声明Unit),那么函数体中即使使用return关键字也不会有返回值
    6. 如果明确函数无返回值或不确定返回值类型,那么返回值类型可以省略(或声明为Any)
    7. 递归函数未执行之前是无法推断出来结果类型,在使用时必须有明确的返回值类型

    案例参数:

      def fun1(i: Int,j: Int): Int = {
        return 1
      }
      def fun2(i: Int,j: Int): Int = {
         1
      }
    //自动推导 def fun3(i:Int)={ 1 } def fun4(i:Int):Unit={ return 1 //依旧返回() }

     

    函数传参:

    1. 函数的形参列表可以是多个, 如果函数没有形参,调用时可以不带()
    2. 形参列表的数据类型可以是值类型和引用类型。
    3. 默认传参:Scala函数的形参,在声明参数时,直接赋初始值(默认值),这时调用函数时,如果没有指定实参,则会使用默认值。如果指定了实参,则实参会覆盖默认值。
    4. 如果函数存在多个参数,每一个参数都可以设定默认值,那么这个时候,传递的参数到底是覆盖默认值,还是赋值给没有默认值的参数,就不确定了(默认按照声明顺序[从左到右])。在这种情况下,可以采用带名参数 
    5. 不定长传参:Scala函数支持可变参数的不定长传参,这个 参数 是个集合, 通过 for循环 可以访问到各个值。
    6. 默认传参和不定长传参不可以混用,否则报错;
    7. scala 函数的形参默认是val的,因此不能在函数中进行修改.

    函数的调用

    函数的调用机制

     

    函数的递归调用

     

    过程

    基本介绍

    将函数的返回类型为Unit的函数称之为过程(procedure),如果明确函数没有返回值,那么等号可以省略

    案例说明:

    注意:

    注意区分: 如果函数声明时没有返回值类型,但是有 = 号,可以进行类型推断最后一行代码。这时这个函数实际是有返回值的,该函数并不是过程。(这点在讲解函数细节的时候讲过的.)

    开发工具的自动代码补全功能,虽然会自动加上Unit,但是考虑到Scala语言的简单,灵活,最好不加.

    惰性函数

    惰性计算

    惰性计算(尽可能延迟表达式求值)是许多函数式编程语言的特性。惰性集合在需要时提供其元素,无需预先计算它们,这带来了一些好处。

    1. 可以将耗时的计算推迟到绝对需要的时候。
    2. 可以创造无限个集合,只要它们继续收到请求,就会继续提供元素。

    函数的惰性使用能够得到更高效的代码。Java 并没有为惰性提供原生支持,Scala提供了。

    介绍

    当函数返回值被声明为lazy时,函数的执行将被推迟,直到我们首次对此取值,该函数才会执行。这种函数我们称之为惰性函数,在Java的某些框架代码中称之为懒加载(延迟加载)。

    object HelloScala {
      def main(args: Array[String]): Unit = {
        //惰性加载 这里并没有直接sum()
        lazy val res = sum(10, 20)
        println("-----------------")
        println("res=" + res) //在要使用res 前,才执行 }
    
      }
    
    
      def sum(n1: Int, n2: Int): Int = {
        println("sum() 执行了..")
        return n1 + n2
      }
      
    }
    

    注意:

    lazy 不能修饰 var 类型的变量
    不但是 在调用函数时,加了 lazy ,会导致函数的执行被推迟,我们在声明一个变量时,如果给声明了 lazy ,那么变量值得分配也会推迟。

  • 相关阅读:
    高级映射之事务
    配置tomcat-users.xml文件
    动态SQL之标签
    性能测试
    Service
    添加 aar 或 jar 包依赖 的方式
    安卓设备 以太网代理 问题排查
    剑指offer:面试题15、链表中倒数第 K 个结点
    剑指offer:面试题14、调整数组顺序使奇数位于偶数前面
    剑指offer:面试题13、在O(1)时间删除链表结点
  • 原文地址:https://www.cnblogs.com/wqbin/p/12919544.html
Copyright © 2011-2022 走看看