SlideShare a Scribd company logo
Scala中的函数式特征
ADC	
  2013	
  
关于我
•  王宏江,花名:宏江	
  
•  Blog:h1p://hongjiang.info	
  
•  经历:	
  
–  Java	
  :	
  10y+	
  	
  
–  Scala	
  :	
  2y+	
  
–  十年工作经验,2009年加入阿里,曾在阿里巴巴中
文站和laiwang.com担任架构师,现在中间件&稳定
性平台部门	
  
–  Scala布道者	
  
–  业余马拉松爱好者	
  
说明
•  内容	
  	
  
	
  	
  	
  	
  	
  	
  1)	
  Scala中的函数式的特征	
  
	
  2)	
  Scala类型系统中的函数式特征	
  
	
  
	
  
	
  
•  交流:h1ps://github.com/CSUG/csug/	
  
•  旺旺群:	
  
	
   	
  Scala交流和答疑:	
  94329267/sugsug	
  
	
  	
  
函数式语言
纯函数式语言
Haskell Miranda
非纯函数式语言	
  
静态类型 动态类型
ML OCaml	
   Scala F# Lisp Scheme Erlang
Clean
关于Scala语言
面向对象与函数式被看成一个硬币的两面,Scala试图将这两⾯面融合起来
怎么理解这两种风格?
命令式与函数式
	
  
在《程序设计语言—实践之路》一书中	
  
将“面向对象”与“面向过程”都归类为“命令式”语
言
命令式与函数式
命令式与函数式
•  图灵机/冯诺依曼体系	
  
– 其运算可看做:	
  
– 通过修改内存来反映运算的结果。	
  
– (用命令修改状态)	
  
•  Lambda演算(λ	
  calculus)形式	
  
– 连续运算(基于函数)得到结果
•  函数式程序是跟值打交道的,而不是跟状
态打交道的。它们的工具是表达式,而不
是命令。	
  
	
  —《ML	
  for	
  the	
  Working	
  Programmer》	
  
  	
   	
  值 vs	
  	
  状态	
  
副作用(side	
  effect)
Scala的做法
•  同时支持val和var体现了scala的“平衡”也可
以说是“圆滑”	
  
•  鼓励使用val,但并不排斥var;实际编码中
val占大多数。
函数式是面向表达式的
Scala中的表达式
•  	
  1)	
  所有的表达式都有值	
  
•  2)	
  除了赋值和函数调用表达式,内置的几个
表达式只有:if,while,for,try,match	
  
•  3)	
  块表达式{…}是基本表达式的组合,它的值
是最后一个表达式的值。	
  
Scala中的表达式
•  一些表达式的值:	
  
	
  1)	
  a=1;	
  
	
  2)	
  while(a<100){print(a)}	
  
	
  3)	
  if(a<2)	
  1;	
  
•  赋值表达式、while表达式的值是Unit类型,它的值
是唯一的:	
  ()	
  
•  if表达式缺乏else的话,不符合条件则返回Unit类
型的();即上面相当于:if(a<2)	
  1	
  else	
  ()	
  
赋值语句的注意点:
不同于java:	
  
1)while(	
  (line	
  =	
  readLine()	
  )	
  !=	
  null	
  )	
  	
  
不起作用,前边的	
  line	
  =	
  readLine()	
  得到的是Unit
类型值	
  
2)x=y=1;	
  //	
  y=1;	
  x=()	
  
	
  y=1表达式的结果是(),x被赋予了Unit类型的值
 表达式主要是由函数调用组成的	
  
Funcfon	
  vs	
  Method	
  
Scala中的Funcfon/Method/Functor	
  
1)	
  狭义地区分(从可传递性上):	
  
方法(method):	
  指的是在trait/class/object中以def关键字声明的,它不能被
直接传递。	
  
	
  
函数(funcfon):	
  类型为ParamsType=>ResultType的变量,这些变量背后是
用FuncfonN对象来封装的;可以被传递。方法可以转换为函数。	
  
	
  
2)	
  广义上,抛开背后的实现,方法就是函数;编译器某些场景自动把方
法封装为一个函数对象来传递。Scala社区并不特别区分这两个名词,
注意语境,有时候函数就是指方法,有时候则是指函数对象	
  
函数作为一等公民
函数作为一等公民体现在哪儿?
1)  可传递/赋值	
  
2)  嵌套函数和匿名函数	
  
3)  高阶	
  
4)  偏应用(parfal	
  applicafon)	
  
5)  闭包	
  
参考:	
  h1p://en.wikipedia.org/wiki/First-­‐class_funcfon	
  
可传递
scala>	
  def	
  hf(f:	
  ()=>String)	
  =	
  println(f)	
  
hf:	
  (f:	
  ()	
  =>	
  String)Unit	
  
	
  
scala>	
  hf(()=>“hi”)	
  	
  //	
  传递一个匿名函数	
  
hi	
  
	
  
scala>	
  def	
  foo()	
  =	
  "ok"	
  
foo:	
  ()String	
  
	
  
scala>	
  hf(foo)	
  	
  //	
  eta-­‐conversion:	
  ()=>foo()	
  
ok
可传递
scala>	
  val	
  fun	
  =	
  (x:Int)	
  =>	
  print(x)	
  
fun:	
  Int	
  =>	
  Unit	
  =	
  <funcfon1>	
  
	
  
scala>	
  fun(2)	
  
2
嵌套函数
scala>	
  def	
  foo	
  ()	
  {	
  
	
  	
  	
  	
  	
  |	
  	
  	
  def	
  bar()	
  {	
  
	
  	
  	
  	
  	
  |	
  	
  	
  	
  	
  	
  	
  println("hi")	
  
	
  	
  	
  	
  	
  |	
  	
  	
  }	
  
	
  	
  	
  	
  	
  |	
  	
  	
  bar	
  
	
  	
  	
  	
  	
  |	
  }
嵌套函数
嵌套函数应用场景并不多,其中一个场景是
将递归函数的转为尾递归方式
lambda:	
  函数字面量(Funcfon	
  literal)	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  (x	
  :Int,	
  y:	
  Int)	
  	
  	
  	
  	
  	
  	
  	
  	
  =>	
  	
  	
  	
  	
  	
  	
  x	
  +	
  y	
  
参数 函数体右箭头
产生一段匿名函数,类型为	
  (Int,Int)=>Int	
  
Scala中参数的个数为0到22个。
匿名函数
高阶函数
Scala里的高阶函数
	
  第一种:用函数做参数的函数。eg:	
  
	
  
	
  scala>	
  def	
  f2(f:	
  ()=>Unit)	
  {	
  f()	
  }	
  
	
  f2:	
  (f:	
  ()	
  =>	
  Unit)Unit	
  
	
  scala>	
  def	
  f1()	
  {println(1)}	
  
	
  f1:	
  ()Unit	
  
	
  scala>	
  f2(f1)	
  
	
  1	
  
	
  scala>	
  f2(()=>println(“hi”))	
  	
  //传入匿名函数	
  
	
  hi	
  
Scala里的高阶函数
	
  第二种:产生的结果是一个函数的函数。eg:	
  
	
  
	
  scala>	
  def	
  hf():Int=>Int	
  =	
  x=>x+1	
  
	
  hf:	
  ()Int	
  =>	
  Int	
  
	
  
	
  scala>	
  val	
  fun	
  =	
  hf	
  
	
  fun:	
  Int	
  =>	
  Int	
  =	
  <funcfon1>	
  
	
  
	
  scala>	
  fun(2)	
  
	
  res0:	
  Int	
  =	
  3	
  
 
在lambda演算中,每个表达式都代表一个只
有单独参数的函数,这个函数的参数本身也
是一个只有单一参数的函数,同时,函数的
值是又一个只有单一参数的函数。
•  多个参数的函数怎么办?
柯里化(currying)	
  
柯里化(currying)	
  
scala>	
  def	
  sum(x:Int,	
  y:Int)	
  =	
  x+y	
  
sum:	
  (x:	
  Int,	
  y:	
  Int)Int	
  
	
  
//参数打散,两个参数分开	
  
scala>	
  def	
  sum2(x:Int)(y:Int)	
  =	
  x+y	
  
sum2:	
  (x:	
  Int)(y:	
  Int)Int	
  
	
  
	
  
	
  
柯里化(currying)	
  
scala>	
  sum2(1)(2)	
  
res1:	
  Int	
  =	
  3	
  
	
  
//	
  上面的调用相当于下面的几个步骤	
  
scala>	
  def	
  first(x:Int)	
  =	
  (y:Int)=>x+y	
  
first:	
  (x:	
  Int)Int	
  =>	
  Int	
  
	
  
scala>	
  first(1)	
  
res2:	
  Int	
  =>	
  Int	
  =	
  <funcfon1>	
  
	
  
scala>	
  val	
  second	
  =	
  first(1)	
  
second:	
  Int	
  =>	
  Int	
  =	
  <funcfon1>	
  
	
  
scala>	
  second(2)	
  
res3:	
  Int	
  =	
  3	
  
柯里化(currying)	
  
•  	
  函数链	
  
	
  把一个带有多个参数的函数,转换为多个只
有一个参数的函数来执行	
  
	
  f(1)(2)(3)	
  	
  à	
  	
  	
  ((f(1))(2))(3)	
  
fa(1)	
   r(2)	
   fc(3)	
  
产生新的函数
带入参数1执行
产生新的函数
x	
  
得到最终的值
带入参数2执行 带入参数3执行
柯里化(currying)	
  
•  柯理化的实际用途?	
  
	
  1)	
  控制抽象,可改变代码的书写风格。	
  
	
  
	
  	
  foo(res,	
  ()=>print(“test))	
  
	
  
	
  	
  foo(res)(()=>print(“test”))	
  	
  
	
  	
  
	
  	
  foo(res){	
  
	
  	
  	
  	
  ()=>print(“test”)	
  
	
  	
  	
  }	
  
柯里化(currying)	
  
•  柯理化的实际用途?	
  
	
  2)	
  实现部分应用函数。	
  
	
  
	
  	
  	
  
部分应用函数(parfal	
  applicafon	
  funcfon)	
  
把一个函数适配为另一个函数
偏应用函数(parfal	
  applicafon	
  funcfon)	
  
占位符:_	
  
	
  
scala>	
  def	
  pow(x:Int,	
  y:Int)	
  =	
  Math.pow(x,y)	
  
pow:	
  (x:	
  Int,	
  y:	
  Int)Double	
  
scala>	
  pow(2,3)	
  
res4:	
  Double	
  =	
  8.0	
  
scala>	
  val	
  square	
  =	
  pow(_:Int,	
  2)	
  
square:	
  Int	
  =>	
  Double	
  =	
  <funcfon1>	
  
scala>	
  square(3)	
  
res5:	
  Double	
  =	
  9.0	
  
部分应用函数(parfal	
  applicafon	
  funcfon)	
  
	
  
scala>	
  def	
  log(fme:Date,	
  msg:String)	
  {	
  println(fme	
  +	
  ":	
  "	
  +	
  msg)	
  }	
  
log:	
  (fme:	
  java.ufl.Date,	
  msg:	
  String)Unit	
  
scala>	
  val	
  log2	
  =	
  log(new	
  Date,	
  _:String)	
  
log2:	
  String	
  =>	
  Unit	
  =	
  <funcfon1>	
  
scala>	
  log2("test1")	
  
scala>	
  log2("test2")	
  
scala>	
  log2("test3")	
  
	
  
三次时间一样吗?	
  
绑定的是表达式,还是表达式的结果?
部分应用函数(parfal	
  applicafon	
  funcfon)
不绑定任何参数	
  
	
  
scala>	
  val	
  pow2	
  =	
  pow	
  _	
  
pow2:	
  (Int,	
  Int)	
  =>	
  Double	
  =	
  <funcfon2>	
  
闭包(closure)	
  
Java中的匿名内部类如何访问局部变量
	
  public	
  Thread	
  createThread(){	
  
	
   	
  //	
  提升局部变量的生命周期	
  
	
   	
  final	
  int	
  innerVar	
  =	
  100;	
  
	
   	
  	
  
	
   	
  return	
  new	
  Thread(){	
  
	
   	
   	
  public	
  void	
  run(){	
  	
  
	
   	
  System.out.println(innerVar);	
  
	
   	
   	
  }	
  
	
   	
  };	
  
	
  }	
  
	
  
innerVar	
  还是分配在栈空间上么?	
  
	
  
Java的匿名内部类,和闭包很像。但用匿名内部类来实现,前提
是先要定义好该行为的接口。繁琐一些,不那么灵活	
  
逻辑行为	
  +	
  上下文
scala>	
  def	
  foo	
  =	
  {	
  
	
  	
  	
  	
  	
  |	
  	
  	
  val	
  localVal	
  =	
  "hello"	
  
	
  	
  	
  	
  	
  |	
  	
  	
  val	
  fun	
  =	
  	
  	
  	
  	
  ()=>	
  	
  	
  	
  localVal	
  	
  	
  +	
  	
  ",world"	
  
	
  	
  	
  	
  	
  |	
  	
  	
  fun	
  
	
  	
  	
  	
  	
  |	
  }
Scala的类型系统中的函数式特征
generic	
  types	
  as	
  first-­‐class	
  types	
  	
  
generic	
  types	
  as	
  first-­‐class	
  types	
  
	
   	
   	
   	
   	
   	
  怎么理解?	
  
List[T]
type	
  parameter
type	
  constructor
Java	
  :	
  	
  class	
  List<T>	
  {}	
  
	
  
Scala:	
  	
  class	
  List[T]	
  
List2[C[_]]
类型参数也是⼀一个类型构造器
Java	
  :	
  	
  class	
  List2<C<T>>	
  {}	
  	
  //不支持	
  
	
  
Scala:	
  	
  class	
  List2[C[T]]	
  	
  或	
  
	
  	
  	
  	
  	
  class	
  List2[C[_]]
scala>	
  new	
  List2[List]
generic	
  types	
  as	
  first-­‐class	
  types	
  
泛型也可以被当作类型
参数传递,与普通类型
没有区别
type
Proper	
  type(特定类型)	
  
	
  
	
  
Int,	
  	
  String,	
  	
  	
  
List[String]	
  
List2[List]	
  
first-­‐order/higher-­‐order	
  	
  type	
  
(⼀一阶/⾼高阶类型:	
  泛型类型	
  	
  
	
  也叫类型构造器)	
  
	
  
	
  
List	
  (一阶),	
  	
  	
  	
  	
  
List2	
  (高阶)
对类型归纳
Higher-­‐kinded	
  type
Kind	
  ?
类型是对数据的抽象
“hi” “alibaba” 2 100
String Int
Kind:	
  	
  类别,对类型的抽象	
  
Types	
  
Values
Kinds	
  
注:“类别”这个翻译不确定是不是标准
 
所有的proper	
  type	
  被抽象为同一种	
  kind,用	
  *	
  表示
String List[Int]
*
Pair[Int,Int]
Kind:
Proper	
  type:
对一阶类型的抽象:	
  
List
	
  	
  *	
  →	
  *
Pair
一阶Kind:
一阶类型/	
  类型构造器: Set
	
  	
  *	
  →	
  *	
  →	
  *
通过
Currying
对⾼高阶类型的抽象:	
  
List2
	
  (	
  *	
  →	
  *)	
  	
  	
  →	
  	
  	
  *Higher-­‐Kind:
高阶类型/	
  类型构造器:
图上少了higher-­‐kind	
  ,	
  	
  h1p://adriaanm.github.io/files/higher.pdf	
  
以函数的视角
class	
  List[T]	
  	
   	
   	
  	
  
List是一个类型构造器,类似一个一阶函数,接受一个proper	
  type参数,并生成一个proper	
  
type.	
  
	
   	
   	
  List	
  :	
  	
  	
  	
  (T)	
  =>	
  List[T]	
  
	
   	
   	
   	
   	
  	
  	
  	
  	
  	
  *	
  	
  →	
  *	
  
	
  
class	
  List2[C[_]]	
  
List2类似高阶函数,接受一个类型构造器,生成一个proper	
  type	
  
	
   	
   	
  List2:	
  	
  	
  (T=>C[T])	
  =>	
  List2[C]	
  
	
   	
   	
   	
   	
  	
  	
  	
  	
  (*	
  	
  →	
  *)	
  	
  →	
  *
type	
  lambda
Scala	
  supports	
  a	
  limited	
  version	
  of	
  type	
  lambda
type	
  lambda
scala>	
  def	
  foo[M[_]]	
  (f	
  :	
  M[Int])	
  =	
  f	
  
	
  
	
  
scala>	
  foo[List]	
  (	
  List(1,2,3)	
  )	
  
res9:	
  List[Int]	
  =	
  List(1,	
  2,	
  3)	
  
	
  
scala>	
  foo	
  (	
  List(1,2,3)	
  ) 	
   	
  //	
  类型参数可以省略,编译器会推断	
  
res9:	
  List[Int]	
  =	
  List(1,	
  2,	
  3)	
  
	
  
scala>	
  foo(	
  (x:Int)	
  =>	
  println(x)	
  )	
  	
  //	
  如何让这句能编译通过?
type	
  lambda
(x:Int)	
  =>	
  println(x)	
  	
  背后是	
  Funcfon1[Int,	
  Unit]	
  
	
  
	
  
scala>	
  foo[	
  ({type	
  X[Y]	
  =	
  Funcfon1[Y,	
  Unit]})#X	
  ]	
  (	
  (x:Int)=>print(x)	
  )	
  
res5:	
  Int	
  =>	
  Unit	
  =	
  <funcfon1>
Scala	
  的类型系统是图灵完备的,即利用类型
系统本身就可以解决一些问题。
利用scala的类型系统解决汉诺塔:	
  h1ps://gist.github.com/jrudolph/66925
我们在招人
•  不限内部或外部	
  
•  联系: hongjiang.wanghj@alibaba-­‐inc.com
Q&A

More Related Content

PDF
千呼萬喚始出來的 Java SE 7
PDF
lambda/closure – JavaScript、Python、Scala 到 Java SE 7
PDF
Ecmascript
PPT
Introduction to C++ over CLI
PPTX
認識 C++11 新標準及使用 AMP 函式庫作平行運算
PDF
Java 開發者的函數式程式設計
PDF
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫
PDF
潜力无限的编程语言Javascript
千呼萬喚始出來的 Java SE 7
lambda/closure – JavaScript、Python、Scala 到 Java SE 7
Ecmascript
Introduction to C++ over CLI
認識 C++11 新標準及使用 AMP 函式庫作平行運算
Java 開發者的函數式程式設計
Java SE 8 的 Lambda 連鎖效應 - 語法、風格與程式庫
潜力无限的编程语言Javascript

What's hot (19)

PPTX
Js的国(转载)
PPTX
Ecma script edition5-小试
PDF
Java 8 與 retrolambda
PPT
Scala
PPT
Java Script 引擎技术
PDF
深入淺出 Web 容器 - Tomcat 原始碼分析
PPTX
Javascript share
PPT
Lua 语言介绍
PPTX
Introduction to Basic Haskell Components (In Chinese)
PDF
JavaScript 教程
PPT
Hi Haskell
PPTX
C++中级培训胶片
 
DOC
深入剖析Concurrent hashmap中的同步机制(下)
PPT
PPTX
ES5 introduction
PDF
OOP in C - Virtual Function (Chinese Version)
PDF
Java script closures
PDF
Swift 程序语言介绍
PPT
Javascript Training
Js的国(转载)
Ecma script edition5-小试
Java 8 與 retrolambda
Scala
Java Script 引擎技术
深入淺出 Web 容器 - Tomcat 原始碼分析
Javascript share
Lua 语言介绍
Introduction to Basic Haskell Components (In Chinese)
JavaScript 教程
Hi Haskell
C++中级培训胶片
 
深入剖析Concurrent hashmap中的同步机制(下)
ES5 introduction
OOP in C - Virtual Function (Chinese Version)
Java script closures
Swift 程序语言介绍
Javascript Training
Ad

Viewers also liked (20)

PPTX
Shell,信号量以及java进程的退出
PPT
Jvm内存管理基础
PPTX
Ali-tomcat
PDF
中等创业公司后端技术选型
PPTX
Scala类型系统
PPT
Java7 fork join framework and closures
PPT
Enum开锁
PPT
Aswan&hump
PPT
善用工具
PPT
聊一些电影
PPT
Scala function-and-closures
PPT
Exodus重构和向apollo迁移
PPT
Effective linux.2.(tools)
DOC
深入剖析Concurrent hashmap中的同步机制(上)
PPT
Effective linux.3.(diagnosis)
PDF
Hash map导致cpu100% 的分析
PPT
Effective linux.1.(commandline)
PPT
Exodus2 大局观
PDF
Real world akka recepies v3
PPTX
Automatic Scaling Iterative Computations
Shell,信号量以及java进程的退出
Jvm内存管理基础
Ali-tomcat
中等创业公司后端技术选型
Scala类型系统
Java7 fork join framework and closures
Enum开锁
Aswan&hump
善用工具
聊一些电影
Scala function-and-closures
Exodus重构和向apollo迁移
Effective linux.2.(tools)
深入剖析Concurrent hashmap中的同步机制(上)
Effective linux.3.(diagnosis)
Hash map导致cpu100% 的分析
Effective linux.1.(commandline)
Exodus2 大局观
Real world akka recepies v3
Automatic Scaling Iterative Computations
Ad

Similar to functional-scala (10)

PPTX
Scala+spark 2nd
PPTX
Scala+RDD
KEY
Scala
PDF
Scala
PDF
Clojure and FP
PPTX
Scala再探
PPTX
Scala分享第二期
PDF
函数式编程
PDF
Clojure简介与应用
ODP
Ihome inaction 篇外篇之fp介绍
Scala+spark 2nd
Scala+RDD
Scala
Scala
Clojure and FP
Scala再探
Scala分享第二期
函数式编程
Clojure简介与应用
Ihome inaction 篇外篇之fp介绍

functional-scala