Clojure/სპეციალური ფორმები

Clojure-ს აქვს რამდენიმე ჩადგმული ფორმა, რომლებსაც ერთობლიობაში სპეციალურ ფორმებს უწოდებენ. ამ თავში ჩვენ ვიხილავთ ძირითად სპეციალურ ფორმებ, აგრეთვე განვიხილავთ Clojure-ში შესაძლებელი დამატებითი გამოსახულების ტიპებს.

str ფორმა ორი ან მეტი მნიშვნელობის კონკატენაციისთვის გამოიყენება, რომელსაც ეს მნიშვნელობები საჭიროების შემთხვევაში ტექსტში გადაყავს (აკონვერტირებს):

user=> (str "Hello," " world!")
"Hello, world!" 

user=> (str 5)
"5" 

user=> (str "Value: " 5)
"Value: 5"

if ფორმა იდენტურია if გამოსახულება C-ს მსგავს ენაში.

user=> (if true "yes")
"yes" 

user=> (if false "yes")
nil

user=> (if false "yes" "no")
"no" 

user=> (if nil "yes" "no")
"no" 

user=> (if "" true)
true

user=> (if 0 true)
true

user=> (if true "yes" "no")
"yes" 

user=> (if (= 1 1) "yes" "no")
"yes" 

user=> (if (= 1 1) (+ 2 3) (+ 5 5))
5

user=> (if (= 1 2) (+ 2 3) (+ 5 5))
10

თუ პირველი არგუმენტი, შეფასების და კონვერტირების შემდეგ, არის true, მაშინ გამოსახულება აბრუნებს მეორე არგუმენტს, წინააღმდეგ შემთხვევაში, მესამე არგუმენტი ბრუნდება. ბოლო, მესამე, არგუმენტი არააუცილებელია.

Clojure-ში, როდესაც მნიშვნელობა კონვერტირდება, ის ყოველთვის არის true, თუ ის არ არის false ან nil.

if ფორმა ძალიან წააგავს ? ოპერატორის მოქმედებას C-ს მსგავს ენებში:

v = true ? 1 : 0

do ფორმა გამოიყენება რამდენიმე ოპერაციის თანმიმდევრობით შესასრულებლად. ფუნქციონალურ პროგრამირებაში ჩვეულებრივად გამოსახულებები შედიან სხვა გამოსახულების შემადგენლობაში ან შეიცავენ სხვა გამოსახულებებს, ასე რომ არ არის საჭიროება ერთი მეორეს მიყოლებით ოპერაციების შესრულების. კარგია, როდესაც გამოსახულება აბრუნებს მნიშვნელობას, რომელსაც შემდეგ გამოიყენებს შემცველი გამოსახულება. თუმცა არის შემთხვევები, როდესაც გამოსახულების დაბრუნებული მნიშვნელობა არ გამოიყენება. თუ ასეთი გამოსახულება მაინც რამე სასარგებლოს აკეთებს, ამბობენ, რომ მას აქვს გვერდითი ეფექტი. მაგალითისთვის, ჩაწერა სტანდარტულ გამოსასვლელზე ან ფაილში ან მონაცემთა ბაზაში, ყველა არის გვერდითი ეფექტების მაგალითი.

Clojure-ში გვაქვს println ფორმა, სტანდარტულ გამოსავალზე ჩასაწერად. თუ გვინდა რომ println გამოვიყენოთ ისეთი გამოსახულების შიგნით, რომლის მნიშვნელობის გამოყენებას შემდეგ ვაპირებთ, ჩვენ ის უნდა ჩავდგათ do გამოსახულებაში:

user=> (do (println "Hello.") (+ 2 2))
Hello.
4

user=> (do (println "Hello.") (println "Hello again.") (+ 2 2))
Hello.
Hello again.
4

do ოპერაცია ასრულებს ყოველ გამოსახულებას თანმიმდევრობით და აბრუნებს ბოლო გამოსახულების მნიშვნელობას.

do არ არის ერთადერთი, რომელიც გაძლევთ საშუალებას რამდენიმე ოპერაცია თანმიმდევრობით შეასრულოთ. let, defn და fn ყველა იძლევა საშუალებას გააკეთოთ იგივე.

ერთი რამ, რასაც უნდა მიეჩვიოთ, არის ის, რომ Clojure ფუნქციონალური ენაა. ყველა გამოსახულება Clojure-ში აბრუნებს მნიშვნელობას. ხშირად, ერთადერთი Clojure გამოსახულებამ შესაძლოა დაიკავოს რამდენიმე ხაზი, სადაც C-ს მსგავსი პროგრამისტი დაწერდა იგივე ლოგიკას როგორც კოდის ბლოკს, შემდგარს რამდენიმე გამოყოფილი გამოსახულებიდან. გამოყოფილი გამოსახულებები შესაძლოა ანიჭებდეს მნიშვნელობას ცვლადს, რომლიც შემდგომ გამოსახულებაში გამოიყენება. ფუნქციონალურ ენებში დაწერილი პროგრამებს აქვთ უფრო დიდი გამოსახულებები გაშლილი რამდენიმე ხაზად, და არა რამდენიმე ბლოკი დაყოფილი მცირე გამოსახულებებად.ასეთმა სტიმლმა შესაძლოა წაგართვათ დრო, სანამ მიეჩვევით, თუმცა რომ ისწავლით, ახალი სტილი ისეთივე ადვილია, როგორც ძველი. არის რამდენიმე უპირატესობა ასე წეროთ თქვენი პროგრამები.

when ფორმა ჰგავს if ფორმას. განსხვავება ისაა რომ არა გვაქვს "else" პორობა, და შესაძლებელია რამდენიმე გამოსახულების შესრულება თუ პირობა "ჭეშმარიტებაა".

user=> (when nil "Should return 'nil'")
nil

user=> (when false "Should return 'nil'")
nil

user=> (when true "Yes")
"Yes" 

user=> (when true 1)
1

user=> (when true 1 2 3)
3

user=> (when true (println "Hello, world") "Yes")
Hello, world
"Yes" 

user=> (when (= 5 (inc 4)) "Yes")
"Yes"

let ოპერატორი გამოიყენება მნიშვნელობის განსაზღვრისათვის და ამ მნიშვნელობის გამოსაყენებლად შემადგენელ ოპერაციაში.

user=> (let [x 2] (+ x 8))
10

user=> (let [x 2 y 8] (+ x y))
10

user=> (let [x 2 y 8] (= (+ x y) 10))
true

user=> (let [x 3] (+ (* x x) 1))
10

user=> (let [color "Red"] (str "Color is: " color))
"Color is: Red" 

user=> (let [color "Red" phrase (str "Color is: " color)] (str "Clojure says: " phrase))
"Clojure says: Color is: Red"

let ფორმა ქმნის დროებით var-ს (x და y ამ შემთხვევაში), რომლის გამოყენება შეიძლება მხოლოდ let გამოსახულების შიგნით. ვექტორი გამოიყენება ამ var-ის და მისი მნიშვნელობის განსაზღვრისთვის, ვექტორი აგრეთვე გამოიყენება სხვა Clojure ფორმების მიერ დროებითი ცვლადების და მათი მნიშვნელობების განსაზღვისათვის. ვექტორი შეიცავს სახელი-მნიშვნელობის წყვილებს.