Опубликован: 21.08.2007 | Доступ: свободный | Студентов: 1416 / 66 | Оценка: 4.23 / 3.74 | Длительность: 15:37:00
Лекция 12:

Функции высших порядков

< Лекция 11 || Лекция 12: 12 || Лекция 13 >
Аннотация: В данной лекции рассматривается аппарат функций высших порядков при организации высококвалифицированных процессов информационной обработки, использующей формализацию и спецификацию данных, таких как синтаксический анализ, кодогенерация, конструирование интерпретаторов и компиляторов по формальному определению реализуемого языка – так называемые синтаксически управляемые методы информационной обработки. Приведены примеры программного кода с использованием функций высшего порядка

Рассматривается аппарат функций высших порядков при организации высококвалифицированных процессов информационной обработки, использующей формализацию и спецификацию данных, таких как синтаксический анализ, кодогенерация, конструирование интерпретаторов и компиляторов по формальному определению реализуемого языка - так называемые синтаксически управлямые методы информационной обработки [ [ 19 ] , [ 31 ] , [ 49 ] , [ 53 ] , [ 66 ] , [ 74 ] ].

Ранжирование функций

Применение функций высших порядков (ФВП) характерно при решении задач регулярной обработки формализованной информации. Подобные задачи возникают при реализации и настройке сложных информационных систем, таких как операционные системы, системы программирования, текстовые и графические процессоры, системы управления базами данных, поддержки проектов и т.п. Рассмотрим технику применения ФВП на примере функционалов языка Лисп.

Функции высших порядков используют другие функции в качестве аргументов или вырабатывают в качестве результатов.

(defun mul-N (N) #'(lambda (x) (* x N)))  
; конструктор семейства функций, множащих аргумент на N 

 (funcall (mul-N 25) 7)                                
; применение частной функции, умножающей на 25

Правильность выражений с такими функциями требует корректной подстановки параметров и учета ранга функции, определяющего возможность манипулирования функциональными значениями. Функции можно ранжировать на основе так называемых типовых выражений, представляющих области определения и значения функций. Задание типов данных может требоваться языком программирования или быть представимо в виде комментария. Методы таких представлений рассмотрены в курсе [ [ 23 ] , [ 8 ] ].

Например, можно ввести обозначения:

Atom - атомы,
  Number - число,
  List (X) - NIL или списки из элементов типа X,
  Bool - NIL или T,'
  Some - любой объект.

Типовые выражения для элементарных функций:

cons : (X List (X)) -> List (X)
car  : List (X) -> X
cdr  : List (X) -> List (X)
eq   : (Atom Atom) -> Bool
at    : Some -> Bool
       : (Atom -> T) & (List (X) -> NIL)
nl    : Some -> Bool
       : (NIL -> T) & (Atom \=NIL -> NIL) & (List (X)\=NIL -> NIL)

Таким же образом можно специфицировать интерпретатор:

eval  : (Some List( (Atom . Some ) )) -> Some
          |__ могут попасть неправильные выражения 

apply : (List(Some ) -> Some  List(Some ) List((Atom . Some))  ) -> Some

Отображающий функционал также может характеризоваться типовым выражением:

map-  : ( List(X)  (X->Y) ) -> List(Y)

(defun map- (x f) (cond (x (cons (funcall f (car x))
                                (map- (cdr x) f )))))
(map- '((1) (2) (3)) #'car )

Можно построить функцию, непосредственно преобразующую свой функциональный аргумент в новую функцию.

mapf  : List(X->Y) ->( List(X) -> List(Y))

(defun mapf (f)  #'(lambda (x)
     (cond (x (cons (funcall f (car x))
                    (funcall (mapf f ) (cdr x)) ))) ))
(funcall (mapf #'car ) '((1) (2) (3)) )

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

manyfun  : List(X->Y) -> (X -> List(Y)) 

 (defun manyfun (lf)  #'(lambda (x)
             (cond (lf (cons (funcall (car lf) x)
                (funcall (manyfun (cdr lf)) x) ))) ))
 (funcall (manyfun '(car cdr length)) '(1 f (2 T) (3 D e)) )

Таким образом можно как бы "просачивать" определения функций над простыми данными по структурам данных и тем самым распространять простые функции на сложные данные подобно матричной арифметике. Такой стиль работы характерен для теории комбинаторов и языка FORTH [ [ 3 ] ]. Похожие построения предлагаются Бэкусом в его программной статье о функциональном стиле программирования и в языке APL, ориентированном на обработку матриц [ [ 16 ] ].

Существует ряд языков функционального программирования, требующих или допускающих спецификацию объектов, что, кроме дисциплины программирования, дает средства для корректной работы с пакетами, сопряжения с модулями на других языках, оптимизирующих преобразований, распараллеливания и верификации программ (Sisal, ML и др.) [ [ 84 ] ].

Конструирование распознавателей

Результативность функций высших порядков Хендерсон показывает на модельной задаче построения распознавателя контекстно-свободного языка, подробно описанной в курсе [ [ 8 ] , [ 23 ] ]. В качестве примера такого языка рассмотрен синтаксис понятия "слог", образованный из гласных и согласных букв [ [ 23 ] ].

В результате достигнуто синтаксическое подобие определения грамматики и программы построенного распознавателя. Это значит, что определение можно автоматически отобразить в такой распознаватель. Отображение - функция высокого порядка, вырабатывающая в качестве результата распознаватель языка, порождаемого исходной грамматикой.

Таблица 12.1. Определение распознавателя языка, синтаксически подобное грамматики языка.
Грамматика
<слог>   ::=  <в-гр> <а-гр> 
                   | <а-гр> <в-гр> 
                   | <в-гр> <а-гр> <в-гр>
Распознаватель
(defun is-syllable (x )                                                                              
    (funcall (is-alt  (is-chain  #'is-b-gr  #'is-a-gr)                                          
                (is-alt  (is-chain #'is-a-gr #'is-b-gr)                                 
                          (is-chain #'is-b-gr (is-chain #'is-a-gr #'is-gr))   
		                      )      ) x ))
Вспомогательные функции
(defun is-alt (p q) #'(lambda (x) (cond ((funcall p x )T)            
                                              ((funcall q x) T)  (T Nil))))
(defun both (x y) (cond ( x y)(T Nil)) )    
(defun is-chain (p q) #'(lambda (x ) (cond ((null x) nil)        
                              ((both(funcall p x) (funcall q nil)) T)      
                              ((both(funcall p Nil) (funcall q x)) T)                                      
           ((both(funcall p (cons (car x)Nil)) (funcall q (cdr x)) ) T)      
           (T(funcall (is-chain (lambda(y) (funcall p(cons(car x)y)))          
                           (lambda(y)(funcall q y)) ) (cdr x) ))     )))

Преобразование определений

Конечно, построенное выше определение не отличается эффективностью. Обычно синтаксические формулы приводят к нормализованной форме, гарантирующей полезные свойства распознавателей и удобство их построения. Выбор нормализованной формы и процесс нормализации обосновывается доказательными построениями, на практике воспринимаемыми как эквивалентные преобразования. Преобразования формул - еще один интересный класс задач символьной обработки. Для демонстрации рассмотрим модель реализации функций свертки текстов. При подходящем выборе обозначений такие функции можно применять для преобразования синтаксических формул с целью приведения к нормализованной форме [ [ 8 ] ].

Пусть свертки системы текстов представлены в стиле самоописания подобно формам Бекуса-Наура списком вида:

(
(Тексты (Имя Вариант ...)...)               
 ; первое имя - обозначение системы текстов
; за ним следуют варианты поименованных текстов

(Вариант Элемент ...)                           
; Вариант представляет собой последовательность Элементов

(Элемент Имя Лексема (Варианты))  
; Элемент - это или Имя, или Лексема, или Варианты в скобках
)
< Лекция 11 || Лекция 12: 12 || Лекция 13 >
Дарья Федотова
Дарья Федотова
Сергей Березовский
Сергей Березовский

В рамках проф. переподготовки по программе "Программирование"

Есть курсы, которые я уже прошел. Но войдя в курс я вижу, что они не зачтены (Язык Ассемблера и архитектура ЭВМ, Программирование на С++ для профессионалов). Это как?

Наталья Алмаева
Наталья Алмаева
Россия
Сергей Кузнецов
Сергей Кузнецов
Россия