Ответ 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 .