写在前面

众所周知,scala一向宣称自己是面向函数的编程,(java表示不服,我是面向bean的编程!)那什么是函数?

在接触java的时候,有时候用函数来称呼某个method(实在找不出词了),有时候用方法来称呼某个method,虽然method的中文翻译就是“方法”,但对于java来说,方法和函数是等价的,或者说没有函数这个概念。

而对于scala,这两者似乎有一个较为明确的边界。

你会发现满世界的函数,而你却在写方法

Scala 方法&函数

方法

Scala的方法和java可以看成是一样的,只是多了点语法糖。

比如无参方法在申明时可以不加括号,甚至在调用过程也不用加括号

def f = 1+1
println(f)

比如方法可以添加泛型规则,这在java中只能在类申明

def f[T](t: T) = {t}

还有其它很多细节语法,遇到才深入吧

一般而言只要知道函数的结构就行(但是我想说,spark的代码就没有一个函数长成这样的啊..),请忽略下图的“函数”字样,其实就是方法

方法应用

def method(): Unit ={
//本地方法
def print(str:String): Unit ={
println(str)
}
print("hello")
}

方法的语法还是跟java差不多的,只是有些可以省略而已。

比较重要的就是本地方法,即方法中嵌套方法

函数

Scala的函数是基于Function家族,0-22,一共23个Function Trait可以被使用,数字代表了Funtcion的入参个数

函数语法

下面这四个函数的意义是一样的

// println(fun1)
// println(fun2)
// println(fun3)
// println(fun4)
// 都为<function2>
val fun1 = new Function2[Int,Int,Int]() {
override def apply(v1: Int, v2: Int): Int = {
v1+v2
}
} val fun2 = new ((Int, Int) => Int)() {
override def apply(v1: Int, v2: Int): Int = {
v1+v2
}
} val fun3 = (v1:Int,v2:Int) => v1+v2 // _可以把method转换成function
val fun4 = fun4Method _
def fun4Method(v1:Int,v2:Int): Int = {
v1+v2
}

一般我们都采用第三种fun3定义方式,也是最难懂的一个定义方式。具体结构参考下图

那函数有什么用呢?

Java里只有方法都能适应一切需求,那scala又提出函数的概念肯定有意义。

1.函数可以直接赋值给变量,可以让函数很方便的传递

2.闭包(closure),可以把灵活操作代码块,从而引申出其他灵活的语法

函数应用

在spark中,有很多方法入参中使用函数的场景,比如如下函数

defrunJob[T,U](fun: Iterator[T] => U ,resHandler: (Int, U) => Unit): Unit ={
//忽略里面的逻辑
}

其中的fun和resHandler都是函数

Fun是入参为Iterator[T],返回值为U的函数,一个入参的函数其实就是Function1的实例

resHandler是入参为Int和 U无返回值的函数,二个入参的函数其实就是Function2

模拟spark中常见的一段代码语法,拿一个普通scala类型的例子来说

//模拟spark的runJob方法
def runJob[T,U](fun: Iterator[T] => U ,resHandler: (Int, U) => Unit): Unit ={
val listBuffer = new ListBuffer[T]
listBuffer.append("h".asInstanceOf[T])
listBuffer.append("e".asInstanceOf[T])
listBuffer.append("l".asInstanceOf[T])
listBuffer.append("l".asInstanceOf[T])
listBuffer.append("o".asInstanceOf[T])
//这里调用函数其实用到了伴生对象的概念,fun(xxx)就是fun.apply(xxx)
val res = fun(listBuffer.iterator)
//spark中,这里是每个partition的数据都存入arr,这里做模拟就一个partition了:)
resHandler(0,res)
} //模拟调用runJob的方法
def main(args: Array[String]): Unit = {
val arr = new Array[String](1)
//fun函数的实际逻辑
val fun = (it:Iterator[String]) => {
val sb = new StringBuilder()
while (it.hasNext)
sb.append(it.next())
sb.toString()
} //resHandler函数的实际逻辑
val resHandler = (i:Int,res:String) => arr(i) = res
runJob[String,String](fun ,resHandler)
println(arr.mkString(""))
}

其实就是传递函数的逻辑,和java的匿名类差不多(只有一个方法的匿名类),只是多了点语法糖

这么做的好处也是不言而喻的

1.可以构造出更抽象的方法,使得代码结构更简洁

2.spark的思想就是lazy,而函数传递也是一个lazy的过程,只有在实际触发才会执行

偏函数

英文为PartialFunction,不知道这么翻译对不对,貌似都这么叫。

PartialFunction其实是Funtion1的子类

参考源码

trait PartialFunction[-A, +B] extends (A => B)

A => B就是标准的函数结构

那PartialFunction有什么作用呢?

模式匹配!

PartialFunction最重要的两个方法,一个是实际的操作逻辑,一个是校验,其实就是用来做模式匹配的。

参考资料

《Scala编程》

scala(一)方法&函数的更多相关文章

  1. 【Scala篇】--Scala中的函数

    一.前述 Scala中的函数还是比较重要的,所以本文章把Scala中可能用到的函数列举如下,并做详细说明. 二.具体函数 1.Scala函数的定义 def fun (a: Int , b: Int ) ...

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

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

  3. Scala高阶函数与泛型

    1. Scala中的函数 在Scala中,函数是“头等公民”,就和数字一样.可以在变量中存放函数,即:将函数作为变量的值(值函数). 2. scala中的匿名函数,即没有函数名称的函数,匿名函数常作为 ...

  4. scala def方法时等号和括号使用说明笔记

    scala定义方法时会指定入参和返回类型(无返回类型时对应Unit,即java和C中的void模式). 1.有入参,有返回类型时,scala具有类型推导功能,以下两种表达方式效果一样.但根据scala ...

  5. scala编程(八)——函数和闭包

    当程序变得庞大时,你需要一些方法把它们分割成更小的,更易管理的片段.为了分割控制流,Scala 提供了所有有经验的程序员都熟悉的方式:把代码分割成函数.实际上,Scala 提供了许多 Java 中没有 ...

  6. Scala 深入浅出实战经典 第42讲:scala 泛型类,泛型函数,泛型在spark中的广泛应用

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

  7. <经验杂谈>C#中一种最简单、最基本的反射(Reflection):通过反射获取方法函数

    说起反射之前和很多用C#/.net的同仁们一样,相比于一般应用层对数据的增删改查总有点觉得深奥到难以理解.其实程序这东西,用过.实践过就很简单,我一直这么认为. 先说下概念:反射 Reflection ...

  8. Python学习入门基础教程(learning Python)--8.3 字典常用的方法函数介绍

    本节的主要讨论内容是有关dict字典的一些常用的方法函数的使用和范例展示. 1. clear清除字典数据 语法结构如下: dict_obj.clear() 示例代码如下: dict1 = {'web' ...

  9. PHP(方法 函数 循环 和 数组 查找)

    循环 和 数组 查找 顺序查找 二分法查找 冒泡排序 方法 函数 定义:一堆代码的集合叫做函数(满足条件下“一堆”) 语法,定义,调用,参数列表(形参,实参),返回值 两种方法: function 方 ...

随机推荐

  1. 解决64位debian下无法安装ia32库的问题

    原文地址:http://crunchbang.org/forums/viewtopic.php?pid=277918 因为64位debian源中并没有包括32位的软件包,所提安装ia32会提示依赖无法 ...

  2. 数据结构(java语言描述)

    概念性描述与<数据结构实例教程>大同小异,具体参考:http://www.cnblogs.com/bookwed/p/6763300.html. 概述 基本概念及术语 数据 信息的载体,是 ...

  3. Django logging模块

    一.Django logging配置 1.在setting.py中配置 # 日志文件存放路径 BASE_LOG_DIR = os.path.join(BASE_DIR, "log" ...

  4. 前端 Dom 直接选择器

    文档对象模型(Document Object Model,DOM)是一种用于HTML和XML文档的编程接口.它给文档提供了一种结构化的表示方法,可以改变文档的内容和呈现方式.我们最为关心的是,DOM把 ...

  5. 如何保护自己的GitHub代码不被别人覆盖

    我们在自己的github上创建了免费的公开代码,为了防止别人通过git push upstream master 覆盖了自己原有的代码,需要作一下设置:Settings->Branchs,然后在 ...

  6. Spark Streaming实战

    1.Storm 和 SparkStreaming区别 Storm                      纯实时的流式处理,来一条数据就立即进行处理 SparkStreaming 微批处理,每次处理 ...

  7. CCF 201312-4 有趣的数[dp][难]

    问题描述 试题编号: 201312-4 试题名称: 有趣的数 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 我们把一个数称为有趣的,当且仅当: 1. 它的数字只包含0, 1, ...

  8. 工作笔记——js前端规范

    去年年末做了一个项目,因为第一次做前端管理职位,第一次做整个项目的前端架构很多东西都不熟悉,作为一次大胆的尝试. js方面的只有一个坑,那就是前端与后端的网络层封装,这一块是在后端的协助下开发的.网络 ...

  9. git 更新某个文件

    1.拉取某个仓库的某个文件 git fetch git checkout origin/master test.php

  10. Mysql之正则匹配

    Regex与Like的关系Mysql中我们经常会用到正则表达式就是Like filed like '%?%' .但是有时对于一些复杂场景下的正则过滤,单单一个like就显得有些力不从心了 Regex的 ...