Haskell
qsort [] = []qsort (x:xs) = qsort [y | y <- xs, y<x] ++ [x] ++ qsort [y | y <- xs, y>=x]
Erlang
qsort([]) -> [];qsort([X|Xs]) -> qsort([Y || Y <- Xs, Y<X]) ++ [X] ++ qsort([Y || Y <- Xs, Y>=X]).
☞ Szybkość procesorów praktycznie przestała rosnąć ok 2006
Rośnie liczba rdzeni
Program sekwencyjny będzie z roku na rok działał coraz wolniej
Program współbieżny będzie z roku na rok działał coraz szybciej
ben@azor$ time ./sudoku-par3 sudoku17.1000.txt +RTS -N1real 0m2.646suser 0m2.610ssys 0m0.044sben@azor$ time ./sudoku-par3 sudoku17.1000.txt +RTS -N2real 0m1.532suser 0m2.971ssys 0m0.088sben@azor$ time ./sudoku-par3 sudoku17.1000.txt +RTS -N4real 0m0.900suser 0m3.396ssys 0m0.177sben@azor$ time ./sudoku-par3 sudoku17.1000.txt +RTS -N8real 0m0.598suser 0m4.316ssys 0m0.357s
solve :: String -> Maybe Gridmain = do [f] <- getArgs grids <- fmap lines $ readFile f print (length (filter isJust (runPar $ parMap solve grids)))
Dla zbudowania systemu odpornego na awarie potrzeba co najmniej dwóch komputerów
W razie awarii jednego, drugi przejmie jego funkcje
Konsekwencje:
Procesy w Haskellu współdzielą pamięć
W Erlangu każdy proces ma własny heap:
W Smalltalku przekazywanie komunikatów, ale przy współdzielonej pamięci
Dla zbudowania systemu odpornego na awarie potrzeba co najmniej dwóch komputerów
Dla zbudowania systemu wysoce odpornego na awarie potrzeba wielu komputerów
Wiele procesów
Pełna izolacja między procesami
Niezależne od lokalizacji
Nie ma współdzielonych danych
Tylko przesyłanie komunikatów
Bliskie intuicyjnemu rozumieniu współbieżności
Świat realny jest współbieżny
Świat realny jest rozproszony
Świat realny jest poznawalny ;)
Tworzenie realnych aplikacji jest oparte na obserwacji rzeczywistych wzorców współbieżności i kanałów komunikacji
Ułatwia budowanie skalowalnych, rozproszonych programów.
Niewiele o składni (czerpie z Prologu)
Programowanie sekwencyjne
Programowanie współbiezne
Programowanie rozproszone
Odporność na błędy
1, 2, 3.1415
hello
"hello"
11> <<16#48,101,$l,"lo">>.<<"Hello">>13> <<2#1010>>.<<"\n">>14> <<2#1010:4>>.<<10:4>>
{color, "red"}
[red,green,blue]
16> [1|[2|[]]].[1,2]
16> X = 1.117> X=X+1.* exception error: no match of right hand side value 218> X = 2.* exception error: no match of right hand side value 219> {Y,Z} = {1,2}.{1,2}20> {V1,2} = {1,V2}. 1: variable 'V2' is unbound
NB Prolog:
?- X=1, X=2.false.?- .(V1,2) = .(1,V2).V1 = 1,V2 = 2.
21> L = [1,2,3].[1,2,3]22> [0,1,2,3] = [0|L].[0,1,2,3]23> [H|T] = L.[1,2,3]24> H.125> T.[2,3]
Funkcje
27> Increment = fun(X) -> X + 1 end,27> [2,3,4] = lists:map(Increment,L).[2,3,4]
-module(math).-export([fac/1]).fac(0) -> 1;fac(X) when X > 0 -> X*fac(X-1).
1> c(math).{ok,math}2> math:fac(5).1203> math:fac(-1). * exception error: no function clause matching math:fac(-1)(math.erl, line 4)
-module(geometry).-export([area/1]).area({rectangle, W,H}) -> W*H;area({square, X}) -> X*X;area({circle, R}) -> 3.14159*R*R.
Eshell V6.4 (abort with ^G)1> c(geometry).{ok,geometry}2> geometry:area({square, 10}).1003> geometry:area({circle, 10}).314.1594> geometry:area(7).* exception error: no function clause matching geometry:area(7) (geometry.erl, line 4)
area2({rectangle, W,H}) -> W*H;area2({square, X}) -> X*X;area2({circle, R}) -> 3.14159*R*R;area2(Other) -> error.
47> self(). <0.11254.0>48> geometry:area2(7).error49> self(). <0.11254.0>50> geometry:area(7). * exception error: no function clause matching geometry:area(7) (geometry.erl, line 4)51> self().<0.11259.0>
NB: wyjątek powoduje zakończenie procesu interpretera, nadzorca uruchamia nowy proces.
lookup(Key, {Key, Val,_,_}) -> {ok, Val};lookup(Key, {Key1,Val,S,B}) when Key < Key1 -> lookup(Key, S);lookup(Key, {Key1, Val, S, B})-> lookup(Key, B);lookup(key, nil) -> not_found.
Komunkacja między procesami jest asynchroniczna
Każdy proces ma swoją 'skrzynkę pocztową' (mailbox)
wysłanie komunikatu (do skrzynki): proces ! komunikat
Odbiór komunikatu
receive wzorzec -> wyrażenie; wzorzec -> wyrażenie; ...end
Wyczyszczenie skrzynki: flush()
- w shellu dodatkowo wypisuje komunikaty.
1> self() ! hello.hello2> self() ! testing.testing3> self() ! [1,2,3].[1,2,3]4> flush().Shell got helloShell got testingShell got [1,2,3]ok5> flush().ok
1> receive 1> ok -> cool 1> after1> 1000 -> timeout1> end.timeout2> self() ! ok. ok3> receive ok -> cool after 100 -> timeout end.cool
8> Shell = self(). <0.36.0>9> SendHello = fun()-> Shell ! hello end.#Fun<erl_eval.20.90072148>10> spawn(SendHello).<0.51.0>11> spawn(SendHello).<0.53.0>12> spawn(SendHello).<0.55.0>13> flush().Shell got helloShell got helloShell got hellook
1> Send = fun(From)->fun()->From ! { ok, {sent, From}, {rcvd, self()} } end end.#Fun<erl_eval.6.90072148>2> spawn(Send(self())).<0.35.0>3> spawn(Send(self())).<0.37.0>4> spawn(Send(self())).<0.39.0>5> flush().Shell got {ok,{sent,<0.32.0>},{rcvd,<0.35.0>}}Shell got {ok,{sent,<0.32.0>},{rcvd,<0.37.0>}}Shell got {ok,{sent,<0.32.0>},{rcvd,<0.39.0>}}ok6> spawn(Send(self())).<0.42.0>7> receive {ok, {sent, From}, {rcvd, By}} -> {ok, From, By} end. {ok,<0.32.0>,<0.42.0>}8> flush().ok
-module(dist).-export([t/1]).t(From) -> From ! { ok, node(), self() }.
$ erl -sname bar(bar@marbook)1> node().bar@marbook(bar@marbook)2> c(dist).{ok,dist}
$ erl -sname foo(foo@marbook)1> c(dist).{ok,dist}(foo@marbook)2> spawn('bar@marbook',dist,t,[self()]).<9728.49.0>(foo@marbook)3> flush().Shell got {ok,bar@marbook,<9728.49.0>}ok
Erlang pozwala na zmianę kodu w trakcie działania programu.
Po skompilowaniu modułu, kolejne wywołanie użyje nowej wersji
21> Crash=fun()->timer:sleep(1000),1/0 end.#Fun<erl_eval.20.90072148>22> self().<0.46.0>23> Crash().* exception error: an error occurred when evaluating an arithmetic expression in operator '/'/2 called as 1 / 024> self().<0.65.0>25> spawn(Crash).<0.68.0>=ERROR REPORT==== 12-Jun-2016::07:00:42 ===Error in process <0.68.0> with exit value: {badarith,[{erlang,'/',[1,0],[]}]}26> self().<0.65.0>
Błąd w procesie nie wpływa na interpreter.
Możemy powiązać procesy tak, że awaria jednego z procesów powoduje zakończenie drugiego:
28> self().<0.65.0>29> spawn_link(fun() -> receive after 200 -> exit(normal) end end).<0.80.0>30> self().<0.65.0>31> spawn_link(fun() -> receive after 200 -> exit(error) end end). <0.83.0>* exception error: error32> self(). <0.85.0>
Po ustawieniu flagi trap_exit
, zakończenie powiązanego procesu
powoduje wysłanie komunikatu, co pozwala na zrestartowanie go.
14> process_flag(trap_exit,true).false15> process_flag(trap_exit,true).true16> flush().ok17> spawn_link(fun() -> receive after 200 -> exit(error) end end). <0.57.0>18> 18> flush().Shell got {'EXIT',<0.57.0>,error}ok19> spawn_link(fun() -> receive after 200 -> exit(normal) end end). <0.60.0>20> flush(). Shell got {'EXIT',<0.60.0>,normal}ok
1> spawn_link(fun() -> receive after 200 -> exit(normal) end end).<0.34.0>2> spawn_link(fun() -> receive after 200 -> exit(error) end end). <0.36.0>* exception error: error3> P = spawn(fun() -> receive after 10000 -> ok end end).<0.39.0>4> monitor(process, P).#Ref<0.0.0.44>5> monitor(process, P).#Ref<0.0.0.49>6> monitor(process, P).#Ref<0.0.0.54>7> flush().Shell got {'DOWN',#Ref<0.0.0.44>,process,<0.39.0>,normal}Shell got {'DOWN',#Ref<0.0.0.49>,process,<0.39.0>,noproc}Shell got {'DOWN',#Ref<0.0.0.54>,process,<0.39.0>,noproc}ok
8> P = spawn(fun() -> receive after 10000 -> exit(error) end end).* exception error: no match of right hand side value <0.45.0>9> Q = spawn(fun() -> receive after 10000 -> exit(error) end end).<0.48.0>10> monitor(process, Q). #Ref<0.0.0.78>11> monitor(process, Q).#Ref<0.0.0.83>12> monitor(process, Q).#Ref<0.0.0.88>13> flush(). Shell got {'DOWN',#Ref<0.0.0.78>,process,<0.48.0>,error}Shell got {'DOWN',#Ref<0.0.0.88>,process,<0.48.0>,error}Shell got {'DOWN',#Ref<0.0.0.83>,process,<0.48.0>,error}ok
erlang:monitor/2
jest częścią biblioteki OTP
Biblioteka ta dostarcza funkcji obsługujących:
Przykłady zastosowań:
Keyboard shortcuts
↑, ←, Pg Up, k | Go to previous slide |
↓, →, Pg Dn, Space, j | Go to next slide |
Home | Go to first slide |
End | Go to last slide |
b / m / f | Toggle blackout / mirrored / fullscreen mode |
c | Clone slideshow |
p | Toggle presenter mode |
t | Restart the presentation timer |
?, h | Toggle this help |
Esc | Back to slideshow |