前往顾页
以后地位: 主页 > 收集编程 > Ajax实例教程 >

FP and OOP编程范式介绍

时候:2017-12-04 21:57来源:知行网www.zhixing123.cn 编辑:麦田守望者

FPOOP 是目前主流的编程范式.我们不议论这两种编程范式的好坏, 仅仅会商一下 FP OOP 二者的不同.

##Decomposition

若何将一个任务分化, 这是任何一名Programmer都需求考虑的事情, 而FPOOP对若何将一个年夜型法度或任务分化有着完整不合的体例.

  • FP 中, 我们凡是将法度分化为有着不合操纵的函数
  • OOP 中, 我们将法度分化为具有不合行动的类.

##Example

我们经由过程举一个简朴的例子, 来讲明FPOOP之间的辨别. 假定我们有:

  • 不合的表达式, 整数, 求反, 乞降.
  • 不消的表达式操纵, eval, toString, hasZero.

这个问题就像实现下面二维表格中的每个空格

--------------------------------------
|        | eval | toString | hasZero |
--------------------------------------
|   Int  |      |          |         |   
--------------------------------------
|   Add  |      |          |         |
--------------------------------------
| Negate |      |          |         |
--------------------------------------

不管你用的是甚么编程说话, 都需求考虑若何实现表格中的每个entry

##Functional Approach

在函数式说话中

  • 为表达式定义数据范例datatype, 为每个范例增加机关函数(静态范例).
  • 为每个操纵定义函数function.
  • 在每个函数中, 所有的数据范例都应当有一个分支branch.

###ML Code

exception BadResult of string

datatype exp =
    Int    of int
  | Negate of exp
  | Add    of exp * exp
fun eval e =
    case e of
Int _ =>e
| Negate e1 => (case eval e1 of
                           Int i => Int (~i)
                         | _ => raise BadResult "non-int in negation")
      | Add(e1,e2) => (case (eval e1, eval e2) of
                           (Int i, Int j) => Int (i+j)
                         | _ => raise BadResult "non-ints in addition")
fun toString e =
    case e of
        Int i      => Int.toString i
      | Negate e1  => "-(" ^ (toString e1) ^ ")"
      | Add(e1,e2) => "("  ^ (toString e1) ^ " + " ^ (toString e2) ^ ")"
fun hasZero e =
    case e of
        Int i      => i=0
      | Negate e1  => hasZero e1
      | Add(e1,e2) => (hasZero e1) orelse (hasZero e2)

###Racket Code

#lang racket

(struct Int (e) #:transparent)
(struct Negate (e) #:transparent)
(struct Add (e1 e2) #:transparent)

(define (eval e)
  (cond ((Int? e) e)
        ((Negate? e) (Int (- (eval e))))
        ((Add? e) (Int (+ (eval (Add-e1 e)) (eval (Add-e2 e)))))
        (else (error "BadResult"))))

(define (toString e)
  (cond ((Int? e) (number->string (Int-e e)))
        ((Negate? e) (string-append "-" (string-append "(" (string-append (toString (Negate-e e)) ")"))))
        ((Add? e) (string-append "(" 
                                 (string-append (toString (Add-e1 e)) 
                                                (string-append " + " 
                                                               (string-append (toString (Add-e2 e)) ")")))))
        (else (error "BadResult"))))

(define (hasZero e)
  (cond ((Int? e) (= (Int-e e) 0))
        ((Negate? e) (hasZero (Negate-e e)))
        ((Add? e) (or (hasZero (Add-e1 e)) (hasZero (Add-e2 e))))))

##Object-Oriented Approach

在面向工具说话中, 将问题分化到类, 每个类对应一种数据范例.

  • 为表达式定义类class, 为所有表达式定义一个笼统类, 可以为所有的子类增加公有的属性和体例.
  • 为每种数据范例定义一个子类subclass.
  • 在每个子类中, 为所有的操纵定义体例method.

##Ruby Code

在静态说话中, 需求定义一个superclass声明所有需求实现的体例, 而在Ruby这类文雅的静态说话中, 我们写出superclass仅仅是为了反应逻辑.

class Exp
  # could put default implementations or helper methods here
end


class Int < Exp
  attr_reader :i
  def initialize i
    @i = i 
  end
  def eval 
    self
  end
  def toString
    @i.to_s 
  end
  def hasZero
    i==0
  end 
end


class Negate < Exp
  attr_reader :e
  def initialize e
    @e = e 
  end
  def eval
    Int.new(-e.eval.i) # error if e.eval has no i method (not an Int)
  end
  def toString
    "-(" + e.toString + ")"
  end
  def hasZero
    e.hasZero
  end
end

class Add < Exp
  attr_reader :e1, :e2
  def initialize(e1,e2)
	@e1 = e1
	@e2 = e2 
  end
  def eval
    Int.new(e1.eval.i + e2.eval.i) # error if e1.eval or e2.eval have no i method
  end
  def toString
    "(" + e1.toString + " + " + e2.toString + ")"
  end
  def hasZero
    e1.hasZero || e2.hasZero
  end
end

##Compare

我们可以看到, 函数是编程将法度分化为履行不合操纵的函数, 而面向工具编程将其分化为具有不合行动的类. 仅它们固然是相反的, 但是确切类似的, 它们决定法度经由过程行分类或列分类. 了解这个问题是非常极其首要的. 那么, 哪一种编程范式更好呢.

对每小我来讲可能有不合的答案, 对我小我来讲, 我更偏疼FP, 仅仅是因为它成心思, 当然pure functional programmingpure object-oriented programming都是不完美的.

我们需求比较这两种范式在做不合标的目标的扩展的时候, 代码的转变.

##Extending Operations Or Variants

当我们利用Functional Porgramming的实现的时候, 增加一个操纵是简朴的. 我们可以直接增加一个function而没必要变动现有的代码. 比如说, 我们增加一个函数将所有正数转化为正数.

fun noNegConstants e =
    case e of
        Int i       => if i < 0 then Negate (Int(~i)) else e
      | Negate e1   => Negate(noNegConstants e1)
      | Add(e1,e2)  => Add(noNegConstants e1, noNegConstants e2)

      
(define (noNegConstants e)
  (cond ((Int? e) (let ((i (Int-e e)))
                    (if (< i 0)
                        (Negate (Int (- i)))
                        (e))))
        ((Negate? e) (Negate (noNegConstants (Negate-e e))))
        ((Add? e) (Add (noNegConstants (Add-e1 e)) (noNegConstants (Add-e2 e))))
        (else (error "BadResult"))))

当碰到另外一种环境, 增加数据范例的时候, 我们需求点窜所有的function增加一个新的分支, 措置新的数据范例.

但是Object-oriented Programming的实现就可以够很好的措置这类环境. 增加一个新的数据范例是非常简朴的, 只需求实现一个子类, 不需求点窜任何代码.

class Mult < Exp
  attr_reader :e1, :e2
  def initialize(e1,e2)
	@e1 = e1
	@e2 = e2
  end
  def eval
    Int.new(e1.eval.i * e2.eval.i) # error if e1.eval or e2.eval has no i method
  end
  def toString
    "(" + e1.toString + " * " + e2.toString + ")"
  end
  def hasZero
    e1.hasZero || e2.hasZero
  end
end

但是增加一个新的操纵, 我们需求点窜之前所有的类来适应这类改变. 当时用静态范例的说话的时候, 我们便可以在父类中声明这类体例, 如许所有的子类没有实现体例的时候, 范例查抄体系就会报错.

----------------------------------------
|              |     OOP    |    FP    |
----------------------------------------
|  Operations  |     ^_^    |   v_v    |  
----------------------------------------
|   Variants   |     v_v    |   ^_^    |  
----------------------------------------

##Extensibility

正如之前我们所看到的:

  • 函数式分化易于增加新的操纵operation.
  • 面向工具式分化易于增加新的variant.

当你提前打算将来会为你的体系增加operationvariant时, 你可以提前挑选利用哪一种编程范式, 但是将来是难以瞻望的, 我们不太可能晓得甚么哪一种拓展是更优良的. 并且更可能的是, 行或列的增加常常是都有的. 这就给我们的法度的拓展增加的了更多的坚苦.

实际上, 编程说话总会供应体例来降落Extensibility, 因为Extensibility is a double-edged sword. 正因为这些启事, 若何才气使软件兼具结实性与拓展性是有价值但是坚苦的.

顶一下
(1)
100%
踩一下
(0)
0%
------分开线----------------------------
标签(Tag):编程范式
------分开线----------------------------
颁发评论
请自发遵循互联网相关的政策法规,严禁公布色情、暴力、革命的谈吐。
评价:
神色:
考证码:点击我更换图片
猜你感兴趣