Imię ..........Piotr
Nazwisko ........Lewicki
Wiek ..
Wzrost 72.4409449 inch
Waga ...2574.9728 oz
Narodowość .........Polska

17-12-2010

Język multi-paradygmatowy Oz – przykłady Mozart/Oz

Filed under: Funkcyjne — Tagi: , — Levik @ 22:26

Przyszło mi się zmierzyć z nowym paradygmatem programowania, mianowicie programowaniem funkcyjnym. Od kilku lat zajmuje się programowaniem. Na początku pisałem imperatywnie, później obiektowo, ale nigdy nie funkcyjnie. Przyznam, że musiałem zmienić odrobinę spojrzenie na kod i samo programowanie. Jednak po krótkiej, ale jakże ciekawej batalii stoczonej na płaszczyźnie mojej klawiatury muszę powiedzieć, że udało się. Jednak spokojna głowa ten paradygmat nie trafi do mojego TOP 3.

Na zajęciach piszemy w języku OCaml i Oz (o pierwszym z nich napiszę później). Teraz skupmy się na języku Oz. Jest to język multi-paradygmatowy, czyli wspomaga kilka paradygmatów. W tym przypadku są jest to:

1. Programowanie w logice
2. Programowanie funkcyjne
3. Programowanie imperatywne
4. Programowanie obiektowe
5. Programowanie deklaratywne

Początki Oz’a sięgają 1991 roku jak to często bywa stworzył go student. Od 1996 roku pieczę nad projektem ma konsorcjum Mozart (często możemy zauważyć w sieci pisownię Oz/Mozart). Projekt jest udostępniany na licencji open source. Składnia języka na początku wydała mi się dość przyjemna, ale z czasem dała ostro popalić. Z języka korzystałem tylko do celów edukacyjnych dlatego nie jestem wstanie powiedzieć wam nic nowego czego nie przeczytacie w dokumentacji i tutorialu (ahhh to co tygryski lubią najbardziej)

Jako, że w internecie jest bardzo mało przykładów związanych z językiem Oz postanowiłem to zmienić. Oto kilka prostych programów.

Funkcja Rev (reverse – przyjmuje jako argument listę) odwracająca listę (rekursja ogonowa).

1
2
3
4
5
6
7
8
9
10
declare fun {Rev L}
	   local fun {Pom L Acc}
		    case L of
		       nil then Acc
		    [] H|T then {Pom T H|Acc}
		    end
		 end
	   in {Pom L nil}
	   end
	end

Funkcja Length która zwraca długość listy przyjętej jako argument.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
declare fun {Length Lst}
	   local fun {Length_acm Lst Acm}
	      if Lst==nil then Acm
	      else {Length_acm Lst.2 Acm+1}
	      end
	   end
	   in {Length_acm Lst 0}
	   end
	end
 
%przykładowa tablica
declare L = 1|2|3|4|5|nil
 
%wydrukowanie wyniku
{Show {Length L}}

Dalej przedstawię zadania z list ćwiczeń, które to rozwiązywałem na zajęciach, niestety nie wszystkie zadania są optymalne obliczeniowo, wiele z nich można usprawnić:

1. Zdefiniuj funkcję Flatten1, która dla argumentu będącego listą list tworzy listę złożoną z elementów wszystkich podlist z zachowaniem ich kolejności, np. {Flatten1 [[5 6] [1 2 3]]} zwraca [5 6 1 2 3], czyli spłaszcza listę o jeden poziom.

1
2
3
4
5
6
7
8
9
10
11
declare fun {Flatten1 L}
	   if L==nil then
	      nil
	   else
	      {Append L.1{Flatten1 L.2}}
	   end
end
 
declare Lst = [[5 6 1 2 3] nil [3 4 3] [3]]
 
{Show {Flatten1 Lst}}

2. Zdefiniuj funkcję Count obliczającą ile razy dany obiekt występuje w danej liście, np. {Count ‘a’ ['a' 'l' 'a']} zwraca 2.

1
2
3
4
5
6
7
8
9
10
declare fun {Count Z Lst}
	   if Lst==nil then 0
	   else
	      if Z==Lst.1 then 1+{Count Z Lst.2}
	      else 0+{Count Z Lst.2}
	      end
	   end
end
 
{Show {Count 'a' a|b|a|b|a|b|nil}}

3. Zdefiniuj funkcję Duplicate powtarzającą dany obiekt określoną liczbę razy i zwracającą wynik w postaci listy, np. {Duplicate ‘la‘ 3} →['la' 'la' 'la'].

1
2
3
4
5
6
7
declare fun {Duplicate O N}
	   if N==0 then nil
	    else O|{Duplicate O N-1}
	   end
	end
 
{Show {Duplicate 'a' 6}}

4. Zdefiniuj funkcję Sqr_list podnoszącą do kwadratu wszystkie elementy danej listy liczb, np. {Sqr_list [1 2 ~3]} → [1 4 9].

1
2
3
4
5
6
7
8
9
10
declare fun {Sqr_list Lst}
	   if Lst==nil then nil
	   else
	      Lst.1*Lst.1|{Sqr_list Lst.2}
	   end
	end
 
declare L = 3|4|nil
 
{Show {Sqr_list L}}

5. Zdefiniuj funkcję Palindrome sprawdzającą, czy dana lista jest palindromem, tj. równa się sobie samej przy odwróconej kolejności elementów, np. {Palindrome ['a' 'l' 'a']} zwraca true.

1
2
3
4
5
6
7
8
9
10
declare fun {Palindrome Lst}
	   if Lst==nil then nil
	   else
	      Lst=={Reverse Lst}
	   end
end
 
declare L = k|a|j|a|k|nil
 
{Show {Palindrome L}}

6. Zdefiniuj funkcję ListLength obliczjącą długość dowolnej listy.

1
2
3
4
5
6
7
8
9
10
declare fun {ListLength Lst}
	   if Lst==nil then 0
	   else
	      1+{ListLength Lst.2}
	   end
	end
 
declare L = 1|2|3|4|nil
 
{Show {ListLength L}}

7. Liczby Fibonacciego są zdefiniowane następująco:
f(0) = 0
f(1) = 1
f(n+2) = f(n) + f(n+1)
Napisz dwie funkcje, które dla danego n znajdują n-tą liczbę Fibonacciego: pierwszą opartą bezpośrednio na powyższej definicji i drugą, wykorzystującą rekursję ogonową. Porównaj ich szybkość wykonania, obliczając np. 37-mą liczbę Fibonacciego.

1
2
3
4
5
6
7
8
9
declare fun {Fib N}
	    if N==0 then 0
	    else
	       if N==1 then 1
	       else {Fib N-1}+{Fib N-2}
	       end
	    end
	 end
{Show {Fib 37}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
declare fun { Fib_tail N}
	   local fun {Fib N1 N2 I}
		    if I=<2 then N2
		    else
		       local Next = N1+N2 in
			  {Fib N2 Next I-1}
		       end
		    end
		 end
	   in {Fib 1 1 N}
	   end
	end
 
{Show {Fib_tail 37}}

8. Zdefiniuj funkcję Initsegment : ‘a list * ‘a list -> bool sprawdzającą w czasie liniowym, czy pierwsza lista stanowi początkowy segment drugiej listy. Każda lista jest swoim początkowym segmentem, lista pusta jest początkowym segmentem każdej listy.

1
2
3
4
5
6
7
8
9
10
11
declare fun {Initsegment L1 L2}
	   case L1 of
	      nil then true
	   [] H|T then
	               if H==L2.1 then {Initsegment T L2.2}
		       else false
		       end
	   end
	end
 
{Show {Initsegment 2|3|nil 1|2|3|4|nil}}

OK myślę, że na razie te kila przykładów wystarczy, mam w zanadrzu jeszcze kilka mini-programików, myślę że z czasem je udostępnię. Jak sami widzicie jestem jeszcze dość zielony w paradygmacie funkcyjnym, ale powoli nabieram zrozumienia wobec tej „filozofii”. Mam szczerą nadzieję, że analiza tych kilku programów pozwoli wam szybciej oswoić się z nowym językiem, a przede wszystkim paradygmatem.

Pozdrawiam PL

- by levik@wp.pl L3VIK -

Jesteś gościem numer - Twój adres IP to: 38.107.179.210