; prefix notation
(+ 1 1) -> 1 + 1 ;
; call nesting
(println (+ 1 2 )) ->  println(1 + 2);
; interop
(.length "abc")
	    
	   
; vector
[1 2 3]
; list 
'(1 2 3)
; map 
{1 2}
	     
	  
	   
; define a value
(def a 2)
(defn -main [name]
  (println "hello " name))
(defn scope []
  (let [a 1 b 2]
    (println a b))) ; 1 2 
	    
	   
(while true
  (println 1))
(if (= a 2) 
   (println "its two")
   (println "not two"))
(when foo (println "im foo"))
(loop [i 0]
 (if (= i 10)
   (println "got to 10!")
   (recur (inc i))))
	     
	  
	    
; many to many channel
; can serve many puts/takes
(def c (chan))
; nil since its empty
(take! c (fn [v] (println v)))
; triggers the print 
(put! c "hello world")
            
	   
(def c (chan))
;<!! means: < writes into, !! blocks and not transaction safe
(future (println "done" (>!! c 42)))
; once delivered prints 42
(future (println "Got!" (<!! c)))
; same as future but returns a channel
(println "It works!" (<!! (thread 42)))
          
	  
	    
; returns a many to many channel
(go 42)
(<!! (go 42))
; notice the use of <! vs <!!
(<!! (go (println "It works!" (<! (go 42)))))
         
	    
	   
(def fbc (chan 1)) 
(go (>! fbc 1)
    (println "done"))
(go (>! fbc 2)
    (println "done")) 
(<!! fbc)
(<!! fbc) 
	    
	    
	   
; sliding-buffer drops from start
(def fbc (chan (dropping-buffer 1)))
(go (>! fbc 1)
    (println "done"))
(go (>! fbc 2)
    (println "done")) 
; we will get only 1 (2 was thrown away)
(<!! fbc)
	     
	   
(def c (chan))
(close! c)
    
; we get back nil
(<!! c)
	    
	    
	   
(def lookups (chan (dropping-buffer 100)))
(def answers (chan (dropping-buffer 100)))
(defn accept-loop []
  (go 
    (while true
      (let [pkt (packet (byte-array 1024))]
        (.receive @udp-server pkt)
        (>! lookups pkt)))))
	   
	   
(defn process-loop []
  (go 
    (while true
      (let [pkt (<! lookups) 
            message (Message. (.getData pkt)) 
            record (.getQuestion message) 
            host (.toString (.getName record) false)
            ip (get-host (normalized-host host))]
        (when ip
          (.addRecord message (record-of host (into-bytes ip)) Section/ANSWER))
        (.setData pkt (.toWire message))
        (>! answers pkt)))))
        
	   
(defn reply-loop []
  (go
    (while true
     (let [pkt (<! answers)] 
       (.send @udp-server pkt))))) 
           
        
(def a (chan))
(def b (chan))
(put! a 42)                    
; will return [42 channel-with-response]
(alts!! [a b])  
(alts!! [a :default :meh]) 
	     
	   
(<!! (timeout 1000))
  
; [nil timeout-channel] 
(alts!! [a (timeout 1000)]) 
; alt with a write no takers so [nil timeout-channel] 
(alts!! [[a 42] (timeout 1000)]) 
	     
	   
(put! a 1)
(put! b 2)
; order will is random (prevent starving)
(alts!! [a b]) 
; we can have priority by ordering
(alts!! [a b] :priority true) 
	     
	   
(def to-mult (chan 1))
(def m (mult to-mult))
(dotimes [n 4]
  (let [c (chan 1)]
    (tap m c)
    (go 
      (while true
         (when-let [v (<! c)]
           (println "Got! " v)
         (println "Exiting!"))))))
(>!! to-mult 42)
(>!! to-mult 43)
(close! to-mult)
 
	   
(def to-pub (chan 1))
(def p (pub to-pub :type))
(let [c (chan 1)]
  (sub p :error c)
    (go 
      (while true
        (when-let [e (<! c)]
   	   (println "got an error" e)))))
(>!! to-pub {:type :error :msg "bad thing"})
(close! to-pub)
 
     
(let [render (render-loop 40)]
  (loop [i 0]
    (when (< i (* width height))
      (go 
        (while true
          ; sleeping for a random time
          (<! (timeout (+ 1000 (rand-int 10000))))
          ; passing position and color 
          (>! render [(rand-int 10000) (rand-int 10)])))
      (recur (inc i)))))
       
    @narkisr https://github.com/narkisr