第5章 函数式编程

news2024/11/24 0:08:01

第5章 函数式编程

5.1 函数式编程思想

  1. 在之前的学习中,我们一直学习的就是面向对象编程,所以解决问题都是按照面向对象的方式来处理的。比如用户登陆,但是接下来,我们会学习函数式编程,采用函数式编程的思路来解决问题。scala编程语言将函数式编程和面向对象编程完美地融合在一起了。
  • 面向对象编程

分解对象,行为,属性,然后通过对象的关系以及行为的调用来解决问题

  • 函数式编程

    将问题分解成一个一个的步骤,将每个步骤进行封装(函数),通过调用这些封装好的步骤,解决问题。

5.2 函数基础

  1. 基本语法

    image

  2. 函数与方法的区别

    image

    package chapter05
    
    object Test01_FunctionAndMethod {
      // main方法,方法和函数差不多,可以统称为函数
      // 函数定义在任何地方,方法定义在类内
      def main(args: Array[String]): Unit = {
        // 1. 定义函数
        def sayHi(name: String): Unit = {
          println("hi, " + name)
        }
    
        // 调用函数
        sayHi("scc")
        // 2. 调用对象的方法
        Test01_FunctionAndMethod.sayHi("scc")
    
        val result = Test01_FunctionAndMethod.sayHello("Alice")
        println(result)
      }
    
      // 2. 定义对象的方法
      def sayHi(name: String): Unit = {
        println("Hi, " + name)
      }
    
      def sayHello(name: String): String = {
        println("Hi, " + name)
        "Hello"
      }
    
    }
    
    
  3. 函数的定义,六种情况

    package chapter05
    
    object Test01_FunctionDefine {
      def main(args: Array[String]): Unit = {
    
        // 定义函数
        def f1(): Unit = {
          println("1. 无参,无返回值")
        }
    
        println(f1())
    
        def f2(): Int = {
          println("2. 无参,有返回值")
          2
        }
    
        println(f2())
    
    
        def f3(name: String): Unit = {
          println("3. 有参,无返回值" + name)
        }
    
        println(f3("scc"))
    
        def f4(name: String): Int = {
          println("4. 有参,有返回值")
          2
        }
    
        println(f4("scc"))
    
        def f5(name1: String, name2: String): Int = {
          println("5. 多参,有返回值" + name1 + name2)
          2
        }
    
        //    f5("scc", "zyy")
        println(f5("scc", "zyy"))
    
        def f6(name1: String, name2: String): Unit = {
          println("6. 多参,无返回值" + name1 + name2)
        }
    
        println(f6("scc", "zyy"))
      }
    }
    
    
  4. 函数参数,4种用法

    package chapter05
    
    //函数参数特殊用法,四种
    object Test03_FunctionParameter {
      def main(args: Array[String]): Unit = {
        // 1. 可变参数
        def f1(str: String*): Unit = {
          println(str)
        }
    
        f1("scc")
        f1("scc", "zyy", "520")
    
    
        // 2. 多个参数,可变参数在后
        def f2(str1: String, str2: String*): Unit = {
          println("str1: " + str1 + " str2: " + str2)
        }
    
        f2("scc")
        f2("scc", "zyy", "520")
    
    
        // 3. 参数默认值,放在最后
        def f3(name: String = "atNanJing"): Unit = {
          println("name: " + name)
        }
    
        f3()
    
        // 4. 带名参数
        def f4(name: String = "zyy", age: Int): Unit = {
          println(s"name: ${name} age is ${age}")
        }
    
        f4(name = "scc", age = 21)
        f4(age = 21)
      }
    }
    
    
  5. 函数至简原则

    所谓的至简原则,其实就是Scala的编译器为了提高开发效率。帮助我们将函数声明中能简化的地方全部都进行了简化。也就是说将函数声明中那些能省的地方全部都省掉。所以简单来说就是:能省则省

    package chapter05
    
    object Test04_Simplify {
      def main(args: Array[String]): Unit = {
        // 定义函数
        def f0(name: String): String = {
          return name
        }
    
        println(f0("scc"))
    
    
        // 1. 省略return
        def f1(name: String): String = {
          name
        }
    
        println(f1("scc"))
    
    
        // 2. 如果函数体只有一行代码,则省略花括号
        def f2(name: String): String = name
    
        println(f2("scc"))
    
        // 3. 函数返回值如果能推断出来,则省略返回值类型,相当于数学函数f3(x)=x
        def f3(name: String) = name
    
        // 4. 如果定义了return,则不能省略返回值类型
        def f4(name: String): String = {
          return name
        }
    
        // 5. 如果函数声明为Unit,那么即使函数体使用return关键字,也不起作用
        def f5(name: String): Unit = {
          return name
        }
    
        // 6. 如果Scala期望无返回值类型,则等号可以省略,叫做过程
        def f6(name: String) {
          println(name)
        }
    
        // 7. 如果函数没有参数,但是声明的时候加上了小括号,那么调用的时候,小括号可加可不加
        def f7() {
          println("7. 如果函数没有参数,但是声明的时候加上了小括号,那么调用的时候,小括号可加可不加")
        }
    
        f7()
        f7
    
        // 8. 如果函数没有参数,那么声明的时候可以省略小括号,在调用的时候,小括号不能加
        def f8 {
          println("8. 如果函数没有参数,那么声明的时候可以省略小括号,在调用的时候,小括号不能加")
        }
    
        f8
    
        // 9. 如果不关系函数名称,只关心逻辑处理,则可以省略def和函数名称,此时为匿名函数或者lambda表达式,区别为=>
        (name: String) => {
          println(name)
        }
      }
    
    }
    
    

5.3 高阶函数-匿名函数

  1. 匿名函数lambda及简化原则

    package chapter05
    
    object Test05_Lambda {
      def main(args: Array[String]): Unit = {
        // 1. 函数类型,String => Unit
        val fun: String => Unit = (name: String) => {
          println(name)
        }
    
        fun("atguigu")
    
        println("===================================")
    
        // 2. 定义一个函数,以匿名函数作为参数传入
        def f(func: String => Unit): Unit = {
          func("匿名函数")
        }
    
        f(fun)
    
        // 3. 匿名函数作为参数传入,类似于传入数据处理逻辑op,处理已经准备好的数据
        f((name: String) => {
          println(name)
        })
    
    
        // 4. 匿名函数至简原则,匿名函数,参数类型可以省略,会根据形参自动推断
        f((name) => {
          println(name)
        })
    
    
        // 5. 匿名函数至简原则,匿名函数,只有一个参数,省略括号
        f(name => {
          println(name)
        })
    
        //6. 匿名函数至简原则, 匿名函数,函数体只有一行,大括号可以省略
        f(name => println(name))
    
    
        // 6. 匿名函数至简原则,匿名函数,如果参数只出现一次,则参数和lambda表达式箭头=>可以省略,并且后面参数用_代替
        f(println(_))
    
        // 7. 如果能够判断println是一个函数体,而不是调用语句,则省略下划线
        f(println)
    
    
        // 实际示例,定义一个“二元运算”函数,只操作1和2两个数,但是具体运算通过参数传入
        def dualFunctionOneAndTwo(func: (Int, Int) => Int): Int = {
          func(1, 2)
        }
    
        dualFunctionOneAndTwo((num1, num2) => {
          num1 + num2
        })
    
        dualFunctionOneAndTwo(_ * _)
    
      }
    
    }
    
    
  2. 函数高阶操作

    • 函数作为值进行传递,注意下划线_,此时为function对象
    • 函数作为参数进行传递
    • 函数作为函数返回值进行返回
    package chapter05
    
    // 函数作为值进行传递
    object Test06_HighOrderFunction {
      def main(args: Array[String]): Unit = {
        def f(n: Int): Int = {
          println("f调用")
          n + 1
        }
    
        def fun(): Int = {
          println("fun调用")
          1
        }
    
        val result: Int = f(123)
        println(result)
    
        //1. 函数作为值进行传递,注意下划线_,此时为function对象
        val f1: Int => Int = f
        val f2 = f _
    
        println(f1)
        println(f1(1))
        println(f2)
        println(f2(1))
    
        // 函数赋值
        val f3: () => Int = fun
        val f4: () => Int = fun _
    
        println(f3)
        println(f4)
    
    
        // 2. 函数作为参数进行传递
        // 定义二元运算参数
        def dualEval(op: (Int, Int) => Int, a: Int, b: Int): Int = {
          op(a, b)
        }
    
        println(dualEval((a, b) => {
          a + b
        }, a = 1, b = 2))
        println(dualEval((a, b) => {
          a - b
        }, a = 1, b = 2))
    
        // 3. 函数作为函数返回值进行返回
        def f5() = {
          def f6(a: Int) = {
            println("f6调用" + a)
          }
    
          f6 _ //将函数直接返回,而不是函数调用
        }
    
        val f7 = f5()
        println(f7)
        println(f7(10))
        // 函数科里化吧?
        println(f5()(10))
      }
    }
    
  3. 函数高阶操作实践

    package chapter05
    
    object Test07_Practice_CollectionOperation {
      def main(args: Array[String]): Unit = {
        // 对数组进行处理,将操作抽象出来,处理完毕之后的结果返回一个新的数组
        val arr = Array(1, 2, 3, 4, 5)
    
        // 对数组进行处理,将操作抽象出来,处理完毕之后的结果返回一个新的数组
        def arrayOperation(array: Array[Int], op: Int => Int): Array[Int] = {
          array.map(op)
        }
    
        // 定义一个加一操作
        val fun = (num: Int) => {
          num + 1
        }
    
        def addOne(num: Int): Int = {
          num + 1
        }
    
        arrayOperation(arr, fun).foreach(println)
        arrayOperation(arr, addOne).foreach(println)
      }
    
    }
    
    
  4. 函数柯里化和闭包

    image

    image

    闭包推荐使用柯里化写法

    image

  5. 递归 pass

  6. 控制抽象

    1. 传值参数

      image

    2. 传名参数,传入的是代码块

      注意a:=>Int 表示传入代码块,返回值为Int

      image

      直接传入代码块

      image

  7. 惰性加载 lazy

    函数​前面加了lazy关键字,和控制抽象差不多,可能节约资源吧

    image

    例子:

    image

    当调用两次时,result值被计算出来,因此不需要再次调用,此处和控制抽象中传名参数不一样

    image​​​

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/668747.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python 随练】阶乘累加计算

题目: 求 12!3!…20!的和。 简介: 在本篇博客中,我们将解决一个数学问题:计算阶乘序列的和。我们将介绍阶乘的概念,并提供一个完整的代码示例来计算给定范围内阶乘数的和。 问题分析: 我们需要计算从1…

基于“遥感+”融合技术在碳储量、碳收支、碳循环等多领域监测与模拟

卫星遥感具有客观、连续、稳定、大范围、重复观测的优点,已成为监测全球碳盘查不可或缺的技术手段,卫星遥感也正在成为新一代 、国际认可的全球碳核查方法。本内容目的就是梳理碳中和与碳达峰对卫星遥感的现实需求,系统总结遥感技术在生态系统…

开源开放 | 开源知识图谱抽取工具发布大模型版DeepKE-LLM

DeepKE-LLM链接: https://github.com/zjunlp/DeepKE/tree/main/example/llm OpenKG地址: http://openkg.cn/tool/deepke Gitee地址: https://gitee.com/openkg/deepke/tree/main/example/llm 开放许可协议:Apache-2.0 license 贡献…

计算机网络核心

1、OSI开放式互联参考模型 1、物理层:机械、电子、定时接口通信信道上的原始比特流传输。2、数据链路层:物理寻址,同时将原始比特流转变为逻辑传输线路。3、网络层:控制子网的运行,如逻辑编址、分组传输、路由选择(IP…

chatgpt赋能python:Python捕获Ctrl+C信号

Python 捕获 CtrlC 信号 在 Python 中,我们通过按下键盘上的 CtrlC 快捷键可以中断程序的运行,但是在某些情况下,我们希望程序在收到 CtrlC 信号后进行一些特殊的处理,而非直接退出或崩溃。这就需要捕获 CtrlC 信号,并…

前端Vue自定义简单实用中国省市区三级联动选择器

前端Vue自定义简单实用中国省市区三级联动选择器&#xff0c; 请访问uni-app插件市场地址&#xff1a;https://ext.dcloud.net.cn/plugin?id13118 效果图如下&#xff1a; #### 使用方法 使用方法 <!-- themeColor:主题颜色 ref:设置唯一ref pickerValueDefault:默认选择…

C++技能系列 ( 6 ) - 可调用对象、std::function与std::bind【详解】

系列文章目录 C技能系列 Linux通信架构系列 C高性能优化编程系列 深入理解软件架构设计系列 高级C并发线程编程 期待你的关注哦&#xff01;&#xff01;&#xff01; 现在的一切都是为将来的梦想编织翅膀&#xff0c;让梦想在现实中展翅高飞。 Now everything is for the…

单片机如何生成周期正弦波

一&#xff0c;简介 在某些场景需要使用单片机的IIS等外设播放正弦波音频数据。本文介绍一种“笨方法”来生成固定频率和固定幅度的正弦波定点型数据&#xff0c;记录总结学习使用。 二&#xff0c;步骤简介 总体步骤概述&#xff1a; 1&#xff0c;使用Audition生成制定波形…

chatgpt赋能python:Python异常捕获存在的问题

Python 异常捕获存在的问题 作为一门广受欢迎、应用广泛的编程语言&#xff0c;Python 在处理异常方面有着比较完善的设计。Python 提供了 try…except…finally 这样的异常处理机制&#xff0c;通过这些机制&#xff0c;开发者可以捕获、处理程序中产生的异常&#xff0c;从而…

【安全】awvs安装(一)

目录 一、简介 二、将安装文件传输到服务器 三、安装 3.1 赋权 3.2 执行安装 四、激活 4.1 复制激活文件到对应安装目录 4.2 赋权 4.3 运行激活文件 五、访问 六、设置不自动更新 七、设置开启 八、忘记密码 前言&#xff1a;安全漏洞扫描工具awvs的安装使用 一、简介…

Android DiskLruCache完全解析,硬盘缓存的最佳方案

概述 LruCache只是管理了内存中图片的存储与释放&#xff0c;如果图片从内存中被移除的话&#xff0c;那么又需要从网络上重新加载一次图片&#xff0c;这显然非常耗时。对此&#xff0c;Google又提供了一套硬盘缓存的解决方案&#xff1a;DiskLruCache(非Google官方编写&…

Nginx基础配置

Nginx的基础配置&#xff1a; Nginx的基础配置 一、实战案例&#xff1a;1.Nginx访问统计&#xff1a;2.基于授权的访问控制&#xff1a;3.基于客户端访问设置&#xff08;设置黑白名单&#xff09;&#xff1a;4.基于域名的nginx虚拟主机&#xff1a;5.基于IP的nginx虚拟主机…

算法分析02--分治法

3.分治法 3.1递归 递归是指子程序&#xff08;或函数&#xff09;直接调用自己或通过一系列调用语句间接调用自己&#xff0c; 是一种描述问题和解决问题的常用方法。使用递归技术往往使函数的定义和算法的描述简洁且易千理解。 递归有两个基本要素&#xff1a;边界条件&…

告别固定字体大小:CSS使用相对单位提升网页可访问性和兼容性

在 Web 开发领域中&#xff0c;有很多误解流传&#xff0c;即使它们被反驳了很多次也仍然存在。"外部链接应该总是在新标签页中打开" 就是一个很好的例子。CSS Tricks 在将近十年前就对此进行了详细的解释&#xff08;简而言之&#xff1a;大多数情况下是错误的&…

沃尔玛、亚马逊跨境境电商如何实现自养账号采退、海淘及测评的

今天曹哥还是针对下亚马逊、沃尔玛跨境平台如何实现自己养买家号可以给自己采购、海淘及测评等技术问题 首先你要有一个稳定的环境方案&#xff0c;这个是做自养号采购、海淘及测评的基础。环境有很多&#xff0c;从早期的虚拟机&#xff0c;模拟机&#xff0c;云手机&#xf…

MATLAB | 绘图复刻(十) | 旋转45度的相关系数热图绘制

我们在论文里经常能见到这样三角形的相关性热图&#xff0c;这样的热图绘制出来会更节省空间&#xff1a; 这期就教大家如何绘制三角形的热图&#xff0c;绘制效果如下&#xff1a; 以下是教程部分&#xff1a; 0 数据准备 这里随便生成了一组数据&#xff0c;计算了相关系数&…

C++——vector迭代器失效与深浅拷贝问题

目录 1. vector迭代器失效问题 1.1 insert迭代器失效 1.1.1 扩容导致野指针 1.1.2 意义变了 1.1.3 官方库windows下VS和Linux下对insert迭代器失效的处理 1.2 erase迭代器失效 1.2.1 失效原因分析 1.2.2 官方库windows下VS和Linux下对erase迭代器失效的处理 1.2.3 测试…

0基础学习VR全景平台篇第46篇:底部菜单- 【开场地图】与【高清矩阵】的对比

大家好&#xff0c;欢迎观看蛙色VR官方——后台使用系列课程&#xff01; 这期 &#xff0c;我们将为大家讲解蛙色VR平台-【开场地图】与【高清矩阵】功能的区别 功能位置示意 一、功能具体应用 开场地图分为两种&#xff0c;分别是高德地图和手绘地图。 高德地图点位目前系统…

【Linux】MySQL 存储引擎

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 MySQL 存储引擎 MyISAM 表支持 3 种不同的存储格式常用存储引擎&#xff1a;InnoDB、MyISAM查看系统支持的存储引擎查看表使用的存储引擎修改存储引擎死锁如何尽可能避免死锁…

每日学术速递6.7

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.CV 1.The ObjectFolder Benchmark: Multisensory Learning with Neural and Real Objects(CVPR 2023) 标题&#xff1a;ObjectFolder 基准测试&#xff1a;使用神经和真实对象进行多感官…