Опубликован: 21.08.2007 | Уровень: для всех | Доступ: платный
Лекция 7:

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

< Лекция 6 || Лекция 7: 1234 || Лекция 8 >
  1. Определения могут быть рекурсивными.
    (DEFUN премьер (x)(COND ((ATOM x) x)
                                           (T (премьер (CAR x ))) ))
    Пример 7.2. Новая функция "премьер" выбирает первый атом из любого данного
  2. Собственно механизм связывания пока определен не был.

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

    Такая единая структура данных оказалась вполне достаточной для представления сколь угодно сложных программ.

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

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

    Пример 7.7. Определить функцию покомпонентной обработки двух списков с помощью заданной функции fn:

    (defun map-comp (fn al vl); fn покомпонентно применить
            ; к соотвественным элементам AL и VL
         (cond
                 (xl (cons (funcall fn (car al) (car vl))         
            ; Вызов данного FN как функции от элементов двух списков
                           (map-comp (cdr al) (cdr vl))
    )    )  )   )

    Теперь покомпонентные действия над векторами, представленными с помощью списков, полностью в наших руках. Вот списки и сумм, и произведений, и пар, и результатов проверки на совпадение:

    (map-comp #'+ '(1 2 3) '(4 6 9))      
                                            ; = (5 8 12 ) Суммы
    (map-comp #'* '(1 2 3) '(4 6 9))    
                                            ; = (4 12 27 ) Произведения
    (map-comp #'cons '(1 2 3) '(4 6 9)) 
                                            ; = ((1 . 4)(2 . 6)(3 . 9)) Пары
    (map-comp #'eq '(4 2 3 ) '(4 6 9))
                                           ; = (T NIL NIL ) Сравнения

    Достаточно уяснить, что надо делать с элементами списка, остальное довершит функционал map-comp, отображающий этот список в список результатов заданной функции.

    Пример 7.8. Для заданного списка вычислим ряд его атрибутов, а именно - длина, первый элемент, остальные элементы списка без первого.

    (defun mapf (fl el)
         (cond                        ; Пока первый аргумент не пуст,
            (fl (cons (funcall (car fl) el ) 
                                     ; применяем очередную функцию
                                     ; ко второму аргументу
    
                      (mapf (cdr fl) el)  
                         ; и переходим к остальным функциям,
    )    )  )   )        ; собирая их результаты в общий список
    
    (mapf '(length car cdr) '(a b c d ))      ; = (4 a (b c d ))

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

  4. Возможны средства управления областями действия имен и их определений.

    На практике сложилась традиция в систему функционального программирования включать специальные функции, обеспечивающие иерархию контекстов, в которых переменные обладают определенным значением. Для Clisp это LET и LET* [ [ 73 ] ].

    Let сопоставляет локальным переменным независимые выражения. С ее помощью можно вынести из сложного определения любые совпадающие подвыражения. Пример:

    (defun UNION- (x y)   (let   ( (a-x (CAR x))
                                                 (d-x (CDR x))   )
           
              (COND  ((NULL x)     y)
                            ((MEMBER a-x y)   (UNION d-x y)  )
                            (T     (CONS a-x (UNION d-x y)) )   )     ))

    Let -1Примечание. Эквивалентность с точностью до побочного эффекта сопоставляет локальным переменным взаимосвязанные выражения. Она позволяет дозировать сложность именуемых подвыражений. Пример:

    (defun ( (member (a x)  (let* (   (n-x (null x))
                                    (a-x (car x))
                                    (d-x (cdr x)) 
                                    (e-car (eq a a-x))   )
    
              (COND (N-X  Nil)
                          (E-CAR T) 
                          (T (MEMBER A D-X)))  )        ))

    Labels - позволяет из списка определений функций формировать контекст, в котором вычисляются выражения.

    Flet - специальная функция, позволяющая вводить локальные нерекурсивные функции.

    defun - позволяет вводить новые определения на текущем уровне.

    Лисп хорошо приспособлен к оптимизации программ. Любые совпадающие подвыражения можно локализовать и вынести за скобки, как можно заметить по передаче значения "(ASSOC e al )" в нижеприведенном определении интерпретатора с явным выделением зависимости от набора встроенных функций. Определения функций хранятся в ассоциативном списке подобно значениям переменных.

    В качестве примера повышения гибкости определений приведено упрощенное определение Лисп-интерпретатора на Лиспе, полученное из М-выражения, приведенного Дж. Мак-Карти в описании Lisp 1.5 [ [ 75 ] ]. Уменьшена диагностичность, нет предвычислений и формы Prog.

    В сравнении с определением в "Многоликое программирование" уточнена работа с функциональными аргументами:

    (DEFUN EVAL  (e al )
          (COND         ((EQ e NIL ) NIL )   
    ((ATOM e ) ((LAMBDA (v )
                          (COND (v (CDR v ) )   
                                (T (ERROR 'undefvalue )) )
                          ) (ASSOC e al ) )
                       )
    
            ((EQ (CAR e) 'QUOTE )    (CAR (CDR e )) )
            ((EQ (CAR e) 'FUNCTION ) (LIST 'FUNARG (CADR fn ) al ) )
            ((EQ (CAR e) 'COND  )    (EVCON (CDR e ) al ) ) 
            (T (apply (CAR e) (evlis (CDR e) al ) al ) )
    )  )  
    (DEFUN APPLY (fn args al )
          (COND
    
            ((EQ e NIL ) NIL )   
            ((ATOM fn )
                 (COND 
    
                     ((MEMBER fn '(CAR CDR CONS ATOM EQ )) (SUBR fn agrs al ))
                     (T (APPLY (EVAL fn al ) args al ))
            )    )
    
            ((EQ (CAR fn ) 'LABEL )
                    (APPLY (CADDR fn )
                           args
                           (CONS (CONS (CADR fn ) (CADDR fn )) 
                                  al ) ) )
    
    ((EQ (CAR fn ) 'FUNARG )
                 (APPLY (CDR  fn ) args (CADDR  fn))
            )
            ((EQ (CAR fn ) 'LAMBDA )
                              (EVAL (CADDR fn )
                                    (APPEND (PAIR (CADR fn ) args ) al ))
            (T (APPLY (EVAL fn al ) args al ))
     )  )
    7.1.

    Определения assoc, append, pair, list - стандартны.

    SUBR - Функция, вызывающая примитивы, реализованные другими, обычно низкоуровневыми, средствами.

    ERROR - Функция, выдающая сообщения об ошибках и сведения о контексте вычислений, способствующие поиску источника ошибки.

< Лекция 6 || Лекция 7: 1234 || Лекция 8 >
Федор Антонов
Федор Антонов

Здравствуйте!

Записался на ваш курс, но не понимаю как произвести оплату.

Надо ли писать заявление и, если да, то куда отправлять?

как я получу диплом о профессиональной переподготовке?

Илья Ардов
Илья Ардов

Добрый день!

Я записан на программу. Куда высылать договор и диплом?

Данила Некрасов
Данила Некрасов
Россия, Пермь, ПНИПУ
Сергей Федоров
Сергей Федоров
Россия