Wpis z mikrobloga

#programowanie #clojure #learnclojurewithmikroblog

Zaczynamy. Kod można przepisywać do intepretera clojure na stronie http://tryclj.com/ albo można sobie zainstalować clojure na komputerze: http://clojure.org/getting_started

Podstawy składni - wywołanie funkcji f(arg1, arg2, arg3) wygląda tak:

(f arg1 arg2 arg3) ; to się wywali bo nie ma funkcji "f"
; oznacza komentarz do końca linii, elementy oddzielamy spacjami.

Na początek - jeśli nie wiemy, co robi jakaś funkcja czy makro w clojure można zawsze wywołać

(doc cokolwiek) ; zwraca dokumentację dotyczącą cokolwiek.
Dla przykładu:

(doc +) ; zwróci nam dokumentację funkcji + czyli

; clojure.core/+ ; to przed "/" to przestrzeń nazw - clojure.core jest dostępna od razu

; ------------------

; ([] [x] [x y] [x y & more])

; Returns the sum of nums. (+) returns 0. Does not auto-promote

; longs, will throw on overflow. See also: +'

Jak widać + przyjmuje 0, 1, 2, lub więcej argumentów. Sprawdźmy.

(+) ; suma 0 elementów to zwraca 0

(+ 100) ; suma 1 elementu to ten element czyli 100 w tym wypadku

(+ 1 2) ; zwroci 3

(+ 1 2 3 4 5) ; zwroci 15

+ to "zmienna" (w clojure zwana Var) przypisana do symbolu +, której wartością jest funkcja sumująca dowolną liczbę argumentów. Clojure widząc listę (czyli cokolwiek w nawiasach okrągłych) pobiera pierwszy element, traktuje go jako funkcję, i wywołuje tą funkcję

biorąc następne elementy jako argumenty (najpierw je wyliczając, jeśli trzeba).

+ nie jest w żaden sposób specjalną funkcją - w clojure funkcje mogą mieć w nazwach + - * / itp. Clojure nie ma specjalnej składni dla wyrażeń artmetycznych, jak większość języków. Czyli

1 + 2*3 + 4/2
nie jest poprawnym kodem clojure. Trzeba to zapisać jako:

(+ 1 (* 2 3) (/ 4 2))
zwykle stosuje się wcięcia

(+ 1

(* 2 3)

(/ 4 2))

Zgoda - jest to trochę niewygodne. Można sobie napisać makro dodające normalną (infiksową) arytmetykę do clojure,

ale zrobimy to potem, o ile dotrwamy do tego momentu :)

Dzielenie liczb całkowitych jest specjalne, bo zwraca dokładne wartości - typ wyniku nazywa się ratio i np

(/ 1 3) ; zwróci wartość zapisywaną przez clojure jako 1/3.
Można na nich normalnie operować funkcjami + - * / < > <= >= = itp Ciekawostka - operatory porównań w clojure działają na dowolnej liczbie argumentów. Sprawdźcie, co zwraca ( <= 1 2 3 4) albo (<= 1 2 4 3).

Przejdźmy do definiowania funkcji. Funkcje definiujemy w clojure słówkiem fn (anonimowe) i defn (nazwane).

(fn [x y]

(+ x y)) ; to definiuje funkcję 2-argumentową i zwraca tą funkcję - od razu zostanie usunięta bo nic z nią nie robimy

(def suma ; def definiuje sumbol suma i tworzy Var-a którego wartość ustawia na funkcję

(fn [x y]

(+ x y)))

(defn suma [x y] ; defn jest najczęstszym sposobem tworzenia funkcji - od razy definiuje ją i przypisuje do symbolu

(+ x y)) ; to definiuje funkcje 2-argumentową zwracającą x+y i przypisuje ją do symbolu suma

W clojure nie ma pętli for, i praktycznie nie używa się zmiennych :) Instrukcja warunkowa wygląda tak:

(if (= (+1 2) 3)

"1+2 rowna sie trzy"

"1+2 nie rowna się trzy")

Jeśli chcemy pętli - musimy użyć rekurencji, lub (zwykle) skonstruować pętlę z map filter i reduce - o tym już nie dzisiaj.

Silnia w clojure (nieoptymalna - można dużo lepiej) wygląda tak:

(defn silnia [n]

(if (< n 2)

1

(* n (silnia (- n 1)))))

Zadanie 1 - napisać funkcję (fib n) zwracającą n-ty element ciągu Fibbonaciego. Powodzenia. Jak wklejacie tu odpowiedzi to spojlerujcie.

W sumie nie wiem, czy taki format jest dobry - wygodnie się to czyta? Na początek trochę dużo informacji musiałem dać. Uwagi mile widziane.

W następnym odcinku już fajne rzeczy - struktury danych i funkcje wyższego rzędu - filter, map i reduce.
  • 7
@Neutrin: clojure jest na jvm, .net i javascriptcie, ale najlepiej działa na jvm. O wersj dla C++ nie słyszałem.

Bangla dobrze jak na to co robi - to nie jest typowy lisp. Przede wszystkim ma Software Transactional Memory zaimplementowane i trwałe (persistent) struktury danych. Efekt jest taki, że pisząc idiomatyczny kod w clojure - jest on praktycznie zawsze gotowy do odpalenia na wielu wątkach. Taki zresztą był cel twórcy tego języka.