Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
розділ_1_28_08_15.doc
Скачиваний:
2
Добавлен:
01.07.2025
Размер:
2.39 Mб
Скачать

3.5. Функціональне програмування

Функціональний стиль програмування оснований на використанні тільки процедур-функцій. Роль змінних виконують параметри функцій. Присвоєння значень проходить тільки при визначенні (заданні) аргументів при звертанні до функцій. Послідовна композиція операторів замінюється покроковим обчисленням аргументів при виклику функції, умовна композиція операторів – такою ж композицією виразів, циклічна композиція – рекурсією.

Подумайте про архітектурні концепції розглянутих нами типів обчислювачів та їх можливості по реалізації функціонального стилю!!!!!

Може здатися, що арсенал таких засобів програмування досить бідний. Але це далеко не так!

Програми, написані функціональною мовою програмування (ФМП), традиційно є коротшими, нагляднішими і простішими для розуміння. До того ж вони є і надійнішими – «змінна» (новий екземпляр параметра функції) створюється тільки в момент присвоєння їй значення і не змінює його за весь час свого існування. Використання рекурсії при виклику функції добре співвідноситься з рекурсивним стилем опису типів значень і таких конструкцій, як виразів, зокрема – звернення до функції (вираз будується за допомогою композиції звертань до функцій-операцій).

В якості прикладу ФМП приведемо лісповське визначення рекурсивної функції append, яка вставляє в початок списку У (її другого параметру) всі елементи списку Х, зберігаючи їх порядок:

(define

append (lambda (X Y)

(cond (( NULL X) Y)

(T (cons (car X) (append (cdr X) Y))

)

)

)

)

Узагальнимо приведені рішення для функціональної парадигми

Дані тут представляються як функціональні вирази, а алгоритми - як системи функціональних рівнянь. Кожній програмі відповідає часткова функція чи множина функцій, що складають найменший розв’язок канонічної системи функціональних рівнянь, тобто системи вигляду

(x) = (f,x),i= 1,2 ,...,m,

де х = ( ),f = ( ).

Існує велика кількість функціональних мов програмування, починаючи з мови LISP та її нащадків і до сучасних мов, таких як SHEMA і ML. Для функціональних програм існує значно більше стратегій обчислень, ніж для процедурних. Добре відомі відмінності між такими стратегіями як “виклик за іменем” і “виклик за значенням”, паралельна і послідовна підстановки і іншими, що використовуються при виконанні функціональних програм. Але у всіх випадках елементарним кроком обчислень є підстановка функціонального означення і спрощення виразів. До того ж, як тільки обчислення закінчуються, то результат визначений однозначно. Іншими словами, стратегія лише визначає час, необхідний на обчислення, і як ці обчислення проводяться, але не остаточний результат.

Абстрактна семантика функціональних програм.

Якщо

= (f,x),

де х = ( ),f = ( ),i = 1,2,..., m – функціональна програма, то (f,x), називається функціональним виразом, тобто є виразом, побудованим із констант, змінних і символів функцій, що визначаються, і символів раніше побудованих функцій. Отже, на функціональну програму можна дивитися як на функціональне рівняння.

Денотаційна семантика. Нехай D, як і раніше, є область даних для змінних програм. Тоді : Dn D. Слід зазначити, що коли у функціональному рівнянні розглядати лише повністю визначені функції, то розв’язку може й не існувати. Якщо ж припустити, що функції часткові, то розв’язок існує завжди, але цей розв’язок може бути не єдиний.

Приклад 3.1. Нехай програма Р маг вигляд

F(x, у) = if х = у then у + 1 else F(х, F(x -1, у + 1)).

Функції

(x, у) = if х = у then у + 1 else x + 1;

(х,у) = if х ≥ 1 then х + 1 else у - 1;

(x, у) = if x ≥ у & ((x - y)mod 2 = 0) then у + 1 else ┴,

де ┴ - символ невизначеності, є розв’язком програми-рівняння Р. Це означає, що коли всі входження функції F в програмі замінити на функцію fі , i = 1,2,3, то зліва і справа від знака рівності будуть стояти однакові функції, тобто

(x, у) = if х = у then у + 1 else (x, (x - 1,у + 1)).

Дійсно, розглянемо, наприклад, функцію . Маємо

(x, у) = if х = у then у + 1 else (x, (x - 1 ,у+ 1));

(х, (x - 1,y + 1)) = if х = (х - 1,y + 1) then (x - 1,у + 1) + 1 else х+ 1; (x - 1, у + 1) = if х - 1 = у + 1 then у + 2 else х.

Розглянемо два випадки:

  1. х-1 = у+1 (x - 1,у + 1) + 2 ∧ х = у + 2;

  2. х – 1 ≠ у + 1 (x - 1, у + 1) = х.

В обох випадках отримуємо

(x - 1, у + 1) = if x - 1 = у + 1 then у+ 2 else х = х;

(x, (x - 1,y + 1) = if x = (x - 1,у + 1)

then (х -1, у + 1) + 1 else х + 1 = х + 1.

Отже, остаточно одержуємо

(х, у) = if х = у then у + 1 else х + 1.

Перевірку того, що решта функцій теж є нерухомими точками програми Р про­понується виконати як корисну вправу.

Будемо говорити, що функції = 1,2,3, - це нерухомі точки функціональної програми Р.

Таким чином, всі три функції є розв’язком функціонального рівняння, яке ви­значає програму Р, і виникає питання: а яку з цих функцій потрібно розглядати як результат виконання програми Р?

Якщо порівнювати між собою функції то виявляється, що коли визна­чена функція , то визначені і функції , але не навпаки.

В цьому випадку говорять, що функція менш визначена або рівна, ніж функції і позначають це так:

.

Неважко переконатися в тому, що відношення є відношенням часткового порядку і, отже, можна говорити, зокрема, про мінімальні і найменші елементи на множині функцій відносно цього порядку.

Можна показати, що розглянута вище функція відносно даного порядку менша не тільки по відношенню до функцій а й по відношенню до будь-якої нерухомої точки програми Р. Більше того, можна показати, що є єдиною функцією з такою властивістю і тому (х,у) називають найменшою нерухомою точкою (ННТ) для програми Р.

Розширимо відношення на вектор-функції:

f = ( ) f ' = ( ) , .

Найбільш важливою властивістю функціональних програм є властивість, яку висвітлює відома теорема Кліпі [15].

Теорема 3.2. Будь-яка функціональна програма Р має єдину найменшу нерухому точку .

Операційна семантика. Нехай Р = F(f,x) = Е - функціональна програма. Вираз

Е[ := ,..., хп := Еп]

означає одночасну підстановку в функціональний вираз Е замість змінних виразів ,і = 1,2,... ,п. Наприклад, якщо Р- програма з попереднього прикладу, то

Е = F(x, у) і

Е[х := 1, у := 2] =if (1 = 2) then 2 + 1 else F(1, F(1-1,2 + 1)).

Якщо одержаний вираз спростити, то

Е[х := 1 := 2] = F(1,F(0,3)).

Позначимо функцію спрощення функціональних виразів через simp.

Станом обчислень функціональної програми називається функціональний вираз, а відношення переходів на функціональних виразах задається за допомогою такого правила:

.

Приклад 3.2. Якщо F(x,y) - функція з попереднього прикладу, то

F(3,1) F(З, F(2,2)) F(3,3) 4,

оскільки

F(3, F(2,2)) = if (3 = F(2,2)) thеп 4 else F(2, F(2,2) + 1));

F(2,2) = if (2 = 2) then (2+1) else F(2, F(1, 3)) = (2 + 1) = 3.

Тоді F(3,F(2,2)) = 4.

Як випливає з наведених прикладів, значенням функціональної програми Р є або константний вираз А, тобто деякий елемент області даних D, одержаний в результаті спрощення (наприклад, А — 4 в розглянутому вище прикладі), або невизначений елемент ┴.

Зв’язок між денотаційною і операційною семантикою встанов­лює таке твердження.

Теорема 3.3. Нехай , ,..., Ап, В - деякі константні вира­зи такі, що simp( ) = simp(B) = b, і = 1,2, ...,n. Тоді ]р( , , … п) ( , А2,..., ) * B, де ]р - зна­чення функції , яка визначається програмою Р.

Доведення пропонується як вправа.

Нижче наводиться функціональна програма обчислення НСД двох натуральних чисел.

НСД(x,y) = if (х > у) then НСД(х - у, у) else

if (х < у) then НСД(x, у - х) else х.

Функціональні програми мають одну дуже корисну властивість порівняно з процедурними програмами: функціональні програми не мають побічних ефектів, пов’язаних з використанням глобальних змінних, в той час як процедурні програми схильні до такого роду ефектів. Побічні ефекти часто приводили до того, що великі затратні розробки зазнавали краху, тому що помилки, які виникають з цих причин, не мають стійкого характеру (їх нази­вають “мерехтливими” помилками). Ці помилки проявляються не завжди при роботі програми і тому їх дуже важко ідентифікувати і виправити.

Розглянемо програму (мова програмування - ПАСКАЛЬ), яка має побічний ефект. Наведена нижче програма обчислює значення суми f(1) + f(2), де f - деяка процедура-функція.

program example(output);

var flag : bool;

function f(n : integer) : integer;

begin

if flag then f := n else f := 2n;

flag := not flag

end;

begin

flag := true;

writeln (f(1) + f(2));

writeln (/(2) + /(1))

end;

Результат роботи програми буде для першого виразу 5, а для другого виразу - 4. Оскільки операція додавання комутативна в множині натуральних чисел, то результати повинні були б збігатися. Причина криється в змінній flag, яка є глобальною і змінює значення функції f.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]