1 / 16

Функциональное программирование

Функциональное программирование. Факультет инноваций и высоких технологий Московский физико-технический институт. Лекция 18. Замыкания, генераторы и отложенные вычисления. λ -исчисление как язык программирования. Синтаксис и семантика. Синтаксис языка был неформально определен раньше

haines
Download Presentation

Функциональное программирование

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Функциональное программирование Факультет инноваций и высоких технологий Московский физико-технический институт

  2. Лекция 18 Замыкания, генераторы и отложенные вычисления

  3. λ-исчисление как язык программирования

  4. Синтаксис и семантика • Синтаксис языка был неформально определен раньше • Набор правил, позволяющих транслировать синтаксические улучшения в чистое λ-исчисление • Семантика определяет результат применения программы (функции) ко входным данным • В силу т-мы Черча-Россера, имеет значение порядок редукции • С функциональном языке семантика во многом определяется стратегией редукции (ленивые vs. энергичные вычисления)

  5. Переопределение имени • (λx.(λz.((λx.z)4))(x+1))3→λx.((λz.z)(x+1))3 →(λx.(x+1))3→4 • При переопределении имени новое имя ссылается на новое значение, а все старые ссылки указывают на старые • Переопределение аналогично использованию связанной переменной с тем же именем let x = 3 in let z = x+1 in let x = 4 in z;;

  6. Замыкания • Определяя функцию со свободными переменными, мы также запоминаем состояние этих свободных переменных (контекст) • Пара из функции + контекста называется замыканием (closure, lexical closure) • Используется статическое связывание let x = 4;; let adder y = x+y;; adder 1;; let x = 3;; adder 1;; adder;; val it : (int -> int) = <fun:clo@0>

  7. mutable-переменные • В F# есть механизм, позволяющий осуществлять динамическое связывание(на момент вызова) let mutable x = 4;; let adder y = x+y;; adder 1;; x <- 3;; adder 1;; let x = 4;; let adder y = x+y;; adder 1;; let x = 3;; adder 1;; • В некоторых других языках (ранние версии ЛИСПа) по умолчанию применяется динамическое связывание ввиду его простоты; замыкания создаются в явном виде.

  8. Замыкания как объекты • Замыкание может возвращаться функцией и применяться к аргументу let def_adder n = fun x -> x+n;; let add5 = def_adder 5;; add5 5;; • Замыкание представляет собой результат частичного применения функции (partial evaluation)

  9. Частичное применение • Рассмотрим функцию Аккермана let rec A m n = if m=0 then n+1 else if n=0 then A (m-1) 1 else A (m-1) (A m (n-1));; • Частичное применение: let A3 = A 3;; • Замыкания – это один из способов частичного применения • Возможна оптимизация частичного применения – в этом случае функция заменяется семейством примитивно-рекурсивных функций A0,A1,A2,A3

  10. Специализация • Программа P: I → O • P : Ist → Idyn → O • Специализированная программа Psp = P ist : Idyn → O • Futamura Projection: • Interpreter : Source → Input → Output • Compiled = (Interpreter Source): Input → Output • Суперкомпиляция

  11. Генераторы и объекты • Генератор может быть реализован как closure с mutable (или динамически связываемым) полем • Closure также может применяться для инкапсуляции данных внутри объекта с несколькими функциями доступа Генератор – это функция, которая может производить последовательность значений, возможно бесконечную

  12. Генератор • В F# нельзя напрямую включать mutable-объекты в closure, поэтому приходится использовать immutable запись с mutable-полем type cell = { mutable content : int };; let new_counter n = let x = { content = n } in fun () -> (x.content <- x.content+1; x.content);; let cnt = new_counter 0;; cnt();; 1 cnt();; 2

  13. Ссылочные объекты • Для таких целей F# включает в себя предопределенный тип объектов ref let new_counter n = let x = ref n in fun () -> (x := !x+1; !x);;

  14. Генерализация генератора let new_generator fgen init = let x = ref init in fun () -> (x:=fgen !x; !x);; let fibgen = new_generator (fun (u,v) -> (u+v,u)) (1,1);;

  15. Генераторы и отложенные вычисления • В примере выше мы определили бесконечную последовательность чисел Фибоначчи • С ней можно производить вычисления, записав функциональное выражение в терминах обработки бесконечной последовательности let map f gen = let g = gen in fun () -> f (g());; let rec repeat cond gen = let x = gen() in if cond x then x else repeat cond gen;; let fgen = map (fun (u,v) -> u) fibgen;; repeat (fun x -> x%32) fgen;;

  16. Отложенные вычисления 2 • Мы можем получить по требованию столько членов последовательности, сколько нужно • Программа для решения задачи выглядит (почти) также, как и при использовании списков • Такие вычисления называются также поточными let filter cond gen = let g = gen in fun () -> repeat cond g;; let rec take n gen = if n=0 then [] else gen()::take (n-1) gen;; take 10 (filter (fun x -> x%3=0) fgen);;

More Related