Обзор функциональных языков программирования

advertisement
Обзор функциональных языков
программирования
Lisp, Scheme, Miranda, Haskell,
Erlang, ML, Val, Sisal
Lisp
• Лисп (LISP, от англ. LISt Processing —
«обработка списков») — семейство языков
программирования, основанных на
представлении программы системой
линейных списков символов, которые притом
являются основной структурой данных языка.
• Лисп считается вторым после Фортрана
старейшим высокоуровневым языком
программирования.
Lisp
•
•
•
•
Common LISP — более навороченный
Scheme — более ясный и простой
AutoLISP – внутренний язык AutoCAD
Common Lisp Object System (CLOS) –
объектно-ориентированный Common Lisp
• MacLisp, Standard Lisp, SpiceLisp, S-1 Lisp,
ZetaLisp, Nil, InterLisp, Emojilisp
CLOS
Абстракции
Переменные экземпляра
Методы экземпляра
Переменные класса
Методы класса
Да
Да
Да
Да
Инкапсуляция
Переменных
Методов
Чтение, запись, доступ
Открытые
Модульность
Разновидности модулей
Пакет
Иерархии
Наследование
Шаблоны
Метаклассы
Сильная типизация
Полиморфизм
Множественное
Нет
Да
Возможна
Да (множественный)
Многозадачность
Долгоживущие объекты
Да
Нет
Типизация
Параллельность
Сохраняемость
Common Lisp
• CL-USER> (+ 2 3)
• 5
• CL-USER> "hello, world"
• "hello, world“
• CL-USER> (defun hello-world () (format t "hello,
world"))
• HELLO-WORLD
Common Lisp
• (defun verbose-sum (x y) "Sum any two
numbers after printing a message." (format t
"Summing ~d and ~d.~%" x y) (+ x y))
•
•
•
•
(defun foo (a b &optional c d) (list a b c d))
(foo 1 2) ==> (1 2 NIL NIL)
(foo 1 2 3) ==> (1 2 3 NIL)
(foo 1 2 3 4) ==> (1 2 3 4)
Common Lisp
• (defun format (stream string &rest values) ...) (defun +
(&rest numbers) ...)
•
•
•
•
•
•
•
•
(defun foo (&key a b c) (list a b c))
(foo) ==> (NIL NIL NIL)
(foo :a 1) ==> (1 NIL NIL)
(foo :b 1) ==> (NIL 1 NIL)
(foo :c 1) ==> (NIL NIL 1)
(foo :a 1 :c 3) ==> (1 NIL 3)
(foo :a 1 :b 2 :c 3) ==> (1 2 3)
(foo :a 1 :c 3 :b 2) ==> (1 2 3)
Common Lisp
•
((lambda (x y) (+ x y)) 2 3) ==> 5
•
(defun plot (fn min max step) (loop for i from min to max by step do (loop repeat
(funcall fn i) do (format t "*")) (format t "~%")))
(defun double (x) (* 2 x))
CL-USER> (plot #'double 0 10 1)
**
****
******
********
**********
************
**************
****************
******************
********************
NIL
•
•
•
•
•
•
•
•
•
•
•
•
•
Common Lisp
• (if (> 2 3) "Yup" "Nope") ==> "Nope"
• (if (> 2 3) "Yup") ==> NIL
• (if (> 3 2) "Yup" "Nope") ==> "Yup"
Clojure
(require '[clojure.test.check :as tc])
(require '[clojure.test.check.generators :as gen])
(require '[clojure.test.check.properties :as prop])
(def sort-idempotent-prop
(prop/for-all [v (gen/vector gen/int)]
(= (sort v) (sort (sort v)))))
(tc/quick-check 100 sort-idempotent-prop)
;; => {:result true, :num-tests 100, :seed 1382488326530}
Scheme
• При разработке Scheme упор был сделан на
элегантность и простоту языка.
• Философия языка подчёркнуто
минималистская.
• Его цель — не сваливать в кучу разные
полезные конструкции и средства, а
напротив — удалить слабости и
ограничения, вызывающие необходимость
добавления в язык новых возможностей.
Scheme примеры
•
•
•
•
•
Предикаты:
(number? 5)
(number? "foo")
(string? "foo")
По соглашению все предикаты
заканчиваются символом «?»
Scheme
• (equal? "foo" "bar")
• (eqv? 5 (+ 2 3))
• (eq? 'a 'A)
• Определение функции:
(define имя_функции (lambda
(список_аргументов) (реализация_функции))),
• Или более коротко:
(define (имя_функции аргументы)
(реализация_функции)).
Scheme
• Ввод-вывод
(write (+ (read) (read)))
• ;; факториал в (неэффективном) рекурсивном
стиле
(define (fact x)
(if (< x 3)
x
(* (fact (- x 1)) x)))
Miranda
• Чистый функциональный язык
программирования.
• Не содержит императивных конструкций
любого вида.
• Имеет строгую полиморфную систему
типов, поддерживает типы данных
пользователя.
• Как и язык ML преподаётся во многих
университетах
Miranda
•
•
•
•
•
•
•
Пример простой программы:
z = sq x / sq y
sq n = n * n
x=a+b
y=a-b
a = 10
b=5
Miranda
• week_days = ["Mon","Tue","Wed","Thur","Fri"]
• days = week_days ++ ["Sat","Sun"]
/*
• 0:[1,2,3] = [0,1,2,3]
• #days = 7
• days!0 = "Mon".
*/
Miranda
• fac n = product [1..n]
• result = sum [1,3..100]
Miranda
• quadsolve a b c
= error "complex roots",
= [-b/(2*a)],
= [-b/(2*a) + radix/(2*a),
-b/(2*a) - radix/(2*a)],
where
delta = b*b - 4*a*c
radix = sqrt delta
if delta<0
if delta=0
if delta>0
Miranda
• fib 0 = 0
• fib 1 = 1
• fib (n+2) = fib (n+1) + fib n
• sum [] = 0
• sum (a:x) = a + sum x
• product [] = 1
• product (a:x) = a * product x
• reverse [] = []
• reverse (a:x) = reverse x ++ [a]
Miranda
• answer = twice twice twice suc 0
• twice f x = f (f x)
• suc x = x + 1
• foldr op k [] = k
• foldr op k (a:x) = op a (foldr op k x)
• sum = foldr (+) 0
• product = foldr (*) 1
• reverse = foldr
postfix []
where postfix a x = x ++ [a]
Miranda
• [ n*n | n <- [1..100] ]
• factors n = [ i | i <- [1..n div 2]; n mod i = 0 ]
• sort [] = []
• sort (a:x) =
sort [ b | b <- x; b<=a ]
++ [a] ++
sort [ b | b <- x; b>a ]
Miranda
• ones = 1 : ones
• nats = [0..]
• odds = [1,3..]
• squares = [ n*n | n <- [0..] ]
• perfects = [ n | n <- [1..]; sum(factors n) = n ]
• primes = sieve [ 2.. ]
where
sieve (p:x) = p : sieve [ n | n <- x; n mod p > 0 ]
Haskell
• Берёт начало из языка Miranda
• Имеет интерпретаторы и компиляторы
(HUGS, Glasgow Haskell Compiler (GHC))
• Интегрируется в программные системы:
.Net – Mondrian, COM/ActiveX –
HaskellScript, Java – jaskell
• ООП: O’Haskell, Haskell++ и Mondrian
Haskell
• Считается одним из «чистых» функциональных
языков, хотя и содержит, например, операции
ввода-вывода при помощи монад. Считается, что
опытный программист не будет ими
злоупотреблять.
• getLine = do c <- getChar
if c == '\n'
then return ""
else do l <- getLine
return (c:l)
Erlang
• Позволяет писать программы для разного рода
распределённых систем.
• Разработан и поддерживается компанией Ericsson.
• Язык включает в себя средства порождения
параллельных процессов и их коммуникации с
помощью посылки асинхронных сообщений.
• Программа транслируется в байт-код, исполняемый
виртуальной машиной, что обеспечивает
переносимость.
• Кратко формулу языка можно выразить как
Erlang=функциональный язык+процессы.
• Синтаксис наследован от Prolog.
Erlang
• Отсутствие присваиваний позволяет Erlang избежать таких
традиционных для императивных языков проблем
распределённых приложений, как необходимость
синхронизации, опасность возникновения тупиков и гонок.
• Java – Everything is an object
• Lisp – Everything is a list
• Erlang – Everything is a process
• Язык стимулирует к созданию большого количества
конкурентных процессов.
• Процессы жёстко изолированы и не имеют общего состояния.
Erlang
• Параллельные вычисления.
• Надежность. Erlang позволяет выстраивать различные
сценарии для отслеживания всевозможных состояний системы
– от примитивных (отслеживание состояния различных
процессов) до продвинутых (таких, как создание failoverкластеров).
• «Горячая» замена кода. Erlang позволяет отслеживать
изменения в системе и загружать обновленные версии кода без
остановки всей системы, что особенно важно, если такая
остановка невыгодна или невозможна.
• Внешние интерфейсы. Процессы в Erlang-е взаимодействуют
друг с другом путем передачи асинхроных сообщений. На этом
же принципе построено взаимодействие и с программами,
написанными на С/С++ или Java. Существует также интерфейс
взаимодействия с .NET.
Erlang
• Стандартные библиотеки:
• Mnesia. Распределенная СУБД.
• Inets. HTTP-клиент и сервер, а также FTPклиент.
• Orber. CORBA v2.0 Object Request Broker
(ORB).
Erlang
• Для телекоммуникационного оборудования
(например, в компаниях Ericsson и Nortel).
• Для создания сервера ejabberd на основе
протокола Jabber.
• Для управления поездами (например, в
метро в городе Лион, Франция).
• В БД-приложениях, нуждающихся в
режиме, близком к режиму реального
времени.
Erlang
•
•
•
•
•
-module(tut1).
-export([fac/1, mult/2]).
fac(1) -> 1;
fac(N) -> N * fac(N - 1).
mult(X, Y) -> X * Y.
• list_length([]) -> 0;
• list_length([First | Rest]) -> 1 + list_length(Rest).
Erlang
• -module(tut14).
• -export([start/0, say_something/2]).
• say_something(What, 0) ->
•
done;
• say_something(What, Times) ->
•
io:format("~p~n", [What]),
•
say_something(What, Times - 1).
• start() ->
•
spawn(tut14, say_something, [hello, 3]),
•
spawn(tut14, say_something, [goodbye, 3]).
tut14:start().
hello
goodbye
<0.63.0>
hello
goodbye
hello
goodbye
Erlang
1> [2*N || N <- [1,2,3,4]].
[2,4,6,8]
2> [X || X <- [1,2,3,4,5,6,7,8,9,10], X rem 2 =:=
0].
[2,4,6,8,10]
Erlang tail recursion
duplicate(0,_) ->
[];
duplicate(N,Term) when N > 0 ->
[Term|duplicate(N-1,Term)].
tail_duplicate(N,Term) ->
tail_duplicate(N,Term,[]).
tail_duplicate(0,_,List) ->
List;
tail_duplicate(N,Term,List) when N > 0 ->
tail_duplicate(N-1, Term, [Term|List]).
-module(ch3).
-behaviour(gen_server).
-export([start_link/0]).
-export([alloc/0, free/1]).
-export([init/1, handle_call/3, handle_cast/2]).
start_link() ->
gen_server:start_link({local, ch3}, ch3, [], []).
alloc() ->
gen_server:call(ch3, alloc).
free(Ch) ->
gen_server:cast(ch3, {free, Ch}).
init(_Args) ->
{ok, channels()}.
handle_call(alloc, _From, Chs) ->
{Ch, Chs2} = alloc(Chs),
{reply, Ch, Chs2}.
handle_cast({free, Ch}, Chs) ->
Chs2 = free(Ch, Chs),
{noreply, Chs2}.
OTP
And much more!
At learnyousomeerlang.com
ML
• Функциональный язык общего назначения,
разработанный в конце 1970 Робертом
Милнером в Университете Эдинбурга
• Имеет также императивные элементы
• Имеет множество диалектов, наиболее
известные из которых на данный момент:
Standart ML, OCaml и F#
ML
• fun fact n = let
fun fac 0 = 1
| fac n = n * fac (n - 1)
in
if (n < 0) then raise Fail "negative argument"
else fac n
end
ML
• Caml
–
–
•
•
•
•
•
•
•
Objective Caml, известный диалект Caml c поддержкой ООП
Moscow ML – популярная реализация Standard ML
произошедшая от Caml light
Standard ML
Alice
F#
Rpal
LML (Lazy ML)
Mythryl
Nemerle
VAL
• Ориентированный на значения
алгоритмический язык
• Был разработан для потоковых архитектур
Деннисом в 1979 году
• Базируется на математической модели «схемы
Денниса»
• Имеет особую обработку ошибок
• Присутствуют итерации
• Отсутствуют рекурсия и ввод/вывод
Sisal
• Streams and Iteration in a Single Assignment
Language
• Функциональный язык однократного
присваивания с неявным параллелизмом,
ориентированный на научные вычисления
• Разрабатывался университетом Манцестера,
LLNL, университетом Колорадо and DEC
• Sisal 1.3 по проведённым тестам в 1986 был
сравним в производительности с Си.
Sisal
• define main
• type OneDim = array [ real ];
• type TwoDim = array [ OneDim ];
• function generate( n : integer
•
returns TwoDim, TwoDim )
•
for i in 1, n cross j in 1, n
•
returns array of real(i)/real(j)
•
array of real(i)*real(j)
•
end for
• end function % generate
Sisal
• for i in 1, number_of_values
new_val := deep_thought( value[i] )
returns array of new_val
unless new_val > upper_val
| new_val < lower_val
end for
Sisal
• Особые циклические конструкции
• Наличие массивов
• Модель всюду завершаемых частичных
вычислений
• «многословный» синтаксис
• Ориентированность на научные
вычисления
Download