关于我 王宏江, 花名 : 宏江 Blog:h1p://hongjiang.info 经历 : Java : 10y+ Scala : 2y+ 十年工作经验,2009 年加入阿里, 曾在阿里巴巴中文站和 laiwang.com 担任架构师, 现在中间件 & 稳定性平台部门 Scala 布道者 业余马

Similar documents
什么是函数式编程?

Microsoft Word - 把时间当作朋友(2011第3版)3.0.b.06.doc

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数

エスポラージュ株式会社 住所 : 東京都江東区大島 東急ドエルアルス大島 HP: ******************* * 关于 Java 测试试题 ******

Guava学习之Resources

KillTest 质量更高 服务更好 学习资料 半年免费更新服务

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基

避孕篇

酒 神 (长篇小说)

(Microsoft Word - 136\260g\270\364\252\272\267s\256Q.doc)

【结构化面试名师精品班2ATY15K002】讲义.docx

PowerPoint Presentation

3.1 num = 3 ch = 'C' 2

chap07.key

无类继承.key

Microsoft Word - 第3章.doc


Fun Time (1) What happens in memory? 1 i n t i ; 2 s h o r t j ; 3 double k ; 4 char c = a ; 5 i = 3; j = 2; 6 k = i j ; H.-T. Lin (NTU CSIE) Referenc

<4D F736F F F696E74202D20332D322E432B2BC3E6CFF2B6D4CFF3B3CCD0F2C9E8BCC6A1AAD6D8D4D8A1A2BCCCB3D0A1A2B6E0CCACBACDBEDBBACF2E707074>

Microsoft Word - 第3章.doc

untitled

Python a p p l e b e a r c Fruit Animal a p p l e b e a r c 2-2

Java

Microsoft Word - 01.DOC

Strings

C/C++语言 - 运算符、表达式和语句

数据结构与算法 - Python基础

Microsoft Word - 把时间当作朋友(2011第3版)3.0.b.07.doc

詞 彙 表 編 號 詞 彙 描 述 1 預 約 人 資 料 中 文 姓 名 英 文 姓 名 身 份 證 字 號 預 約 人 電 話 性 別 2 付 款 資 料 信 用 卡 別 信 用 卡 號 信 用 卡 有 效 日 期 3 住 房 條 件 入 住 日 期 退 房 日 期 人 數 房 間 數 量 入

Microsoft PowerPoint - plan08.ppt

電機工程系認可證照清單 /7/1

9, : Java 19., [4 ]. 3 Apla2Java Apla PAR,Apla2Java Apla Java.,Apla,,, 1. 1 Apla Apla A[J ] Get elem (set A) A J A B Intersection(set A,set B) A B A B

WWW PHP

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

Microsoft PowerPoint - 8. 运算符重载 Operator Overloading.pptx

山东建筑大学学分制管理规定(试行)

二 筒 答 题 { 共 4 题, 每 题 1 0 分, 共 4 0 分 } 5. 简 述 教 育 与 社 会 实 践 相 结 合 的 现 实 意 义 6. 简 述 科 教 兴 国 战 略 的 涵 义 7. 简 述 科 学 精 神 的 涵 义 8. 简 述 创 新 教 育 思 想 对 学 校 教 育

获取 Access Token access_token 是接口的全局唯一票据, 接入方调用各接口时都需使用 access_token 开发者需要进行妥善保存 access_token 的存储至少要保留 512 个字符空间 access_token 的有效期目前为 2 个小时, 需定时刷新, 重复

WWW PHP Comments Literals Identifiers Keywords Variables Constants Data Types Operators & Expressions 2

Java java.lang.math Java Java.util.Random : ArithmeticException int zero = 0; try { int i= 72 / zero ; }catch (ArithmeticException e ) { // } 0,

Learn_Perl 3-02.pdf

Microsoft Word - 44雙月刊

新・解きながら学ぶJava

OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课

Microsoft PowerPoint - 3. 函数Functionl.ppt [兼容模式]

一般的类型和一般的方法 (Generic Types and Methods) 齐琦

《大话设计模式》第一章

e bug 0 x=0 y=5/x 0 Return 4 2


C/C++ - 字符串与字符串函数

威 福 髮 藝 店 桃 園 市 蘆 竹 區 中 山 里 福 祿 一 街 48 號 地 下 一 樓 50,000 獨 資 李 依 純 105/04/06 府 經 登 字 第 號 宏 品 餐 飲 桃 園 市 桃 園 區 信 光 里 民

Chapter12 Derived Classes

, 即 使 是 在 昏 暗 的 灯 光 下, 她 仍 然 可 以 那 么 耀 眼 我 没 有 地 方 去, 你 会 带 着 我 么 杜 晗 像 是 在 嘲 笑 一 般, 嘴 角 的 一 抹 冷 笑 有 着 不 适 合 这 个 年 龄 的 冷 酷 和 无 情, 看 着 江 华 的 眼 神 毫 无 温

<4D F736F F F696E74202D BDE1B9B9BBAFB3CCD0F2C9E8BCC D20D1ADBBB7>

<4D F736F F D20C577BCD6AAEFA4FDBBBFAF5BB279>

2009年3月全国计算机等级考试二级Java语言程序设计笔试试题


+ 演示代码已发布到 Github n


EJB-Programming-3.PDF

Microsoft Word - 澎湖田調報告-宏達組9804.doc


平 凡 足 迹 李 本 川 作 者 为 中 国 科 学 院 海 洋 研 究 所 研 究 员,1935 年 生, 山 东 荣 成 人 我 今 年 63 岁 了 大 前 年 丈 夫 和 儿 子 在 一 个 月 内 先 后 离 开 了 人 世, 女 儿 又 已 出 嫁, 现 在 是 孑 然 一 身 我 是

今天 年春季号 总 92 期

*

( ) / / / / / / /

(Microsoft Word - 8\244T\244\362\277\337\272]\244W\265L\246W.doc)

Microsoft Word - 專家本色 doc


但, 你 应 该 听 过 我 们 走 在 大 路 上 这 首 歌, 或 许 还 知 道 革 命 人 永 远 是 年 轻 那 支 歌 ; 并 且, 几 乎 可 以 肯 定, 你 在 戴 红 领 巾 的 那 阵, 必 然 唱 过 牛 儿 还 在 山 坡 吃 草, 放 牛 的 却 不 知 道 哪 儿 去

2 临 终 助 念 答 问 序 临 终 关 怀, 由 佛 门 净 宗 古 来 祖 师 大 德 提 倡 助 念 往 生, 现 今 已 渐 为 社 会 大 众 所 重 视, 在 台 湾, 台 大 长 庚 等 各 大 医 院, 也 都 设 有 助 念 室 ; 大 陆 上 许 多 道 场, 也 有 专 为

校园之星

<4D F736F F F696E74202D FA8BEA861B8EAB7BDBEE3A658BB50C0B3A5CE28B773A6CBA5AB29>

之 原 則 及 國 防 部 訂 頒 國 軍 列 管 國 有 不 動 產 提 供 非 軍 方 單 位 使 用 處 理 原 則 規 定 不 符, 仍 應 以 出 租 方 式 辦 理 惟 可 就 偏 遠 地 區 提 供 官 兵 金 融 水 電 服 務 使 用 部 分, 研 議 降 低 租 金 標 準, 報

chineseall

釋禪波羅蜜次第法門

证券代码: 证券简称:锦江股份 公告编号:【】

1700 装 卸 搬 运 7645 装 卸 搬 运 服 务 2100 建 筑 7410 工 程 服 务 11% 装 卸 搬 运 服 务, 是 指 使 用 装 卸 搬 运 工 具 或 者 人 力 畜 力 将 货 物 在 运 输 工 具 之 间 装 卸 现 场 之 间 或 者 运 输 工 具 与 装 卸

前 言 教 育 无 小 事, 它 成 就 着 学 生 的 未 来 作 为 教 师, 他 们 无 时 无 刻 不 在 关 注 着 学 生 的 成 长 学 生 的 未 来 学 生 就 像 一 朵 含 苞 待 放 的 花 朵, 需 要 老 师 们 的 细 心 呵 护, 给 学 生 需 要 的 东 西, 而

《盗墓笔记》 南派三叔/著

<CFFBB7D1D5DFD0D0CEAAD1A72E6D7073>

独立学院建设与发展







à










¹ ¹

Transcription:

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 Clean 静态类型 动态类型 ML OCaml Scala F# Lisp Scheme Erlang

关于 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) x 带入参数 1 执行 带入参数 2 执行 带入参数 3 执行

柯里化 (currying) 柯理化的实际用途? 1) 控制抽象, 可改变代码的书写风格 foo(res, ()=>print( test)) foo(res)(()=>print( test )) foo(res){ ()=>print( test ) }

柯理化的实际用途? 2) 实现部分应用函数 柯里化 (currying)

部分应用函数 (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 怎么理解?

Java : class List<T> {} Scala: class List[T] List[T] type parameter type constructor

Java : class List2<C<T>> {} // 不支持 Scala: class List2[C[T]] 或 class List2[C[_]] List2[C[_]] 类型参数也是 一个类型构造器

generic types as first- class types scala> new List2[List] 泛型也可以被当作类型参数传递, 与普通类型没有区别

对类型归纳 type Proper type( 自身类型 ) Int, String, List[String] List2[List] first- order/higher- order type ( 一阶 / 高阶类型 : 类型构造器 ) List ( 一阶 ), List2 ( 高阶 )

Higher- kinded type

Kind?

类型是对数据的抽象 String Int hi alibaba 2 100

Kind: 类别, 对类型的抽象 Kinds Types Values 注 : 类别 这个翻译不确定是不是标准

所有的 proper type 被抽象为同一种 kind, 用 * 表示 Kind: * Proper type: String List[Int] Pair[Int,Int]

对一阶类型的抽象 : 通过 Currying 一阶 Kind: * * * * * 一阶类型 / 类型构造器 : Set List Pair

对 高阶类型的抽象 : Higher- Kind: ( * *) * 高阶类型 / 类型构造器 : List2

图上少了 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