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

Ihome inaction 篇外篇之fp介绍

on

  • 696 views

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

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

Statistics

Views

Total Views
696
Views on SlideShare
696
Embed Views
0

Actions

Likes
2
Downloads
10
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as OpenOffice

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Ihome inaction 篇外篇之fp介绍 Ihome inaction 篇外篇之fp介绍 Presentation Transcript

    • Ihome In Action 函数式编程简介 Author:Dennis —— IHOME 的今生来世之篇外篇
    • 什么是 FP
      • FP : Functional Programming
      • 是指基于 lambda 演算的一种编程典范,函数式编程是一系列理念,而非教条。
      • Lambda 演算:
      • 一套用于研究 函数 定义、函数应用和 递归 的 形式系统 。它由 丘奇 ( Alonzo Church )和他的学生 克莱尼 ( Stephen Cole Kleene )在 20 世纪 30 年代 引入
    • FP 的优点
      • Lambda 演算与图灵模型等价
      • 无副作用:
      • 1 、无锁,并行, Erlang
      • 2 、利于单元测试
      • 机器辅助的推理和优化 amb 操作符
      • Less Code 更高的抽象能力带来更少的代码,更优雅的实现。
    • FP 特性
      • 无副作用、高阶函数、闭包、 currying 、延时求值、 Continuation
      • 、模式匹配、 Mond……
    • 无副作用
      • 1 、所有符号都是 final ,利于单元测试和调试,只需要关心输入、输出
      • 2 、从来不会有两个线程修改同一变量的情况出现,无需锁,无需临界区,利于并行, erlang 就是个例子
      • 3 、由于函数无副作用,因此函数的组合也将是无副作用的,这在命令式语言是不可想象的
    • 高阶函数
      • 函数:在 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
    • 高阶函数例子
      • 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)
    • 高阶函数 filter
      • 用于过滤列表,根据谓词predicate结果判断
      • (define (filter predicate sequence)
      • (cond ((null? sequence) '())
      • ((predicate (car sequence))
      • (cons (car sequence) (filter predicate (cdr sequence))))
      • (else
      • (filter predicate (cdr sequence)))))
    • 高阶函数 accumulate
      • 将列表中的元素按照操作OP累积起来
      • (define (accumulate op initial sequence)
      • (if (null? sequence)
      • initial
      • (op (car sequence) (accumulate op initial (cdr sequence)))))
    • 高阶函数 合并
      • 合并起来,求解下列问题:
      • 求解<=n中所有fib(k)是偶数的列表
      • 第一步:生成0-n
      • (define (enumerate-interval low high)
      • (if (> low high)
      • '()
      • (cons low (enumerate-interval (+ low 1) high))))
      • (enumerate-interval 0 n)
    • 高阶函数 合并
      • 第二步:由map生成0-n整数对应的fib(k)
      • (map fib (enumerate-interval 0 n))
      • 第三步:过滤偶数
      • (filter even?
      • (map fib (enumerate-interval 0 n)))
    • 高阶函数 合并
      • 第四步:将结果累积到列表
      • (accumulate cons
      • '()
      • (filter even?
      • (map (enumerate-interval 0 n)))))
    • 高阶函数 合并
      • 最终结果:
      • (define (even-fibs n)
      • (accumulate cons
      • '()
      • (filter even?
      • (map fib (enumerate-interval 0 n)))))
    • 高阶函数 合并
      • 以信息流的方式去观察,高阶函数带来了约定接口的抽象
    • 闭包 - 定义
      • 严格定义:闭包是包含了自由变量的代码块
      • 泛化:匿名函数, block 都归入闭包
      • 自由变量?
      • (define (get-adder x)
      • (lambda(y)(+ x y)))
      • X 就是自由变量,在离开 get-adder 作用域之后仍然可以访问。
      • (define add4 (get-adder 4))
      • (add4 7) => 11
      • 闭包作用:模块化、简化代码、抽象
    • 闭包 - 应用举例
      • 排序:
      • 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}
    • 闭包 - 应用举例
      • 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 });
    • 闭包应用举例
      • 模拟对象, 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;)())
    • Currying
      • Currying :俗称克里化,命名为了纪念逻辑学家 Haskell Curry 。它是为了解决 lambda 演算在多个参数情况下而引入的。作用是把带有多个参数的函数转化为带有单个参数的函数(其余的参数由 curry 来决定如何处理)
    • 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); 
    • 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
    • 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  
    • 延时求值
      • Lazy evalution :函数调用时,对参数的求值推迟到需要使用该参数的时候。
      • 作用:
      • 1 、特殊的控制结构
      • 2 、无穷列表,流 (stream)
    • 特殊的控制结构
      • 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))
    • 特殊的控制结构
      • 这个函数在非延时求值器的时候将无法正确求值,因为(/ 1 0)在函数调用前将求值,抛出错误。
      • 而在一个延时求值器中,由于推迟了对参数的求值,那么在(= 0 0)返回true之后,直接求值exception-value并返回,(/ 1 0)将根本不会被调用到,从而整个函数可以正确运作。
    • 无穷级数
      • 相对于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))
    • 无穷级数
      • 定义1的无穷数列
      • (define ones (cons-stream 1 ones))
      • 更无敌的例子,筛法求素数的无穷数列:
    • 筛法求素数
      • (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)))
    • Continuation
      • 表达式的求值分为两个阶段:
      • 1 、 what to evalute?
      • 2 、 waht to do with the value?
      • 那么 what to do with the value 就称为表达式的延续 (continuation)
    • Continuation 例子
      • (if (null? x)
      • '()
      • (cdr x))
      • 表达式(null? x)求值后,根据这个表达式的值去决定执行'()还是(cdr x),这个决定的过程就是表达式(null? x)的延续.
      • (+ 2
      • (call/cc
      • (lambda (k)
      • (* 5 (k 4))))) => 6
    • Continuation 在语言中的支持
      • call/cc: call-with-current-continuation
      • 该过程调用一个函数,并向此函数传入当前的continuation
      • Scheme、Ruby中都有这个call/cc支持
      • Continuaton的作用:
      • 1、实现高级的控制结构,break、goto
      • 2、实现代码级别的程序调用,协程
      • 3、实现机器推理所需要的fail、try机制
    • 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))))))))))
    • 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)))
    • amb操作符的实现
      • 通过call/cc实现,amb本质上是一种失败、回溯机制,通过continuation记录堆栈的跳转来实现
      • scheme的实现,通过宏 continuation 2.scm
      • Ruby的实现 continuation.rb
    • amb操作符的使用
      • 一道逻辑题:
      • Baker, Cooper, Fletcher, Miller, 和Smith住在一动5层公寓的不同楼层。Baker不在顶楼住。Cooper不在底楼住。Fletcher既不在顶楼也不在底楼。Miller住的楼层比Cooper住的高。Smith和Fletcher的楼层不相邻。Fletcher和Cooper的楼层不相邻。问每个人住的楼层。
    • 模式匹配