Your SlideShare is downloading. ×
Ihome inaction 篇外篇之fp介绍
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

Ihome inaction 篇外篇之fp介绍

680
views

Published on

很早以前做的一次函数式编程的介绍,很不成熟,做个备份。

很早以前做的一次函数式编程的介绍,很不成熟,做个备份。

Published in: Technology

0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
680
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
10
Comments
0
Likes
2
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Ihome In Action 函数式编程简介 Author:Dennis —— IHOME 的今生来世之篇外篇
  • 2. 什么是 FP
    • FP : Functional Programming
    • 是指基于 lambda 演算的一种编程典范,函数式编程是一系列理念,而非教条。
    • Lambda 演算:
    • 一套用于研究 函数 定义、函数应用和 递归 的 形式系统 。它由 丘奇 ( Alonzo Church )和他的学生 克莱尼 ( Stephen Cole Kleene )在 20 世纪 30 年代 引入
  • 3. FP 的优点
    • Lambda 演算与图灵模型等价
    • 无副作用:
    • 1 、无锁,并行, Erlang
    • 2 、利于单元测试
    • 机器辅助的推理和优化 amb 操作符
    • Less Code 更高的抽象能力带来更少的代码,更优雅的实现。
  • 4. FP 特性
    • 无副作用、高阶函数、闭包、 currying 、延时求值、 Continuation
    • 、模式匹配、 Mond……
  • 5. 无副作用
    • 1 、所有符号都是 final ,利于单元测试和调试,只需要关心输入、输出
    • 2 、从来不会有两个线程修改同一变量的情况出现,无需锁,无需临界区,利于并行, erlang 就是个例子
    • 3 、由于函数无副作用,因此函数的组合也将是无副作用的,这在命令式语言是不可想象的
  • 6. 高阶函数
    • 函数:在 scheme 中通常称为 procedure ,例子:
    • + => #<primitive:+>
    • (define (square x) (* x x)
    • (square 3) => 9
    • (square 4) => 10
    • ( (lambda(x) (* x x)) 3) => 9 匿名函数
    • 函数可以作为参数,作为返回值。
    • 高阶函数: high-order function ,简而言之就是操作函数的函数。注意,在 FP 中,函数是 first-class
  • 7. 高阶函数例子
    • Map 、 foreach 、 filter 、
    • map, 将 proc 作用于列表的每个元素,返回新的列表:
    • (define (map proc items)
    • (if (null? Items)
    • '()
    • (cons (proc (car items))
    • (map proc (cdr items)))))
    • (map square (list 1 2 3 4))
    • => (1 4 9 16)
  • 8. 高阶函数 filter
    • 用于过滤列表,根据谓词predicate结果判断
    • (define (filter predicate sequence)
    • (cond ((null? sequence) '())
    • ((predicate (car sequence))
    • (cons (car sequence) (filter predicate (cdr sequence))))
    • (else
    • (filter predicate (cdr sequence)))))
  • 9. 高阶函数 accumulate
    • 将列表中的元素按照操作OP累积起来
    • (define (accumulate op initial sequence)
    • (if (null? sequence)
    • initial
    • (op (car sequence) (accumulate op initial (cdr sequence)))))
  • 10. 高阶函数 合并
    • 合并起来,求解下列问题:
    • 求解<=n中所有fib(k)是偶数的列表
    • 第一步:生成0-n
    • (define (enumerate-interval low high)
    • (if (> low high)
    • '()
    • (cons low (enumerate-interval (+ low 1) high))))
    • (enumerate-interval 0 n)
  • 11. 高阶函数 合并
    • 第二步:由map生成0-n整数对应的fib(k)
    • (map fib (enumerate-interval 0 n))
    • 第三步:过滤偶数
    • (filter even?
    • (map fib (enumerate-interval 0 n)))
  • 12. 高阶函数 合并
    • 第四步:将结果累积到列表
    • (accumulate cons
    • '()
    • (filter even?
    • (map (enumerate-interval 0 n)))))
  • 13. 高阶函数 合并
    • 最终结果:
    • (define (even-fibs n)
    • (accumulate cons
    • '()
    • (filter even?
    • (map fib (enumerate-interval 0 n)))))
  • 14. 高阶函数 合并
    • 以信息流的方式去观察,高阶函数带来了约定接口的抽象
  • 15. 闭包 - 定义
    • 严格定义:闭包是包含了自由变量的代码块
    • 泛化:匿名函数, block 都归入闭包
    • 自由变量?
    • (define (get-adder x)
    • (lambda(y)(+ x y)))
    • X 就是自由变量,在离开 get-adder 作用域之后仍然可以访问。
    • (define add4 (get-adder 4))
    • (add4 7) => 11
    • 闭包作用:模块化、简化代码、抽象
  • 16. 闭包 - 应用举例
    • 排序:
    • Java:
    • class Product implements Comparator{
    • public int compare(Product other)
    • return this.price-other.price
    • Collections.sort(products)
    • Ruby:
    • products.sort{|a,b| a.price-b.price}
  • 17. 闭包 - 应用举例
    • Java7 引入的闭包语法:
    • double log = { double x => Math.log(x) }.invoke(10);
    • int sum = { int x, int y => x + y }.invoke(3, 4); // will return 7
    • String[] girls = { &quot;Jane&quot;, &quot;Eva&quot;, &quot;Sarah&quot;, &quot;Alice&quot; };
    • Arrays.sort(girls, { String s1, String s2 => int r = s1.length() - s2.length(); r == 0 ? s1.compareTo(s2) : r });
  • 18. 闭包应用举例
    • 模拟对象, lua:
    • function make_stack()
    •         local data = {};         local last = -1;
    •         local function push(e)             last = last + 1;             data[last] = e;         end
    •         local function pop()             if last == -1 then                 return nil             end             last = last - 1             return data[last+1]         end
    •         return function (index)             local tb = {push=push, pop=pop}             return tb[index]         end end
    • s=make_stack()
    • s(&quot;push&quot;)(&quot;test0&quot;)
    • s(&quot;push&quot;)(&quot;test1&quot;) s(&quot;push&quot;)(&quot;test2&quot;) s(&quot;push&quot;)(&quot;test3&quot;)
    • print(s(&quot;pop&quot;)()) print(s(&quot;pop&quot;)()) print(s(&quot;pop&quot;)())
  • 19. Currying
    • Currying :俗称克里化,命名为了纪念逻辑学家 Haskell Curry 。它是为了解决 lambda 演算在多个参数情况下而引入的。作用是把带有多个参数的函数转化为带有单个参数的函数(其余的参数由 curry 来决定如何处理)
  • 20. Currying 例子 1
    • Javascript 为例:
    • function add(x, y)  {       if(x!=null && y!=null) return x + y;  
    •      else if(x!=null && y==null) 
    • return function(y)  {            return x + y;       } 
    •      else if(x==null && y!=null)
    •   return function(x) {           return x + y;      }  } 
    • var a = add(3, 4); 
    • var b = add(2); 
    • var c = b(10); 
  • 21. Currying 例子 2
    • Ruby1.9 引入了 Proc#curry
    • plus = lambda {|a,b| a + b}  
    • plus(3,4) =>7
    • curried_plus = plus.curry
    • plus_three = curried_plus[3] 
    • plus_three(4) =>7
  • 22. Currying 例子 3
    • 可以写出很优雅的代码
    • is_weekday = lambda {|day_of_week, time| time.wday == day_of_week}.curry  
    •   
    • sunday    = is_weekday[0]  
    • monday    = is_weekday[1]  
    • tuesday   = is_weekday[2]  
    • wednesday = is_weekday[3]  
    • thursday  = is_weekday[4]  
    • friday    = is_weekday[5]  
    • saturday  = is_weekday[6]  
    •   
    • case Time.now  
    • when sunday   
    •    puts &quot;Day of rest&quot;  
    • when monday, tuesday, wednesday, thursday, friday  
    •    puts &quot;Work&quot;  
    • when saturday  
    •    puts &quot;chores&quot;  
    • end  
  • 23. 延时求值
    • Lazy evalution :函数调用时,对参数的求值推迟到需要使用该参数的时候。
    • 作用:
    • 1 、特殊的控制结构
    • 2 、无穷列表,流 (stream)
  • 24. 特殊的控制结构
    • Unless过程:
    • (define (unless condition usual-value exception-value)
    • (if condition
    • Exception-value
    • Usual-value))
    • (unless (= 0 0)
    • (/ 1 0)
    • (begin (display “exception return 0”) 0))
  • 25. 特殊的控制结构
    • 这个函数在非延时求值器的时候将无法正确求值,因为(/ 1 0)在函数调用前将求值,抛出错误。
    • 而在一个延时求值器中,由于推迟了对参数的求值,那么在(= 0 0)返回true之后,直接求值exception-value并返回,(/ 1 0)将根本不会被调用到,从而整个函数可以正确运作。
  • 26. 无穷级数
    • 相对于cons、car、cdr,我们定义相应的stream-cons stream-car stream-cdr,因此也有相应的高阶函数stream-map stream-filter等。
    • 定义自然数: (define (integers-starting-from n)
    • (cons-stream n (integers-starting-from (+ n 1))))
    • (define integers (integers-starting-from 1))
  • 27. 无穷级数
    • 定义1的无穷数列
    • (define ones (cons-stream 1 ones))
    • 更无敌的例子,筛法求素数的无穷数列:
  • 28. 筛法求素数
    • (define (divisible? x y) (= (remainder x y) 0))
    • (define (sieve stream)
    • (cons-stream
    • (stream-car stream)
    • (sieve (stream-filter (lambda(x)
    • (not (divisible? x (stream-car stream))))
    • (stream-cdr stream)))))
    • (define primes (sieve (integers-starting-from 2)))
  • 29. Continuation
    • 表达式的求值分为两个阶段:
    • 1 、 what to evalute?
    • 2 、 waht to do with the value?
    • 那么 what to do with the value 就称为表达式的延续 (continuation)
  • 30. Continuation 例子
    • (if (null? x)
    • '()
    • (cdr x))
    • 表达式(null? x)求值后,根据这个表达式的值去决定执行'()还是(cdr x),这个决定的过程就是表达式(null? x)的延续.
    • (+ 2
    • (call/cc
    • (lambda (k)
    • (* 5 (k 4))))) => 6
  • 31. Continuation 在语言中的支持
    • call/cc: call-with-current-continuation
    • 该过程调用一个函数,并向此函数传入当前的continuation
    • Scheme、Ruby中都有这个call/cc支持
    • Continuaton的作用:
    • 1、实现高级的控制结构,break、goto
    • 2、实现代码级别的程序调用,协程
    • 3、实现机器推理所需要的fail、try机制
  • 32. Continuation break 语句
    • scheme中是没有break的,可以通过continuation模拟:
    • (define product
    • (lambda (ls)
    • (call/cc
    • (lambda (break)
    • (let f ((ls ls))
    • (cond
    • ((null? ls) 1)
    • ((= (car ls) 0) (break 0))
    • (else (* (car ls) (f (cdr ls))))))))))
  • 33. Continuation amb 操作符
    • amb, 是 John McCarthy 在 1961 年提出的。
    • Amb 表达式
    • ( amb e1 e2 e3 e4 ...)
    • 有歧义性地返回 n 个表达式中 ei 之一的值,例如:
    • (list (amb 1 2 3) (amb 'a 'b))
    • 将有如下六个值:
    • (1 a) (1 b) (2 a) (2 b) (3 a) (3 b)
    • 注意: (amb) 永远是 fail 。
    • (define (require p)
    • (if (not p) (amb)))
  • 34. amb操作符的实现
    • 通过call/cc实现,amb本质上是一种失败、回溯机制,通过continuation记录堆栈的跳转来实现
    • scheme的实现,通过宏 continuation 2.scm
    • Ruby的实现 continuation.rb
  • 35. amb操作符的使用
    • 一道逻辑题:
    • Baker, Cooper, Fletcher, Miller, 和Smith住在一动5层公寓的不同楼层。Baker不在顶楼住。Cooper不在底楼住。Fletcher既不在顶楼也不在底楼。Miller住的楼层比Cooper住的高。Smith和Fletcher的楼层不相邻。Fletcher和Cooper的楼层不相邻。问每个人住的楼层。
  • 36. 模式匹配