scala 学习笔记(07) 一等公民的函数

摘要:
在scala中,一切都是一个对象,而一切都是函数。函数与Int、String、Class和其他类型的位置相同。换句话说,使用函数与使用普通类型相同。因此:1.函数可以分配给变量。可以将defhelloWorld(msg:String)作为参数传递:Unit={println(“Hello,”+msg)}deffoo={println(“foo”)}defmain(args:Array[String

在scala中一切皆对象,一切皆函数,函数跟Int,String、Class等其它类型是处于同等的地位,换句话说,使用函数跟使用普通的类型一样,没什么区别,因此:

1、函数可以赋值给变量,可以当参数传递

  def helloWorld(msg: String): Unit = {
    println("Hello," + msg)
  }

  def foo = {
    println("foo")
  }

  def main(args: Array[String]) {
    //函数赋值给变量
    var d = helloWorld _
    d("jimmy") //Hello,jimmy
    //直接定义匿名函数
    d = (msg: String) => println("你好," + msg)
    d("杨俊明") //你好,杨俊明

    //无参函数,作为另一个函数的参数
    var x = (a: Unit, b: String) => {
      a
      println(b)
    }

    x(foo,"ha ha")
    //foo
    //haha
  }

上面这些代码都是合法的

2、函数可以嵌套

既然class里可以定义class,函数是一等公民,理应享受跟class同样的待遇,因此当然也可以嵌套

  def funA(arr: Array[String]) = {
    def funB(a: String) = {
      '[' + a.trim + ']'
    }
    arr.foreach(x => println(funB(x)))
  }

  def main(args: Array[String]) {
    funA(Array("a", " b ", "c ", " f"))
    //  [a]
    //  [b]
    //  [c]
    //  [f]
  }

3、所谓的偏函数

  def add(a: Int, b: Int, c: Int) = {
    a + b + c
  }

  def main(args: Array[String]) {
    val add2 = add(_: Int, _: Int, 0)
    println(add2(1, 2)) //3
  }

利用这个技巧,可以实现带缺省参数,参数个数不同的"重载"版本

4、闭包

  def fun = {
    var i = 10;
    def funTest = {
      println(i)
      i = i + 1
    }
    funTest
    println(i)
  }

  def main(args: Array[String]) {
    fun
  }

funTest访问了funTest定义范围之外的变量 i

5、高阶函数

  def main(args: Array[String]) {

    (1 to(9, 2)).map("*" *).foreach(x => println(" " * ((9 - x.length) / 2) + x))

//        *
//       ***
//      *****
//     *******
//    *********
    
  }

 打印一颗小树冠,代码如此简单? 算法逻辑见下图,这不是重点,重点是上面这行代码是函数叠函数,to是对象1的一个函数,1 to (9,2),即从1到9,每次递增2,最终即为1,3,5,7,9,然后用map函数映射成一行行星号,然后再用foreach函数,结合前置空格输出

// move         len
// 4 * 1
// 3 *** 3
// 2 ***** 5
// 1 ******* 7
// 0********* 9


6、克里化(curring)

  def add_1(a: Int, b: Int, c: Int) = {
    a + b + c
  }

  def add_2(a: Int) = (b: Int, c: Int) => {
    a + b + c
  }

  def add_3(a: Int) = (b: Int) => (c: Int) => {
    a + b + c
  }

  def main(args: Array[String]) {
    println(add_1(1, 2, 3)) //6
    println(add_2(1)(2, 3)) //6
    println(add_3(1)(2)(3)) //6
  }

这个一直没明白真正的用途,号称是可以用来做参数的类型智能推断,但我感觉只是可以把参数拆散,在参数的调用方式上,略有『链式』编程的风格

7、参数隐式转换

  def add(a: Int, b: Int) = a + b

  def foo(a:Int)={
    println(a)
  }

  def boo(a:String)={
    println(a)
  }

  implicit def convert(x: String): Int = {
    x match {
      case "one" => 1
      case "two" => 2
      case "three" => 3
      case _ => 0
    }
  }

  def main(args: Array[String]) {
    println(add("one", "two"))//3
    foo("one")//1
    boo("one")//one
  }

我们并没有定义一个形如add(a:String,b:String)的加法函数,但是最终即成功调用了add("one","two"),秘密在于implicit做了参数的隐式转换,这一个很强大的武器,威力过于巨大,上面的这个转换,会把当前代码作用域的所有String参数,默认都按这个规则转换,foo("one")输出1就是证明,所以没掌握精通前,建议小心使用。

免责声明:文章转载自《scala 学习笔记(07) 一等公民的函数》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇SIM卡中文件PostgreSQL之oracle_fdw安装与使用下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

JAVA中java.util.Date、java.sql.Timestamp和String之间的互相转换

感谢博主分享 https://www.cnblogs.com/zhang-yan/p/7733005.html java.util.Date---->String /** * 将java.util.Date对象转化为String字符串 * @param date * 要格式的java.util.Date对象 * @par...

使用 java 创建你的第一个区块链(第一部分)

本系列教程的目的是帮助您了解如何开发区块链技术。 在本教程中,我们将: 创建你的第一个(非常)基本的“区块链”。 实施简单的工作证明(采矿)系统。 惊叹于可能性。 (我假设您对面向对象编程有基本的了解) 需要注意的是,本教程并没有生产区块链的完整功能。相反,这是一个概念实现的证明,以帮助您理解区块链,为以后的教程打基础。 1,安装 教程中使用 Java,...

ASP.NET Core MVC基础知识

本章将和大家分享ASP.NET Core MVC的一些基础知识,包括Action接收参数、Action向视图传值、常用过滤器的使用、布局页、分部视图、视图组件ViewComponent的使用以及在视图中如何导入公共命名空间等,希望通过本文的分享能够对初学者有所帮助。下面我们直接进入主题。 首先来看一下我们的解决方案: 本Demo的Web项目为ASP.NE...

【Swift】WKWebView与JS的交互使用

一、前言   近日,有朋友问我关于WKWebView与JS的交互问题,可我之前一直使用的是UIWebView,也不曾做过WKWebView的交互啊!接下来大家一块学习下WKWebView是怎么实现原生代码和JS交互的。2016年时候曾写过一篇关于UIWebView与JS的交互。传送门>>> 二、WKWebView 支持更多的HTML5的...

jdk版本比较

JDK各个版本的新特性   对于很多刚接触java语言的初学者来说,要了解一门语言,最好的方式就是要能从基础的版本进行了解,升级的过程,以及升级的新特性,这样才能循序渐进的学好一门语言。今天先为大家介绍一下JDK1.5版本到JDK1.7版本的特性。希望能给予帮助。 JDK1.5新特性:   1.自动装箱与拆箱: 自动装箱的过程:每当需要一种类型的对...

spring aop实现拦截接口请求打印日志

 在spring配置  1编写自己的注解类 2.编写注解解析类 3.配置spring aop代理 (下面我使用注解 如使用配置 配置切点即可,有两种代理默认jdk代理 设置true 为cglib代理) //注解类 1 /** 2 * 自定义注解 拦截器 3 * @author 4 * 给需要监控的方法加上改注解,就可以实现该方法的日志记录 5...