Можете ли вы представить один и тот же пример с использованием языков программирования процедур, функциональных, логических и OO?

Кто-нибудь может предоставить мне пример, который поможет мне разобраться в процедурных, функциональных, логических и объектно-ориентированных моделях программирования бок о бок, используя почти такую ​​же примерную проблему.

Пожалуйста, дайте мне примерные фрагменты кода той же самой проблемы с использованием языков программирования процедур, функциональных, логических и OO.

Ответ 1

Попробуем более простой пример - просто вычисляем n-й номер Фибоначчи.

Во-первых, процедурный (в Паскале):

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)

На самом деле проблема не стоит создавать класс, поэтому я добавил кэширование уже вычисленных результатов.

В этом примере показано:

  • и его создание (создание экземпляра)
  • класс имеет собственный раздел памяти, собственное состояние ( 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" для остальной части чисел, не нужны конструкции типа , если
  • декларативный стиль - мы не определяем порядок шагов для вычисления значения функции main: компилятор/интерпретатор/время выполнения вычисляет это сам по себе, учитывая определения функций. Мы говорим компьютеру, что хотим, а не что делать.
  • ленивая оценка. Если main вызывал только "fib 2", тогда "fib n" не вызывался, потому что функции оценивались только тогда, когда их результат необходимо передать как параметр другим функциям.

Но основной особенностью функциональных языков является то, что функции являются объектами первого класса. Это может быть продемонстрировано другой реализацией fib:

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

Здесь мы передаем функцию fibs как параметр функции zipWith. Этот пример также демонстрирует ленивую оценку: "бесконечный" список вычисляется только в той степени, в которой он необходим для других функций.

Кстати, функционал не нужен, а не объектно-ориентированный. Примером языка программирования, который является функциональным и объектно-ориентированным, является Scala.

Пролог:

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 сумма X-1-го числа Фибоначчи и X-2-го числа Фибоначчи), Пролог преследует предикаты. На самом деле может быть более 1 ответа!
  • Нет входных значений и возвращаемого значения - вместо этого мы определяем связь между "входом" и "выводом".

Эта программа также может быть использована для выяснения того, что число Фибоначчи 8 находится на 6-й позиции в последовательности:

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

Ответ 3

Project Euler Проблема номер 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))))

Пролог: Возьмите из этого здесь, отправленный 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.

Ответ 4

Ну его очень просто

  • Процедурная, функциональная логика скажем, вы хотите что-то вычислить (что делают компьютеры)
    • Разделите проблему на функции, скажем, f1, f2, f3.... теперь, если вы посмотрите на проблему, вы увидите, что она разделена на функции.. но должна быть начальная точка (с которой вы начинаете вычисление) и конечную точку (где вы заканчиваете вычисление), а между ними - функции (f1, f2, f3). Таким образом, то, что вы действительно сделали, вместо того, чтобы писать одну большую функцию (F), которая делает все, и очень долго, вы разбили ее на более мелкие части (это называется рефакторинг). Понимание единственной функции, которая составляет 150 строк, скучно. Когда вы дойдете до конца строки, вы забудете, где вы начали, и мы разобьем вещи. теперь, как мы делаем вычисление --- > Мы создаем единую функцию say compute() (это называется фасад), которая будет вызывать оставшиеся функции (f1, f2, f3...) в желаемом упорядоченном порядке и вернет результат. Теперь поймите это: Если бы мы написали одну функцию, которая составляла бы около 150 строк (увеличивается сложность). предположим, мы сломали его на 3 функции и сказали, что каждая функция имеет 50 строк (управляемых).. как мы уменьшили сложность, так как сумма строк из 3 функций все еще равна 150: D. сложность уменьшается по имени функции.., в которой четко указано, что делает функция. Это означает, что вы смотрите на имя, которое может иметь представление о том, что делает функция.

Логика программирования OO:
Теперь функции разбросаны по функциональной логике. Когда мы приводим все связанные функции (поведение) внутри одного зонтика (класса), мы еще больше уменьшаем сложность.. как.. по "Название класса". Теперь вы можете сказать, что вместо вызова f1, f2, f3.. мы вызываем c1.f1(), c2.f2, c3.f3(), где "c" обозначает класс (проект, управляемый доменом).

imp.. независимо от того, используете ли вы oops или функциональную логику, всегда есть начальная и конечная точка вычисления... помните, что вычислял(), о котором я говорил.. и вопрос в том, кто его называет.. и ответ это вы.. Все логика ООП или процедурная логика скрыты за ней (Service Facade)