您能使用过程式、函数式、逻辑式和面向对象编程语言来表示相同的示例吗?

发布于 2024-12-07 06:42:45 字数 107 浏览 3 评论 0原文

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

请给我使用过程、函数、逻辑和面向对象编程语言的相同问题的示例代码片段。

Can anyone please provide me with an example that can help me to understand Procedural, functional, Logic and Object Oriented programming models side by side by using nearly same example-problem.

Please give me example code-snippets of the somewhat same problem using Procedural, Functional, Logic and OO programming languages.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

悍妇囚夫 2024-12-14 06:42:45

让我们尝试更简单的例子 - 只计算第 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.

这个例子展示了过程式语言的特征:

  • 有一些子例程(在本例中是函数)
  • 变量可能被多次赋值( := 运算符)
  • 有循环(<在这种情况下, for 运算符)
  • 语言是命令式的,即我们告诉计算机按什么顺序做什么

第二,面向对象(在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)

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

这个例子显示:

  • 类及其实例化(创建实例)
  • 类有自己的内存部分,自己的状态(self 及其成员)
  • 语言是命令式的,即我们告诉计算机按什么顺序做什么

不是已显示,但我们可以例如从返回某个序列的第 n 个成员的抽象类派生该类。通过子类化,我们得到定义斐波那契数列的类,序列 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 需要
  • 声明式风格 - 我们不定义计算 ma​​in 函数值的步骤顺序:给定函数,编译器/解释器/运行时会自行计算出这一点定义。我们告诉计算机我们想要得到什么,而不是做什么。
  • 懒惰评价。如果 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) - 即第一个斐波那契数为 1,第二个斐波那契数为 1)以及推断其他谓词的规则(Y 是第 X 个斐波那契数是 Y 是 a X-1 个斐波那契数和 X-2 个斐波那契数之和),Prolog 推断有问题的谓词。实际上可能有不止 1 个答案!
  • 没有输入值和返回值 - 相反,我们定义“输入”和“输出”之间的关系。

该程序还可用于找出斐波那契数 8 位于序列中的第 6 位:

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

Let's try simpler example - just calculating n-th Fibonacci number.

First, procedural (in 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.

This example shows features of procedural languages:

  • There are some subroutines (function in this case)
  • Variables are assigned value probably multiple times ( := operator)
  • There are cycles (for operator in this case)
  • Language is imperative, i.e. we are telling computer what to do in what order

Second, object oriented (in 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)

Actually the problem is not worth creating a class, so I added caching of already calculated results.

This example shows:

  • class and its instantiation (creating instance)
  • class has own section of memory, own state (self and its members)
  • Language is imperative, i.e. we are telling computer what to do in what order

Not shown but we can e.g. descend this class from abstract class returning n-th member of some sequence. By subslassing we get class defining Fibonacci sequence, sequence 1,2,3..., sequence 1,4,9,16,... etc.

Third, in functional style (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)

Following features of a functional programming paradigm are demonstrated:

  • there is no state, no variables - just functions defined
  • there are no cycles - only recursion
  • pattern matching: we separately defined "fib 0", "fib 1" and "fib n" for rest of numbers, no constructs like if were needed
  • declarative style - we don't define the order of steps to calculate main function value: the compiler/interpreter/runtime figures this out by itself, given the function definitions. We tell the computer what we want to get, not what to do.
  • Lazy evaluation. If main was calling only "fib 2" then "fib n" was not called because functions are evaluated only when their result is needed to be passed as parameter to other functions.

But the main feature of functional languages is that functions are first class objects.
This can be demonstrated by other implementation of fib:

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

Here we are passing fibs function as parameter to zipWith function.
This example also demonstrates lazy evaluation: "infinite" list is computed only to extent it is needed for other functions.

By the way, functional does not necessary mean not object oriented. An example of programming language that is both functional and object oriented is 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.

Following features of logic programming style can be seen:

  • Language is declarative. As in functional style, we define things and not telling in what order to do them.
  • But the difference with functional style is that we define predicates, not functions. In this case, predicate fib(X, Y) means "X-th Fibonacci number is Y". Given some known predicates (fib(1, 1) and fib(2, 1) - i.e. first Fibonacci number is 1 and second Fibonacci number is 1) and rules to infer other predicates (Y is X-th Fibonacci number is Y is a sum of X-1th Fibonacci number and X-2th Fibonacci number), Prolog infers predicates in question. Actually there could be more than 1 answer!
  • There is no input values and return value - instead of this we define a relation between "input" and "output".

This program could also be used to find out that Fibonacci number 8 is at 6th position in the sequence:

?- between(0,inf,X), fib(X,8).
X = 6 .
绻影浮沉 2024-12-14 06:42:45

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

(它具有我自己的可怕的设计99 语言。)

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

(It features my own horribly contrived 99 language.)

送你一个梦 2024-12-14 06:42:45

欧拉项目问题 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);
}

编写的非常低效的版本

(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))))

这是用 MIT Scheme Prolog : 摘自此处,由 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.

Project Euler Problem number 2: http://projecteuler.net/problem=2

Haskell (functional/logic):

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 (procedural/imperative):

#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);
}

And here is a very inefficient version written in 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.
萌︼了一个春 2024-12-14 06:42:45

嗯,它非常简单的

  1. 程序、功能逻辑
    假设你想计算一些东西(这就是计算机所做的)

    1. 将问题分解为函数 f1,f2,f3...
      现在,如果您查看问题,您会发现它分为函数..但是必须有一个起点(从您开始计算的位置)和终点(您结束计算的位置),并且它们之间是函数(f1 ,f2,f3)。
      因此,您真正所做的不是编写一个大函数(F)来完成所有事情并且很长,而是将其分解为更小的部分(这称为重构)。理解一个 150 行长的函数很无聊。当你读到行尾时,你会忘记你是从哪里开始的,因此我们将它们分开。
      现在我们如何进行计算 --->
      我们创建一个函数,例如compute()(这称为facade),它将按所需顺序调用其余函数(f1,f2,f3 ...)并返回结果。
      现在明白了这一点:
      如果我们编写一个函数,该函数大约需要 150 行(复杂性会增加)。
      假设我们将其分解为 3 个函数,并假设每个函数有 50 行(可管理).. 由于 3 个函数的行数之和仍然是 150 行,我们如何降低复杂性:D 。函数名称降低了复杂性..它清楚地说明了函数的作用..这意味着查看名称您可以了解函数的作用。

OO编程逻辑:
现在功能分散在功能逻辑中..当我们将所有相关功能(行为)放在一个伞(类)中时,我们进一步降低了复杂性..如何..通过“类名称”。现在您可以说,我们不调用 f1,f2,f3..,而是调用 c1.f1(),c2.f2,c3.f3(),其中“c”表示类(域驱动设计)。

imp .. 无论您使用oops还是函数逻辑,总有一个计算的起点和终点...记住我谈到的compute()..问题是谁调用它..答案是你。一切OOP的逻辑或者过程逻辑都隐藏在它的背后(Service Facade)。

Well its very simple

  1. Procedural, Functional logic
    lets say you want to compute something (that's what computers do)

    1. break the problem into functions say f1,f2,f3....
      now if you look at the problem , you see it divided into functions .. but there has to be a starting point (from where you start the computation) and ending point (where you end the computation) and between them are the functions (f1,f2,f3).
      Thus what you have really done is instead of writing one big function (F) that does every thing and is very long you have break it into smaller parts (this is known as refactoring). Understanding a single function that is 150 line long is boring.. when you get to the end of line you will forget where you started thus we break things apart.
      now how we do the computation --- >
      We create a single function say compute() (this is known as facade ) that will call the remaining functions (f1,f2,f3...) in desired ordered and will return the result.
      Now understand this:
      If we had written a single function that would have been around 150 lines (complexity increases)..
      assume we broke down it into 3 functions and say each function is of 50 lines (manageable) .. how did we reduce complexity since the sum of lines of 3 functions is still 150 :D . the complexity is reduced by function name .. which clearly states what the function does.. it means looking at the name you can have a idea what the function does.

OO Programming logic:
Now functions are scattered in functional logic .. when we bring all the related functions (behavior) inside a single umbrella (Class) we have further reduced the complexity .. how .. by "Class name". Now you can say that instead of calling f1,f2,f3.. we call c1.f1(),c2.f2,c3.f3() where "c" denotes a class (domain driven design).

imp .. no matter whether you use oops or functional logic there is always a starting and ending point of computation ... remember the compute() i talked about.. and the question is who call's it .. and the answer is you .. Everything OOP's logic or procedural logic is hidden behind it (Service Facade)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文