Aktywne Wpisy
userrrr +19
Nasz kraj byłby bogaty, gdyby szwaby i kacapy wypłacili nam odszkodowanie za II wojne światową, wg szacunków szwaby są nam winne ok 6 bln PLN za II wojne św, kacapy strzelam drugie tyle, bo za wojne, za to, że nas perfidnie okradali za czasów PRLu i za to, że sa narodowymi kłamcami i oszustami, z którymi się nie da rozmawiać, czyli to będzie od kacapów ok 12 bln PLN czyli w sumie
![](https://wykop.pl/cdn/c0834752/580493708ca3f006337fc53ad546525f479063f3d4017957b690f22ce104a989,q60.jpg)
wonziu1 +7
Wszyscy się smieją że ruskie dostają czitosy za zgruzowanie, a na ukrainie cokolwiek jest dawane rodziną ofiar xD czy jedynie usmiech zalenskiego ma zasklepić rany?
#ukraina
#ukraina
Odcinek 3 - więcej o funkcjach wyższego rzędu, uzupełnienie niektórych rzeczy które pominąłem.
Dla odmiany zacznijmy najpierw od zadania z poprzedniego odcinka.
Najpierw napiszę jedną funkcję tak, jakby nie było map reduce ani nic takiego:
; suma wektorow 2wymiarowych v1 i v2
(
defn
```**```
v2d+ [v1 v2]
``````
[(
```**```
+
```**```
(v1 0)
``````
(v2 0))
``````
(
```**```
+
```**```
(v1 1)
``````
(v2 1))])
```Resztę funkcji można zapisać analogicznie. Jest to jednak sporo kodu, i jest on specyficzny dla wersji dla wektorów 2-wymiarowych. Fajnie by było napisać to tak, żeby działało również dla wersji 3-wymiarowej. Można zauważyć, że robimy to samo (sumujemy) wszystkie elementy obu wektorów. Więc może map i reduce?```
(defn v2d+ [v1 v2] (map + v1 v2))
(defn v2d- [v1 v2] (map - v1 v2))
(defn v2d*s [v s] (map (fn [x] (* x s)) v))
(defn v2d*v2d [v1 v2] (reduce + (map * v1 v2)))
(defn v2d-len [v] (Math/sqrt (v2d*v2d v v)))
```Trochę krócej ;) I mamy tą zaletę, że wszystkie funkcje działają dla wektorów dowolnej wielkości. Ale przetestujmy te funkcje.```
(v2d+ [1 2] [3 4]) ; zwraca (4 6). Czemu nie [4 6] ?
```Otóż clojure oprócz konkretnych typów danych ma interfejsy. Interfejsem używanym przez większość kolekcji jest ISeq. Zawiera on 3 funkcje:```
(first coll) ; zwraca pierwszy element kolekcji (lub nil jak jest pusta)
(rest coll) ; zwraca sekwencję kolejnych elementów kolekcji oprócz pierwszego (jak nie ma to pusta sekwencja)
(cons item coll) ; tworzy sekwencję przez dołączenie item na początku kolekcji coll
```Sekwencje mogą być leniwe, czyli clojure nie musi znać wszystkich elementów sekwencji od razu w momencie jej utworzenia. Wystarczy, że wie, jak ma je wyliczyć w razie, jak będą potrzebne. Dzięki temu Clojure może bezproblemowo operować na nieskończonych sekwencjaach tak długo, jak ich nie każemy w całości wyświetlić, albo w inny sposób nie spowodujemy konieczności wyliczenia wszystkich elementów.Przykład nieskończonej sekwencji:```
(repeat 5) ; zwróci Execution Timed Out! bo okazuje się, że nie umiemy wyświetlić wartości nieskończonej sekwencji
(take 10 (repeat 5)) ; zwróci (5 5 5 5 5 5 5 5 5 5), bo funkcja take bierze pierwsze n elementów sekwencji
```Co ciekawe - można operować na leniwych sekwencjach bez ich wyliczania. Np map nie wymusza wyliczenia sekwencji. Przykład:```
(def tmp (map + (repeat 5) (repeat 1))) ; właśnie dodaliśmy nieskończoną liczbę 1 do nieskończonej liczby 5. Szybko się z tym clojure uwinęło, prawda :)
(take 10 tmp) ; zwróci (6 6 6 6 6 6 6 6 6 6)
(take 1 tmp) ; zwróci (6)
```Przydatną funkcją zwracającą sekwencje jest range. (range n) zwróci sekwencję 0..n-1 włącznie. (range) zwróci nieskończoną sekwencję od 0 w górę.```
(range 10) ; zwróci (0 1 2 3 4 5 6 7 8 9)
(take 10 (range)) ; zwróci (0 1 2 3 4 5 6 7 8 9) czyli to samo.
```Zauważmy, że```
(def tmp2 (map + (repeat 5) (range)))
(take 3 tmp2) ; zwróci (5 6 7)
```Na razie nie będziemy się skupiać na sekwencjach, więcej o nich (i o ogrmonej liczbie funkcji operujących na nich) można poczytać w [http://clojure.org/sequences](http://clojure.org/sequences)Jak widać map operuje nie na wektorach, tylko na wspólnym interfejsie kolekcji - sekwencjach, i zwraca sekwencje. Dlatego dostaliśmy (4 6) z naszej funkcji, a nie [4 6]. Dla pewności możemy sprawdzić typ zwracanej wartości, bo listy w clojure również są wyświetlane jako (4 6).```
(type (v2d+ [1 2] [3 4])) ; zwraca clojure.lang.LazySeq czyli jest to sekwencja (i to leniwa, choć leniwa sekwencja 2-elementowa to trochę overkill)
```Jeśli nam to nie przeszkadza - możemy nasze funkcje zostawić w takiej postaci sposób. Jeśli chcemy, żeby zawsze zwracały wektory, można skonwertować sekwencje do wektorów:```
(defn v2d+ [v1 v2] (vec (map + v1 v2)))
(defn v2d- [v1 v2] (vec (map - v1 v2)))
(defn v2d*s [v s] (vec (map (fn [x] (* x s)) v)))
```Tutaj można użyć skrótu do zapisywania funkcji anonimowej, zamiast pisać```
(fn [x] (* x s))
```można napisać```
#(* % s)
```Tak zrobił @rubberbandman. % jest argumentem tej funkcji. Dla funkcji wielo-argumentowych używa się %1 %2 itd, ale dla większych funkcji lepiej nie korzystać ze skrótu, tylko użyć fn i ponazywać argumenty.Poprzednim razem obiecałem wyjaśnić sprawę optymalności rekurencji jako sposobu na pętle. Kłamałem ;) Będzie w następnym odcinku, bo i tak długie są te wpisy.Zadanie 3. napisać swoją wersję funkcji map działającej dla funkcji 1-argumentowych i 1 kolekcji.```
(defn nasz-map [f coll] ...)
Można skorzystać z reduce albo z rekurencji.
Jak zwykle proszę o uwagi i komentarze. Co się nie podoba, co niejasne, czy za bardzo skaczę po tematach, jak z długością wpisów? Robi ktoś te zadanka?
map
ale w czystym Scheme.
Komentarz usunięty przez moderatora
Komentarz usunięty przez autora
Komentarz usunięty przez moderatora
Z tego co zauważyłem, ludzi stosują clojure do