Лекция 2
Мы умеем вводить из консоли:
(defn hello []
(let [input (read-line)]
(println "Hello, " input)))
(hello)
;Aboba228
;Hello, Aboba228
Умеем много вводить из консоли:
(defn hello []
(let [input (read-line)]
(if (= "." input) nil
(do (println "Hello, " input) (recur)))))
(hello)
; hello
; Hello, hello
; clojure
; Hello, clojure
; .
;
; Process finished with exit code 0
Умеем считать более умные штуки:
(defn rsum []
(loop [sum 0]
(let [input (read-line)]
(if (= "." input)
sum
(let [sum' (+ sum (read-string input))]
(println "sum = " sum')
(recur sum')
)
))
))
(rsum)
; 10
; sum = 10
; 20
; sum = 30
; 30
; sum = 60
; .
; Process finished with exit code 0
Вот так произвольные штуки
(defn io [f input output]
(spit output (f (slurp input))))
Пользоваться иожем так:
(io (fn [input] (apply str (mapv #(str "Hello, " % "\n") (clojure.string/split-lines input))))
"data/hello.in"
"data/hello.out"
)
; "hello.in"
; Aboba
; hi hi
;
; "hello.out"
; Hello, Aboba
; Hello, hi hi
(type (read-string "10")) ;Java.lang.Long
(type (read-string "(+ 10 x (* x y))")) ;clojure.lang.PersistentList
(mapv type (read-string "(+ 10 x (* x y))")) ;clojure.lang.Symbol java.lang.Long clojure.lang.PersistentList
read-string читает в кложурские формы
'y
- обозначает символ y
(def expr (read-string "(+ 10 x (* x y))"))
(def x 10)
(def y 20)
(eval expr) ;220
(def y 200)
(eval expr) ;2020
(defn trace [value]
(println "\t\t" value)
value)
(defn add [x y]
(trace "add")
(+ x y ))
(add (trace 10) (trace 20))
; 10
; 20
; add
; Аппликативный порядок
(defn add [x y]
(trace "add")
(+ (eval x) (eval y) ))
(add '(trace 10) '(trace 20))
;add
;10
;20
; оно может несколько раз считать одно и то же
; Нормальный порядок
; Есть ленивый порядок!
(defn add [x y]
(trace "add")
(+ (force x) (force y) ))
(add (delay(trace 10)) (delay(trace 20)))
ГК: сейчас мы будем наглеть
;мы ушли в свой неймспейс ks
(defn cons [h t] [h t])
(defn first [[h t]] h)
(defn rest [[h t]] (force t))
(def empty nil)
(defn empty? [stream] (= empty stream))
(defn count [stream]
(if (empty? stream) 0) 0 (inc (count (rest stream))))
(defn to-list [stream]
(if (empty? stream) ()
(c/cons (first stream)
(to-list (rest stream))
))
)
(defn map [f stream]
(if (empty? stream) empty)
(c/cons (f (first stream))
(map (rest stream))
)
)
(defn filter [p? stream]
(if (empty? stream) empty
(let [tail (filter p? (rest stream))]
(if (p? (first stream))
(cons (first stream) tail)
tail))))
(defn take [n stream]
(cond (empty? stream) empty
(pos? n) (cons (first stream) (take (dec n) (rest stream)))
:else empty))
(defn take-while [p? stream]
(cond (empty? stream) empty
(p? (first-stream)) (cons (first stream) (take-while p? (rest stream)))
:else empty))
(defn some [p? stream]
(cond (empty? stream) false
(p? (first-stream)) true
:else (some p? (rest stream))))
(defn every [p? stream]
(cond (empty? stream) true
(p? (first-stream)) (every p? (rest stream))
:else false))
Создадим всякие приколы:
(def ones (ks/cons 1 (delay ones)))
(defn ints [n]
(ks/cons s (ints (inc n))))
Получили бесконечную структуру данных!
(def primes
letfn(prime? [n]
(not (ks/some #(zero? (mod n %) )
(ks/take-while #(>= n (* % %)) primes)
)))
(ks/cons 2 (ks/filter prime? (ints 3))))
; ГК забыл делей у функций в cs
(def lazy-ints [n] (lazy-seq n (lazy-ints (inc n))))
(def primes
letfn(prime? [n]
(not (some #(zero? (mod n %) )
(take-while #(>= n (* % %)) primes)
)))
(lazy-seq 2 (filter prime? ())))
(apply vector (take 30 primes ))
Есть отображение:
{"x" 1 "y" 2}
(type {"x" 1 "y" 2}) ; clojure.lang.PersistentArrayMap
(map? {"x" 1 "y" 2}) ; true
(empty? {"x" 1}) ;false
(contains? {"x" 1} "x") ; true
(contains? {"x" 1} "y") ; false
(contains? {"x" 1} 1) ; false
(count {"x" 1 "y" 2}) ; 2
(get {"x" 1 "y" 2} "x") ;1
(get {"x" 1 "y" 2} "z") ;nil
(keys {"x" 1 "y" 2} ) ; (x y)
(vals {"x" 1 "y" 2}) ; (1 2)
(assoc {"x" 1 "y" 2} "z" 3) ; добавило z
(assoc {"x" 1 "y" 2} "z") ; убавило я