您能使用过程,功能,逻辑和OO编程语言表示相同的示例吗?

时间:2011-09-29 04:38:32

标签: paradigms

任何人都可以请我提供一个示例,通过使用几乎相同的示例问题,可以帮助我理解程序,功能,逻辑和面向对象的编程模型。

请使用过程,功能,逻辑和OO编程语言向我提供类似相同问题的示例代码片段。

4 个答案:

答案 0 :(得分:11)

http://99-bottles-of-beer.net/

(它以我自己可怕的99语言为特色。)

答案 1 :(得分:10)

让我们尝试更简单的例子 - 只计算第n个斐波纳契数。

首先,程序性(在Pascal中):

program Fibonacci;

function fib(n: Integer): Integer;
var a: Integer = 1;
    b: Integer = 1;
    f: Integer;
    i: Integer;
begin
  if (n = 1) or (n = 2) then
     fib := 1
  else
    begin
      for i := 3 to n do
      begin
         f := a + b;
         b := a;
         a := f;
      end;
      fib := f;
    end;
end;

begin
  WriteLn(fib(6));
end.

此示例显示了过程语言的功能:

  • 有一些子程序(本例中的功能)
  • 可能多次为变量分配值(:= 运算符)
  • 有循环(在这种情况下 运算符
  • 语言势在必行,即我们告诉计算机该做什么顺序

其次,面向对象(在Python中):

class Fibonacci:
   def __init__(self):
       self.cache = {}
   def fib(self, n):
       if self.cache.has_key(n):
           return self.cache[n]
       if n == 1 or n == 2:
            return 1
       else:
           a = 1
           b = 1
           for i in range(2, n):
               f = a + b;
               b = a;
               a = f;
           self.cache[n] = f;
           return f;


fibonaccyCounter = Fibonacci()
print fibonaccyCounter.fib(6)

实际上这个问题不值得创建一个类,所以我添加了已经计算过的结果的缓存。

此示例显示:

  • 类及其实例化(创建实例)
  • 类有自己的内存部分,自己的状态(自我及其成员)
  • 语言势在必行,即我们告诉计算机该做什么顺序

未显示但我们可以例如从抽象类中返回此类,返回某个序列的第n个成员。通过子类化,我们得到定义Fibonacci序列的类,序列1,2,3 ...,序列1,4,9,16,......等。

第三,在功能风格(Haskell)中:

import Text.Printf

fib :: Int -> Int
fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)

main = printf "%d\n" (fib 6)

演示了函数式编程范例的以下特性:

  • 没有状态,没有变量 - 只是函数定义
  • 没有周期 - 只有递归
  • 模式匹配:我们分别为其余数字定义“fib 0”,“fib 1”和“fib n”,不需要 if 等结构
  • 声明式样式 - 我们没有定义计算 main 函数值的步骤顺序:编译器/解释器/运行时在给定函数定义的情况下自行计算出来。我们告诉计算机我们想要得到什么,而不是做什么。
  • 懒惰的评价。如果main只调用“fib 2”,则不会调用“fib n”,因为仅当需要将其结果作为参数传递给其他函数时才会计算函数。

但是函数式语言的主要特征是函数是第一类对象。 这可以通过fib的其他实现来证明:

fib n = fibs!!n
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

这里我们将fibs函数作为参数传递给zipWith函数。 此示例还演示了延迟评估:“无限”列表仅计算到其他函数所需的范围。

顺便说一下,功能并不一定意味着不是面向对象的。一个功能和面向对象的编程语言的例子是Scala。

的Prolog:

fib(1, 1).
fib(2, 1).


fib(X, Y):-
        X > 1,
        X1 is X - 1,
        X2 is X - 2,
        fib(X1, Z),
        fib(X2, W),
        Y is W + Z.


main :-
   fib(6,X), write(X), nl.

可以看到以下逻辑编程风格的特征:

  • 语言是声明性的。在功能风格中,我们定义事物而不是按什么顺序来做。
  • 但与功能风格的区别在于我们定义谓词,而不是函数。在这种情况下,谓词fib(X,Y)表示“第X个斐波那契数是Y”。给定一些已知的谓词(fib(1,1)和fib(2,1) - 即第一个Fibonacci数为1,第二个Fibonacci数为1)和推断其他谓词的规则(Y是第X个Fibonacci数是Y是第一个斐波那契数和第二个第二个斐波纳契数之和,Prolog推断出有问题的谓词。实际上可能有超过1个答案!
  • 没有输入值和返回值 - 而是我们定义“输入”和“输出”之间的关系。

该程序也可用于发现第8号斐波那契位于序列的第6位:

?- between(0,inf,X), fib(X,8).
X = 6 .

答案 2 :(得分:7)

项目欧拉问题编号2:http://projecteuler.net/problem=2

Haskell(功能/逻辑):

p2 = sum [x | x <- fibs, (x `mod` 2) == 0] where
    fibs = unfoldr acc (0,1) where
            acc (prev, cur) | (prev+cur) > 4000000 = Nothing
                            | otherwise            = Just (prev+cur, (cur, prev+cur))

Python(OO):

class FibSum(object):
    def __init__(self, end):
        self.end = end
        self.next_two = (1,0)
        self.sum = 0

    def __iter__(self):
        return self

    def next(self):
        current, previous = self.next_two
        self.next_two = (previous+current, current)
        new = current+previous

        if current >= self.end:
            raise StopIteration
        elif (new % 2) == 0:
            self.sum += new
        else:
            pass


fibcount = FibSum(4000000)
[i for i in fibcount]
print fibcount.sum

C(程序/命令):

#include <stdio.h>

int main(void) 
{
    long int sum, newnum, previous = 0;
    long int current = 1;

    while(current <= 4000000) 
    {
        newnum = previous+current;
        if ((newnum % 2) == 0) 
        {
            sum = sum + newnum;
        }
        previous = current;
        current = newnum;

    }
    printf("%d\n", sum);
}

这是一个用MIT Scheme

编写的非常低效的版本
(define (unfold func seed)
    (let* ((result (func seed)))
    (cond ((null? result) ())
    (else (cons (car result) (unfold func (second result)))))))

(define (test x)
    (cond ((> (sum x) 4000000) ())
    (else (list (sum x) (list (second x) (sum x))))))

(define (sum xs)
    (cond ((null? (cdr xs)) (first xs))
    (else (+ (car xs) (sum (cdr xs))))))

(sum (filter (lambda (x) (eq? (modulo x 2) 0)) (unfold test (list 0 1))))

Prolog:Take from this here, posted by 13tazer31

fibonacci(_,Current,End,0) :-
        Current > End.
fibonacci(Previous, Current, End, Total) :-
        divisible(Current, 2),
        Next is Current + Previous,
        fibonacci(Current, Next, End, Sum),
        Total is Sum + Current, !.
fibonacci(Previous, Current, End, Total) :-
        Next is Current + Previous,
        fibonacci(Current, Next, End, Total).

divisible(Number, 0) :-
        write(‘Error: division by 0′).         
divisible(Number, Divisor) :-
        Number mod Divisor =:= 0.

答案 3 :(得分:1)

非常简单

  1. 程序性,功能逻辑 假设您想要计算某些东西(这是计算机的作用)
    1. 将问题分解为函数说f1,f2,f3 .... 现在,如果你看一下这个问题,你会看到它分为函数..但是必须有一个起点(从你开始计算的地方)和结束点(结束计算的地方),它们之间是函数(f1) ,F2,F3)。 因此,你真正做的不是编写一个大函数(F)来完成所有事情而且很长时间你将它分解成更小的部分(这称为重构)。理解150行长的单个函数很无聊......当你到达行尾时,你会忘记你从哪里开始,因此我们将事情分开。 现在我们如何进行计算---&gt; 我们创建一个单独的函数,例如compute()(这被称为facade),它将调用所需的剩余函数(f1,f2,f3 ...)并返回结果。 现在明白了: 如果我们编写了一个大约150行(复杂性增加)的单个函数。 假设我们将它分解为3个函数并说每个函数是50行(可管理)。我们如何降低复杂性,因为3个函数的行总和仍为150:D。函数名称减少了复杂性..它清楚地说明了函数的作用..它意味着查看名称,你可以知道函数的作用。
  2. OO编程逻辑:
    现在函数分散在函数逻辑中。当我们将所有相关函数(行为)放在一个伞(Class)中时,我们进一步降低了复杂性..如何... by&#34; Class name&#34;。现在你可以说不是调用f1,f2,f3 ..而是调用c1.f1(),c2.f2,c3.f3(),其中&#34; c&#34;表示一个类(域驱动设计)。

    imp ..无论你是使用oops还是功能逻辑,总有一个计算的起点和终点......记住我所谈到的compute()......而问题是谁打电话给它。答案就是你。所有OOP的逻辑或程序逻辑都隐藏在它背后(服务门面)