package com.dtspark.scala.basics

 /**
  * 函数式编程进阶:
  * 1,函数和变量一样作为Scala语言的一等公民,函数可以直接赋值给变量;
  * 2, 函数更长用的方式是匿名函数,定义的时候只需要说明输入参数的类型和函数体即可,不需要名称,但是如果你要使用的话,一般会把这个匿名函数赋值给一个变量(其实是val常量),Spark源码中大量存在这种语法,必须掌握;
  * 3, 函数可以作为参数直接传递给函数,这极大的简化的编程的语法,为什么这样说呢?原因非常简单:
  *      第一:以前Java的方式是new出一个接口实例,并且在接口实例的回调方法callback中来实现业务逻辑,现在是直接把回调方法callback传递给我的函数,且在函数体中直接使用,这毫无疑问的简化的代码的编写,提升了开发效率;
  *      第二:这种方式非常方便编写复杂的业务逻辑和控制逻辑,对于图计算、机器学习、深度学习等而言至关重要; *
  *      函数作为函数的参数传递的编程方式是称之为高阶函数的编程方式,Spark源码和应用程序开发中至少60%都是这种代码,必须务必一定要掌握。
  * 4, 函数式编程一个非常强大的地方之一在于函数的返回值可以是函数,当函数的返回类型是函数的时候,这个时候就表明Scala的函数实现了闭包!
  *      Scala闭包的内幕是:Scala的函数背后是类和对象,所以,Scala的参数都作为了对象的成员!!!!!!,所以后续可以继续访问,这就是Scala实现闭包的原理内幕! *
  * 5, Currying, 复杂的函数式编程中经常使用,可以维护变量在内存中的状态,且实现返回函数的链式功能,可以实现非常复杂的算法和逻辑;
  */
 object functionalProgramming {
   def main(args: Array[String]): Unit = {
     /**
      * 1,函数和变量一样作为Scala语言的一等公民,函数可以直接赋值给变量;
      */
     val hiData = hiBigData _
     hiData("Spark")

     /**
      * 2, 函数更长用的方式是匿名函数,定义的时候只需要说明输入参数的类型和函数体即可,不需要名称,但是如果你要使用的话,一般会把这个
      *      匿名函数赋值给一个变量(其实是val常量),Spark源码中大量存在这种语法,必须掌握;
      */
     val f = (name: String) => println("Hi, " + name)
     f("Kafka")

     /**
      * * 3, 函数可以作为参数直接传递给函数,这极大的简化的编程的语法,为什么这样说呢?原因非常简单:
          *      第一:以前Java的方式是new出一个接口实例,并且在接口实例的回调方法callback中来实现业务逻辑,现在是直接把回调方法callback传递给我的函数,且在函数体中直接使用,这毫无疑问的简化的代码的编写,提升了开发效率;
          *      第二:这种方式非常方便编写负责的业务逻辑和控制逻辑,对于图计算、机器学习、深度学习等而言至关重要;
          *      函数作为函数的参数传递的编程方式是称之为高阶函数的编程方式,Spark源码和应用程序开发中至少60%都是这种代码,必须务必一定要掌握。
      */
     def getName(func: (String) => Unit, name: String){
       func(name)
     }
     getName(f,"Scala")
    Array(1 to 10: _*).map { (item: Int) => 2 * item }.foreach { x => println(x) }

    /**
     *  4, 函数式编程一个非常强大的地方之一在于函数的返回值可以是函数,当函数的返回类型是函数的时候,这个时候就表明Scala的函数实现了闭包!
     *       Scala闭包的内幕是:Scala的函数背后是类和对象,所以,Scala的参数都作为了对象的成员!!!!!!,所以后续可以继续访问,这就是Scala
     *       实现闭包的原理内幕!
     */
    def funcResult(message: String) = (name: String) => println(message + " : " + name)
    //def funcResult(message: String, name: String){println(message + " : " + name)}

    funcResult("Hello")("Java")  //Currying函数写法, 必须掌握这种写法,只要是复杂的Scala函数式编程代码就一定会使用这种写法
    val result = funcResult("Hello")
    result("Java")
   }

   def hiBigData(name: String){
     println("Hi, " + name)
   }

 }

2.补充知识

a.代码中第一点有一句 
val hiData = hiBigData _ 这里_将hiBigData 转成了函数 
在Scala中,无法直接操纵方法,只能直接操纵函数,所以需要使用_。 
b.代码中第二和第三点 
val f = (name: String) => println(“Hi, ” + name) 调用时直接f(“Kafka”)容易理解。 
但是 getName(f,”Scala”) 调用时这里f 是没参数的! 
def getName(func: (String) => Unit, name: String){ 
func(name) 

这里getName第一个参数是函数,输入类型为String,无返回值。所以这里第一个参数是函数,而开始学的时候,我一直不理解为什么没有括号,像这样 getName(f(“xx”),”Scala”),仔细想过之后才知道f(“xx”)不是函数,而是一个Unit,而要求的是(String)=>Unit!也就是说函数作为参数传入时是不能加括号的!!! 
函数中如果函数作为参数传入,有两种调用方式,第一种是上面那种,先定义一个函数值,如 
val f = (name: String) => println(“Hi, ” + name) ,这里也可用def f(name: String){println(“Hi, ” + name)},然后传入名称就行。第二种是直接写入匿名函数,如这里也可以改为 getName((name: String) => println(“Hello, ” + name) , “Spark”) 
个人感觉难点还是在传入函数与函数之间的如何使用才是难点! 
c.闭包 
什么是闭包? funcResult(“Hello”)(“Java”)中”Hello”是第一个参数,”Java”是第二个参数,正常情况下一个函数参数是不会保存下来的,因为这里是没有创建对象,如果要保存下来得这样吧:val some = “Hello”,定义个内存空间给他,然后funcResult(some)这样。但是例子中是保存下来了,保存在哪里?可以理解为像funcResult这种函数作为函数返回值的类型里面有一个小地方用为保存参数的,而这个函数看作两个函数,一旦程序运行时第一个函数会先得到一个参数,然后会保存起来,后面的第二个函数能拿到这个参数来继续使用(越说越不清了 -_-!)。

 

Scala函数式编程进阶的更多相关文章

  1. Scala实战高手****第12课:Scala函数式编程进阶(匿名函数、高阶函数、函数类型推断、Currying)与Spark源码鉴赏

    /** * 函数式编程进阶: * 1.函数和变量一样作为Scala语言的一等公民,函数可以直接赋值给变量 * 2.函数更常用的方式是匿名函数,定义的时候只需要说明输入参数的类型和函数体即可,不需要名称 ...

  2. Spark函数式编程进阶

    函数式编程进阶 1.函数和变量一样作为Scala语言的一等公民,函数可以直接复制给变量: 2.函数更长用的方式是匿名函数,定义的时候只需要说明输入参数的类型和函数体即可,不需要名称,但是匿名函数赋值给 ...

  3. Scala函数式编程——近半年的痛并快乐着

    从9月初啃完那本让人痛不欲生却又欲罢不能的<七周七并发模型>,我差不多销声匿迹了整整4个月.这几个月里,除了忙着讨食,便是继续啃另一本"锯著"--<Scala函数 ...

  4. Python函数式编程(进阶2)

    转载请标明出处: http://www.cnblogs.com/why168888/p/6411915.html 本文出自:[Edwin博客园] Python函数式编程(进阶2) 1. python把 ...

  5. Scala实战高手****第5课:零基础实战Scala函数式编程及Spark源码解析

    Scala函数式编程 ----------------------------------------------------------------------------------------- ...

  6. 9、scala函数式编程-集合操作

    一.集合操作1 1.Scala的集合体系结构 // Scala中的集合体系主要包括:Iterable.Seq.Set.Map.其中Iterable是所有集合trait的根trai.这个结构与Java的 ...

  7. Scala函数式编程(三) scala集合和函数

    前情提要: scala函数式编程(二) scala基础语法介绍 scala函数式编程(二) scala基础语法介绍 前面已经稍微介绍了scala的常用语法以及面向对象的一些简要知识,这次是补充上一章的 ...

  8. Scala函数式编程(四)函数式的数据结构 上

    这次来说说函数式的数据结构是什么样子的,本章会先用一个list来举例子说明,最后给出一个Tree数据结构的练习,放在公众号里面,练习里面给出了基本的结构,但代码是空缺的需要补上,此外还有预留的test ...

  9. Scala函数式编程(四)函数式的数据结构 下

    前情提要 Scala函数式编程指南(一) 函数式思想介绍 scala函数式编程(二) scala基础语法介绍 Scala函数式编程(三) scala集合和函数 Scala函数式编程(四)函数式的数据结 ...

随机推荐

  1. MDX函数(官方顺序,带示例)

    MDX函数(官方顺序) 1.  AddCalculatedMembers (MDX) 返回通过将计算成员添加到指定集而生成的集. 语法: AddCalculatedMembers(Set_Expres ...

  2. spring项目的 context root 修改之后,导致 WebApplicationContext 初始化两次的解决方法

    修改了 spring web 项目的 context root 为 / 之后,在启动项目时,会导致 WebApplicationContext  初始化两次,下面是其初始化日志: 第一次初始化: 四月 ...

  3. [原]openstack-kilo--issue(七):虚拟机怎么通外网,外网怎么ping通虚拟机

    =====问题======= 虚拟机可以ping通外网,外网能ping通虚拟机但是收不到reply 这个问题本人遇到有两种情况: 1.安装完整openstack-kilo后,在route中和虚拟机中抓 ...

  4. Swift实现截屏并保存相册

    func saveToLocal() { //截屏 let screenRect = UIScreen.mainScreen().bounds UIGraphicsBeginImageContext( ...

  5. C语言 时间函数的学习和总结

    一直都是以简单的time_t t,time(&t),ctime(&t)来表示时间,后来要以时间为日志文件的名字时,就有点蒙逼了.学习一下.   tm结构: struct tm {   ...

  6. ViewPager+Fragment再探:和TAB滑动条一起三者结合

    Fragment前篇: <Android Fragment初探:静态Fragment组成Activity> ViewPager前篇: <Android ViewPager初探:让页面 ...

  7. POJ 1066 Treasure Hunt【线段相交】

    思路:枚举四边墙的门的中点,与终点连成一条线段,判断与其相交的线段的个数.最小的加一即为答案. 我是傻逼,一个数组越界调了两个小时. #include<stdio.h> #include& ...

  8. Sphinx和coreseek检索引擎

    Sphinx是检索英文用,coreseek是检索中文用. Sphinx(斯芬克斯)是一个基于SQL的全文检索引擎,可以结合MySQL,PostgreSQL做全文搜索,它可以提供比数据库本身更专业的搜索 ...

  9. 万能的 SQL编程

    简介:T-SQL语句创建库.创建表和听.和添加约束等.T-SQL是数据库结构化查询语言,常见的增加.删出.修改.查询.创建库和创建表的语句,还支持定义变量.输出语句.逻辑控制语句(IF.CASE.WH ...

  10. android 下载文件

    import com.example.android.R; import android.app.Activity;import android.os.Bundle;import android.os ...