Давайте попробуем более простой пример - просто вычисление 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)
На самом деле проблема не стоит создавать класс, поэтому я добавил кеширование уже рассчитанных результатов.
В этом примере показано:
- class иего экземпляр (создание экземпляра)
- класс имеет собственный раздел памяти, собственное состояние ( self и его члены)
- Язык является обязательным, то есть мы говорим компьютеру, чтоделать в каком порядке
Не показано, но мы cНапример, потомок этого класса из абстрактного класса, возвращающий 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 вызывал только «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 .