Scala之函数式编程

这篇具有很好参考价值的文章主要介绍了Scala之函数式编程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Scala之函数式编程

目录

函数和方法的区别:

 参数默认值:

 函数至简原则---能省则省:

至简原则细节

匿名函数的化简:

匿名函数至简原则:

高阶函数:

高阶函数的三种用法:

(1)函数可以作为值进行传递

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

匿名化简:

柯里化写法:

闭包:

递归:

优化递归:尾递归优化

控制抽象:

值调用:

名调用:

懒加载:

函数和方法的区别:


方法和函数的区别就是在位置上的不同

方法--是在类中表示(面向对象)-----伴生对象中的方法(相当于静态方法)  或者在伴生类中定义方法

写在其他位置的都是函数

函数是支持嵌套的但是并不支持函数的重载和重写(重载和重写是针对的类中的方法而言)

Scala中也有可变参数,不过与Java不同  

def main(args: Array[String]): Unit = {
    def sayhi(name: String*): Unit={
      println(s"hi $name")
    }
    sayhi()
    sayhi("shdus")
    sayhi("sdsdsd","shdushd")
  }

执行结果Scala之函数式编程

 参数默认值:

(Java中不存在默认值   可通过重载实现)

  def main(args: Array[String]): Unit = {
    def sayhi(name: String="zhangsan"): Unit={
      println(s"hi $name")
    }
    sayhi()
    sayhi("shdus")
    //sayhi("sdsdsd","shdushd")
  }

执行结果:

Scala之函数式编程

 当想使用默认参数时,且有多个参数时  需要使用带名参数

 def main(args: Array[String]): Unit = {
    def sayhi(name: String="zhangsan",age :Int): Unit={
      println(s"hi $name age is $age")
    }
    sayhi(age = 18)
    sayhi("shdus",18)
    //sayhi("sdsdsd","shdushd")
  }

执行结果:

Scala之函数式编程

 函数至简原则---能省则省:

至简原则细节

1 return 可以省略, Scala 会使用函数体的最后一行代码作为返回值

                 特殊情况  return 不能省略:

    //
    def sayhi2(name :String) :String ={
      if(name==null)
        {
          return ""
        }
      println(s"Hi $name")
       name
    }

比如 传入参数为null  这个return 就不能省略  这里要作为程序的一个出口

如果省略 则会执行下边的语句   返回name

2 )如果函数体只有一行代码,可以省略花括号
                 如果不是一行代码而且省略了
3 )返回值类型如果能够推断出来,那么可以省略(和返回值类型一起省略)
                        //函数式编程最终省略的结果是 只保留传入的是什么  传出的是什么

4)如果有 return,则不能省略返回值类型,必须指定

因为每一行代码都是一个代码块   如果不写返回类型 就会返回默认最后一行代码 这时return name的返回值类型为nothing类型

  def sayhi5(name :String):String={
      println(s"hi $name")
      return name
    }
                        
5 如果函数明确声明 unit,那么即使函数体中使用 return 关键字也不起作用
(6)Scala 如果期望是无返回值类型,可以省略等号
(7)如果函数无参,但是声明了参数列表,那么调用时,小括号,可加可不加
(8)如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略
9 )如果不关心名称,只关心逻辑处理,那么函数名( def )可以省略----匿名函数
=>前后分别是传入参数和返回值  =之前的是传入参数与返回值类型 = 之后 是传入的变量名 与实现逻辑)
(匿名函数中没有结果类型)
    val function: (String, Int) => String = (name: String, age: Int) => name + "的年龄是" + age

匿名函数的化简:

匿名函数至简原则:

(1)参数的类型可以省略,会根据形参进行自动的推导
可根据后边推到前面    也可根据前面推到后边  一般都是化简后边的
    val function1 = (name: String, age: Int) => name + "的年龄是" + age
    //后推前
    val function2: (String, Int) => String = (name,age) => name + "的年龄是" + age
//前面推后边
(2)类型省略之后,发现只有一个参数,则圆括号可以省略;其他情况:没有参数和参
数超过 1 的永远不能省略圆括号。
(3)匿名函数如果只有一行,则大括号也可以省略
多行不可以省略

val function3: (String, Int) => String = (name: String, age: Int) =>
  {
    println(name + "的年龄是" + age+"666")
    name + "的年龄是" + age
  }
(4)如果(所有)参数(都)只出现一次,则参数省略且后面参数可以用_代替(但是只剩下_是避不可以的)(并且是在已经经历了其他的函数化简的前提下才可替代,无法在不进行其他化简的前提下替代)
    val function5 :(Int,Int)=>Int     //输入类型  输出类型
    = {
        2*_+4*_
      }

高阶函数:

高阶函数的三种用法:

(1)函数可以作为值进行传递

是将这个函数当作值进行传递   

val function: String => String = sayHi _
    function("tangxiaocong")

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

先构造一个抽象函数   再调用的时候 当作参数传递真正的逻辑

高阶函数接受一个或多个函数作为参数,并/或返回一个函数作为结果。

 def operaXY(x:Int,y:Int,func:(Int,Int)=>Int):Int={
      func(x,y)
    }
    def sumXY(x:Int,y:Int): Int =x+y

    val i: Int = operaXY(10, 20, sumXY)
        println(i);    

(3)柯里化函数:

详见下文 

不化简的匿名:

    def operaXY(x:Int,y:Int,func:(Int,Int)=>Int):Int={
      func(x,y)
    }
    val i: Int = operaXY(10, 20, (x:Int,y:Int)=>x-y)
        println(i);

匿名化简:

    (1)化简类型

    (2)化简xy使用_代替

def operaXY(x:Int,y:Int,func:(Int,Int)=>Int):Int={
      func(x,y)
    }
    val i: Int = operaXY(10, 20, _-_)
        println(i);

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

涉及到函数的一个嵌套,一级调用返回的是一个函数  二级调用返回值

 def sumxy1(x:Int)={
      def sumy(y:Int): Int =
      {
        x+y
      }
      sumy _
    }

    val function1: Int => Int = sumxy1(10)
    println("歇一会")
    val i1: Int = function1(20)
    println(i1)

使用匿名函数进行化简

将等号后边的匿名函数作为返回值进行返回
 def sumxy2(x: Int): Int => Int = (y: Int) => x + y // 将等号后边的匿名函数作为返回值进行返回
    val intToInt: Int => Int = sumxy2(58)
    val i3: Int = intToInt(23)
    println(i3)

再次对匿名函数进行化简:
这种化简就是过度化简,难懂,不建议

 def sumxy3(x: Int): Int => Int = x + _ 

柯里化写法:

为了防止过度化简,作者引入了一个数学概念---柯里化的写法:
把多个形参的参数列表打散成一个形参的多个参数列表

 def KlH(c:Char)(s:String)(i:Int)={
      c !='0' || s != "" || i !=0
    }
    println(KlH('0')("")(0))

闭包:

闭包:函数式编程的标配

闭包 :如果一个函数,访问到了它的外部(局部)变量的值,那么这个函数和他所处的
环境,称为闭包(防止嵌套造成栈溢出)
闭包让代码更加灵活
(闭包其实就是把外层的变量打包成常量让内层函数使用)
 def sumx(x:Int)={
      def sumy(y:Int):Int={
        x+y
      }
      sumy _
    }

上述采用的相当于是柯里化写法--先进行第一层调用  传入x再传递给内层函数  让x从变量变成常量,防止多次嵌套造成栈溢出

    val function: Int => Int = sumx(23)
    val i: Int = function(34)
    println(i)

递归:

递归:嵌套调用自身的函数
递归其实是不如循环快的,因为递归还是会造成压栈
  def jc(n: Int):Long ={
//递归:嵌套调用自身的函数
      if(n==1)
          1
      else
        jc(n-1)*n
    }
    println(jc(5))

优化递归:尾递归优化

尾递归:最后递归调用函数的一行 只有自身的函数  没有其他值

实际尾递归是用到了闭包  递归没办法用闭包(闭包   把上一层的变量在本层变成常量,减少压栈次数----引入了res变量)(其实相当于定义一个变量当作累加器,来替代压栈)

    def jc1(n: Int,res:Long=1):Long ={
      //递归:嵌套调用自身的函数
      if(n==1)
        res
      else
        jc1(n-1,res*n)
    }

判断是否是尾递归,可以使用一个注解----@tailrec(不是尾递归会报错)

控制抽象:

函数定义有值调用和名调用(两种方式的传参方式不同)

值调用:

--将代码块的结果作为参数传入函数中,使用参数时,只带入结果

(值调用是指函数在调用时,先计算参数的值,然后再将这个值传递给函数。这意味着每个参数都只计算一次

名调用:

--直接将整个代码块传入参数中,使用一次参数就会运行一次

(名调用是指函数在调用时,将参数的表达式作为代码块传递给函数。这意味着每次函数使用参数时都会重新计算它的值。)

  //值调用
    def sayHi1(name:String):Unit={
      println("函数调用")
      println(s"$name  hi")
      println(s"$name  hi")
    }
    sayHi1({
      println("hello")
      "linhai"
    })
    println("==================================================")
    //名调用
     def sayHi2(name: => String):Unit={
    println("函数调用")
      println(s"$name  hi")
      println(s"$name  hi")
    }
sayHi2({
  println("hello")
  "linhai"
})

运行结果的对比:
Scala之函数式编程

懒加载:

其实懒加载相当于Linux中的sleep函数   会暂时性休息,当使用到惰性语句的时候才会运行

关键字---lazy   而且lazy只能用于val关键字上

def sumxy(x:Int,y:Int):Int={
  println("sumxy调用")
  x+y
}
    lazy val sum=sumxy(10,20)
    println("啦啊啦啦啦")
    println(sum)

运行结果:

Scala之函数式编程

自定义while循环:

def mywhile(b:Boolean)(op : => Unit):Unit={
  if (b)
    {
      op
      mywhile(b)(op)
    }

}
var i=0
  mywhile(i<5)(
    {
      println(i)
      i +=1
    }
  )

上述代码会陷入死循环   因为传入b(i<5)的时候是值调用  只传参一次  一直为真则一直++

改进   对b进行名调用  

Scala之函数式编程文章来源地址https://www.toymoban.com/news/detail-409041.html

到了这里,关于Scala之函数式编程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Scala编程基础:表达式、函数、模式匹配与集合操作

    本文详细介绍了Scala编程的基础知识,包括表达式的使用,方法与函数的区别,模式匹配的各种模式,以及Scala Trait(特质)的定义和使用。

    2024年04月14日
    浏览(51)
  • 2023_Spark_实验七:Scala函数式编程部分演示

    1、Scala中的函数 在Scala中,函数是“头等公民”,就和数字一样。可以在变量中存放函数,即:将函数作为变量的值(值函数)。 2、匿名函数 3、带函数参数的函数,即:高阶函数 示例1: (*)首先,定义一个最普通的函数 (*)再定义一个高阶函数 (*)分析这个高阶函数

    2024年02月08日
    浏览(61)
  • 2023_Spark_实验九:Scala函数式编程部分演示

    需求: 1、做某个文件的词频统计//某个单词在这个文件出现次数 步骤: 1、文件单词规律(空格分开) 2、单词切分 3、单词的统计 (k,v)-(k:单词,V:数量) 4、打印 框架: 1、单例对象,main() 2、创建CONF 3、创建SC--读取文件的方式--》RDD 4、RDD进行处理 5、关闭资源 一、新

    2024年02月08日
    浏览(48)
  • Scala的函数式编程与高阶函数,匿名函数,偏函数,函数的闭包、柯里化,抽象控制,懒加载等

    函数式编程 解决问题时,将问题分解成一个一个的步骤,将每个步骤进行封装(函数),通过调用这些封装好的步骤,解决问题。 例如:请求-用户名、密码-连接 JDBC-读取数据库 Scala 语言是一个完全函数式编程语言。万物皆函数。 函数的本质:函数可以当做一个值进行传递

    2024年02月09日
    浏览(54)
  • Scala方法和函数

    方法和函数的作用几乎是一样的,但是函数在使用的过程中更加灵活和多样化 scala中函数是头等公民 . 可以作为方法的返回值和参数使用 scala是一个集面向对象和面向函数于一身的编程语言 , 灵活的函数是函数式编程的一种体现 函数的使用使代码更加简洁和灵活 scala中一种函

    2024年02月09日
    浏览(33)
  • 【C++】泛型编程 ② ( 函数模板与普通函数区别 )

    函数模板与普通函数区别 : 主要区别在于它们能够处理的 数据类型数量 和 灵活性 ; 自动类型转换 : 函数模板 不允许 自动类型转化 , 会进行严格的类型匹配 ; 普通函数 能够进行 自动类型转换 , 内含隐式的类型转化 ; 参数 / 返回值 数据类型 : 普通函数 只接受 特定类型 参数

    2024年02月20日
    浏览(37)
  • Golang函数以及函数和方法的区别

    在接触到go之前,我认为函数和方法只是同一个东西的两个名字而已(在我熟悉的c/c++,python,java中没有明显的区别),但是在golang中者完全是两个不同的东西。官方的解释是, 方法是包含了接收者的函数 。到底什么意思呢。 首先函数的格式是固定的,func+函数名+ 参数

    2024年02月13日
    浏览(44)
  • 【Linux操作系统】Linux系统编程实现递归遍历目录,详细讲解opendir、readdir、closedir、snprintf、strcmp等函数的使用

    在Linux系统编程中,经常需要对目录进行遍历操作,以获取目录中的所有文件和子目录。递归遍历目录是一种常见的方法,可以通过使用C语言来实现。本篇博客将详细介绍如何使用C语言实现递归遍历目录的过程,并提供相应的代码示例,同时解释相关函数的使用。 1.1.1 函数

    2024年02月12日
    浏览(38)
  • 函数与方法有区别?

    有区别,当然是有区别。 不管是java、rust还是go,他们都是不一样的。 先看定义: 函数(Function) 是一段独立的代码块,用于执行特定的任务。函数可以被多次调用,并且可以接受参数和返回结果。在Go中,函数是独立于任何结构体或类型的。 方法(Method) 是与特定类型相

    2024年02月13日
    浏览(31)
  • Python方法与函数的区别

    函数:function,功能,代码包 方法:method,类函数 class function,generic function 泛函数,对象与生俱来的函数 另看到一篇文章的标题是《Excel200多个宏代码集,比函数强多了!有效提高工作效率!》,这里的函数是内置函数,经历了应用的洗礼和算法的优化的常用功能的代码包

    2023年04月08日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包