Функциональное программирование
DESCRIPTION
Функциональное программирование. Факультет инноваций и высоких технологий Московский физико-технический институт. Лекция 6. Сопоставление с образцом. Рекурсия. Циклы. Сопоставление с образцом. type document = SSN of int | Passport of string;; type personx = string * int * document;; - PowerPoint PPT PresentationTRANSCRIPT
Сошников Дмитрий Валерьевич
к.ф.-м.н., доцент[email protected]
Факультет инноваций и высоких технологий
Московский физико-технический институт
Лекция 6
Сопоставление с образцом. Рекурсия. Циклы
3
©20
08 С
ошни
ков
Д.В
.
type document = SSN of int | Passport of string;;type personx = string * int * document;;let vasyax = ("Vasya",14,SSN 1234);;
let (_,_,doc)= vasyax;;
match vasyax with _,_,SSN x -> print_int x| _,_,Passport s -> print_string s;;
let print_doc = function _,_,SSN x -> print_int x| _,_,Passport s -> print_string sin print_doc vasyax;;
4
©20
08 С
ошни
ков
Д.В
.
match expr with pattern1 [when cond1] -> expr1| pattern2 [when cond2] -> expr1| …;;
match D with _ when D>0 -> “Два корня”| _ when D=0 -> “Один корень”| _ -> “Нет корней”;;
match root with Some(t) -> printf “Корень: %d\n” t| None -> printf “Корней нет\n”
5
©20
08 С
ошни
ков
Д.В
.
Конструкции для определения лямбда-выражений:
fun Поддерживает несколько аргументов в
каррированной форме: fun x y -> … Не поддерживает pattern matching
function Поддерживает только один аргумент
(возможно, tuple) Поддерживает pattern matching с
несколькими вариантами описания
6
©20
08 С
ошни
ков
Д.В
.
let rec fact1 = function 1 -> 1| x -> x*fact1(x-1);;
let rec fact2 x = match x with 1 -> 1 | x -> x*fact2(x-1);;
// это уже не pattern matchinglet rec fact3 x = if x = 1 then 1 else x * fact3(x-1);;
7
©20
08 С
ошни
ков
Д.В
.
Определения в F# могут быть рекурсивными, т.е. в рамках «let rec»- определения возможно использовать определяемую функцию
В λ-исчислении напрямую понятия рекурсии нет – мы позднее узнаем, как определяется рекурсия в λ-исчислении
Рекурсия – зачастую единственный способ совершения итеративных действий
8
©20
08 С
ошни
ков
Д.В
.
let rec print_n a b = if a>=b then print_int b else begin print_int a; print_n (a+1) b end;;
print_n 1 10;;
Напечатать числа от a до b
9
©20
08 С
ошни
ков
Д.В
.
Группировка по блокам регулируется отступами
Можно опускать некоторые элементы синтаксиса, например, in в let … in …
#lightlet rec print_n a b = if a>=b then print_int b else print_int a print_n (a+1) b;;print_n 1 10;;
10
©20
08 С
ошни
ков
Д.В
.
print_n – типичная реализация цикла со счетчиком
Необходимо выполнить какое-то действие несколько раз, при этом переменная-счетчик меняется от a до b
Действие можно задать функцией int → unit
Функционал – функция, принимающая или возвращающая функцию
11
©20
08 С
ошни
ков
Д.В
.
В F# (но не в других функц.языках) имеется также встроенная конструкция цикла for:
let rec forl a b f = if a>=b then f b else f a forl (a+1) b f;;
forl 1 10 (fun i -> print_int i);;
for i=1 to 10 do print_int i;;for i in 1..10 do print_int i;;
12
©20
08 С
ошни
ков
Д.В
.
fora a b i f = f(f(…f(i,b),…),a+1,a)let rec fora a b i f = if a>=b then i else f (fora (a+1) b i f) a;;
fora 1 10 (fun a i -> a+i);;
Посчитаем сумму чисел от 1 до 10:
А сумму 1+...+x^n/n!
13
©20
08 С
ошни
ков
Д.В
.
(* Следующее за 10 простое число *)whilel 10 (fun i -> not is_prime i);;
(* sin(sin(sin(x))) *)let sin3 x = reccall 3 sin x;;
let sin3 = reccall 3 sin;;
14
©20
08 С
ошни
ков
Д.В
.
Линейная Вызов функции генерирует не
более одного рекурсивного вызова
Нелинейная (плохая)let rec fib a = if a<2 then 1 else fib (a-1) + fib (a-2);;
fib 4fib 4
fib 3fib 3 fib 2fib 2
fib 2fib 2 fib 1fib 1 fib 1fib 1 fib 0fib 0
fact 3fact 3
fact 3fact 3
fact 1fact 1
15
©20
08 С
ошни
ков
Д.В
.
Прямая Косвенная
A вызывает B; B вызывает C; С вызывает A Часто встречается при построении
компиляторов методом рекурсивного спуска
let rec A = … B … and B = … C … and C = … A …;;