Created
December 16, 2014 20:18
-
-
Save lsgrep/cdd7d7999d0f1ffc9e77 to your computer and use it in GitHub Desktop.
playing with clojure
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns learn.core | |
(:require [clojure.core.async :refer [chan sliding-buffer go go-loop | |
timeout >! <!]]) | |
(:require [clojure.core.reducers :as r]) | |
(:require [clj-http.client :as http]) | |
(:require [org.httpkit.client :as httpkit]) | |
(:require [clojure.java.io :as io]) | |
(:require [net.cgrand.enlive-html :as html]) | |
(:use [clojure.java.shell :only [sh]]) | |
(:require [clojure.string :as str]) | |
(:require [clojure.tools.trace :as trace]) | |
(:require [clojure.edn :as edn]) | |
(:require [clojure.repl :refer [find-doc doc source]]) | |
(:require [clojure.data.json :as json]) | |
(:require [clojure.core.logic :as logic]) | |
(:require [clojure.tools.cli :as cli]) | |
(:require [clj-mmap :as mmap]) | |
(:require [iota :as iota]) | |
(:require [taoensso.nippy :as nippy]) | |
(:use [slingshot.slingshot :only [try+ throw+]]) | |
(:import java.lang.Runtime) | |
(:import [java.io PushbackReader StringReader RandomAccessFile StringWriter]) | |
(:import [java.net Socket]) | |
(:import [jline.console ConsoleReader]) | |
(:gen-class)) | |
(str/split (:out (sh "ls")) #"\n") | |
;;String manipulation str | |
(str/capitalize "this is quite unproper thing to do") | |
(str/lower-case "COLUMN_HEADER_ONE") | |
(str/upper-case "Dépêchez-vous, l'ordinateur!") | |
;; managing whitespaces | |
(str/trim " \t Bacon ipsum dolar sit.\n ") | |
(str/replace "Who\t\n\n\n\r\t all this \f whitespace here?" #"\s+" " ") | |
(str/triml " Colum header \t") | |
(str/trimr "\t\t\t\t\tSecond Level bullet. \n") | |
(def lines ["#! /bin/bash \n " | |
"du -a ./ | sort -n -r -r \n"]) | |
(str lines) | |
(apply str lines) | |
(str "asdfasd" " " "Doe...." ) | |
(def first-name "John") | |
(def last-name "Doe") | |
(def age 42) | |
(apply str "A" "B" "C") | |
(str "a" "b" "c") | |
(def header "first_name,last_name,employee_number\n") | |
(def rows ["luke,vanderhart,1" "ryan,neufeld,2"]) | |
(apply str header ( interpose "\n" rows)) | |
(def food-items ["milk" "butter" "flour" "eggs"]) | |
(str/join "," food-items) | |
(str/join (vec (range 4))) | |
;; String as seqs | |
(seq "Hello, World!, Emacs rocks and So does Clojure") | |
(frequencies (str/lower-case "An adult all about Pussies")) | |
(defn yelling? | |
"is every letter capitalized?" | |
[s] | |
(every? #(or (not (Character/isLetter %)) | |
(Character/isUpperCase %)) | |
s)) | |
(yelling? "LOUD noises!") | |
(yelling? "LOUD, VERY LOUDF") | |
;; you don't have to space Clojure | |
( apply str [\H \e \l \l \o \, \space \w \o \r \l\d\!]) | |
;;integer string intera manipulation | |
(int \a) | |
(int \b) | |
(int \c) | |
(char 97) | |
(def codes [115 101 99 114 101 116 32 109 101 115 115 97 103 101 115]) | |
( apply str (map char codes)) | |
;; actually this is pretty , pretty cool | |
(map char (range 0x0410 0x042F)) | |
(def me {:first-name "Ryan" :favorate-language "Clojure"}) | |
;;you access map values either way | |
(str "My name is " (:first-name me) ", and I like to program in " (me :favorate-language)) | |
(apply str (interpose " " [ 1 2.000 (/ 3 1) (/ 4 9)])) | |
;; string formatting | |
(defn filename | |
"generate sortable filename" | |
[name i] | |
(format "%03d-%s" i name) | |
) | |
(filename "kickass" 1 ) | |
;; string width control | |
(defn tableify [row] | |
(apply format "%-20s | %-20s | %-20s" row)) | |
(def header ["first name" , "Last Name", "Employee ID"]) | |
(def employees [["Ray" "Neufeld", 2] | |
["Luke","Vanderhart" ,1]]) | |
(print header) | |
(->> (concat [header] employees) | |
(map tableify) | |
(mapv println)) | |
(str first-name ", " last-name "- age:" age) | |
;; applying str for seqs | |
( apply str "C3P0, R2D2:" [\W \h \y \v \h \f \ \P \n \r \f \n \e]) | |
(re-find #"\d+" "Mine is 7 inch") | |
;;debugging with a macro | |
(defmacro dbg[x] `(let [x# ~x] (println "debug:" '~x "=" x#) x#)) | |
(print (+ (* 3 4) (dbg (* 8 9)))) | |
(defn ^:dynamic fib[n] (if (< n 2) n (+ (fib ( - n 1 )) (fib (- n 2))))) | |
;;trace out coude execution, but you have to mark function as ^:dynamic | |
(trace/dotrace [fib] (fib 3)) | |
;; http related testing | |
;;(print (:status (http/get "http://clojure.org"))) | |
;(:status (http/get "http://clojure.org")) | |
;; ( -> ( http/get "http://clojure.org") | |
;; :headers | |
;; (get "server") | |
;; ) | |
;;regular expressions | |
;; re-find matches portions of string | |
(re-find #"\w+" "this is quite awesome....") | |
;; re-matches is a full string/regex match | |
(re-matches #"\w+" "my-param") | |
;; extracting simple words from a sentences | |
(re-seq #"\w+" "Don't go gentle into that good night") | |
(re-seq #"\d{3}-\d{4}" "my phone number is 455-4543") | |
(defn match-mentions | |
[tweet] | |
(re-seq #"(#|@)(\w+)" tweet) | |
) | |
(match-mentions "@asadf #asdfasdf fuck yeah") | |
;; string replace | |
(def about-me "My favourate color is green") | |
(str/replace about-me "green" "red") | |
;; linkify comment | |
(defn linkify-comment | |
[repo comment] | |
(str/replace comment #"#(\d+)" | |
(str "[#$1](https://github.com" repo "/issues/$1)")) | |
) | |
(linkify-comment "next/big-thing" "As soon as we fix #42 and #1337 we | |
should be set to release ") | |
;;tokenizing | |
(str/split "Header1, Header2, Header3 " #",") | |
(str/split "Spaces Newlines\n\n" #"\s+") | |
(def data-delimiters #"[ : -]") | |
(str/split (str (java.util.Date.)) data-delimiters) | |
;; keyword , name etc | |
(name :wonderful) | |
(keyword (name :wonderful)) | |
(name :user/valid?) | |
(namespace :user/valid?) | |
(.substring (str :user/valid?) 2) | |
(def shopping-area "bakery") | |
(keyword shopping-area "bagels") | |
(symbol shopping-area) | |
;; 'will turn arithmetic operation to big style | |
(*' 9999 9999 9999 9999 9999) | |
;; math ops | |
(/ 1 3) | |
(type (/ 1 3 )) | |
(+ (/ 1 3) 0.3) | |
(+ (/ 1 3 ) 3) | |
(rationalize 0.3) | |
(+ (/ 1 3 ) (rationalize 0.3)) | |
(Integer/parseInt "234") | |
(Double/parseDouble "2.234") | |
(bigdec "3.141592653589793238462643383279502884197") | |
(bigint "2345234564562346346723973245978239048502456723452345") | |
(int 2.0001) | |
(int 2.999999999) | |
(Math/round 2.9999999) | |
(Math/round 3.013452345) | |
(Math/round 3.499999) | |
(Math/round (+ 2.496 0.5)) | |
(Math/floor 2.9999) | |
(with-precision 3 (/ 7M 9)) | |
(with-precision 1 :rounding FLOOR (/ 7M 9)) | |
(with-precision 3 (/ (bigdec 1 ) 3)) | |
;; fuzzy equals | |
(defn fuzzy= [tolerance x y ] | |
(let [diff (Math/abs (- x y))] | |
(< diff tolerance))) | |
(fuzzy= 0.01 10 10.0001) | |
(def equals-within-ten? (partial fuzzy= 10)) | |
(equals-within-ten? 109 100) | |
;;trigs | |
(defn sin-plus [ a b ] | |
(+ (* (Math/sin a) (Math/cos b)) | |
(* (Math/sin b) (Math/cos a)))) | |
(sin-plus 0.1 0.3) | |
(Integer/toString 34 2) | |
(Integer/toString 234345 16) | |
(defn to-base [n radix] | |
(Integer/toString radix n)) | |
(def two-base | |
(partial to-base 2 )) | |
(two-base 23345) | |
(defn mean | |
[coll] | |
(let [sum (apply + coll) | |
count (count coll)] | |
(if (pos? count) | |
(/ sum count) | |
0)) | |
) | |
(mean []) | |
(def fs-flags [:owner-read :owner-write | |
:group-read :group-write | |
:global-read :global-write]) | |
(def bitmap (zipmap fs-flags | |
(map (partial bit-shift-left 1) (range)))) | |
(print bitmap) | |
(defn permissions-int [& flags] | |
(reduce bit-or 0 (map bitmap flags))) | |
(def owner-only (permissions-int :owner-read :owner-write)) | |
(Integer/toBinaryString owner-only) | |
(def read-only ( permissions-int :owner-read :group-read :global-read)) | |
(Integer/toBinaryString read-only) | |
(defn able-to? [permissions flag] | |
(not= 0 (bit-and permissions (bitmap flag)))) | |
(able-to? read-only :global-read) | |
(able-to? read-only :global-write) | |
;; random numbers | |
(rand) | |
(rand-int 10) | |
(rand-nth [ 1 3 4]) | |
(rand-nth '(:a :b :c)) | |
(rand-nth (seq #{:heads :tails})) | |
(shuffle (range 10)) | |
(java.util.UUID/randomUUID) | |
(java.util.UUID/randomUUID) | |
;; date | |
(defn now [] | |
(java.util.Date.)) | |
(System/currentTimeMillis) | |
;; write files | |
(defn save [uri file] | |
(with-open [in (io/input-stream uri) | |
out (io/output-stream file)] | |
(io/copy in out) | |
(print "copying " file " don"))) | |
;; keywords to filter | |
(def ml-keywords ["machine learning" "artificial intelligence" "deep learning" "gaussian" ]) | |
(def math-keywords ["regression" "statistics" ]) | |
(def traning-keywords ["lynda" "pluralsight" "ttc" ]) | |
(def universities-keywords ["stanford" "mit" ]) | |
;; file operations | |
(defn readgzfile [file] | |
(with-open [ in (java.util.zip.GZIPInputStream. | |
(io/input-stream file)) | |
rdr (io/reader in)] | |
(print "reading stuff") | |
(doseq [line (line-seq rdr) | |
w ml-keywords] | |
(if (re-find (re-pattern (str "(?ix)" w)) line ) | |
( println line))))) | |
;(save "https://kickass.to/hourlydump.txt.gz" "/tmp/hourly.txt.gz") | |
;(readgzfile "/tmp/hourly.txt.gz") | |
(defn remote-server-receive-date [] | |
(-> (str (java.util.Date.)) | |
(StringReader.) | |
(PushbackReader.))) | |
;;read date from server.fucking awesome and i like it very much.. | |
(edn/read (remote-server-receive-date)) | |
;; date compare | |
(defn now [] (java.util.Date.)) | |
(def one-second-ago (now)) | |
(Thread/sleep 1000) | |
(compare (now) one-second-ago) | |
(compare one-second-ago one-second-ago) | |
;;generating dates and data | |
(def daily-from-epoch | |
(let [start-date (java.util.GregorianCalendar. 1970 0 0 0 0)] | |
(repeatedly | |
(fn [] | |
(.add start-date java.util.Calendar/DAY_OF_YEAR 1) | |
(.clone start-date))))) | |
(take 2 daily-from-epoch) | |
(def end-of-feb (take 2 (drop 57 daily-from-epoch))) | |
(println end-of-feb) | |
(map class end-of-feb) | |
;; | |
(defn daily-from-year [& [start-year]] | |
(let [start-date (java.util.GregorianCalendar. (or start-year 1970) | |
0 0 0 0 )] | |
(repeatedly | |
(fn [] | |
(.add start-date java.util.Calendar/DAY_OF_YEAR 1) | |
(.clone start-date))))) | |
(take 3 ( daily-from-year 1999)) | |
(take 2 (daily-from-year)) | |
;;set related stuff, actually this is fun | |
(time (dotimes [_ 100] (set (vec (range 1e5))))) | |
(time (dotimes [_ 100] (into #{} (vec (range 1e5))))) | |
(into (sorted-set) (range 100)) | |
(into (sorted-set) (shuffle (range 2000))) | |
(into (sorted-set) "awesome ,I love clojure so much,and I can't live without") | |
(def alphabet-str (str/upper-case (apply str (map char (range (int \a) (+ 1 (int \z))))))) | |
(def alphabet (into (sorted-set) alphabet-str)) | |
(last alphabet) | |
(sorted-set-by > 1 2 3 4 5 6 6 ) | |
(conj #{ :a :b :c} :d) | |
(conj #{:a :b :c} :d :e) | |
(def my-set #{:red :white :blue}) | |
(contains? my-set :blue) | |
(get my-set :azure :i-am-not-spaniard) | |
(my-set :blue) | |
(take 10 (filter #{ 1 3 4} (take 1000 (repeatedly #(rand-int 10) )))) | |
(clojure.set/union #{:white :black} #{:red :black}) | |
(clojure.set/intersection #{:white :black } #{:red :black} #{:black :awesome}) | |
(clojure.set/difference #{:red :white :blue :yellow} #{:red} #{:white}) | |
(clojure.set/subset? #{:blue :white } #{:blue :white :red}) | |
(clojure.set/subset? #{:blue :white} #{:zuere :zoe}) | |
;; map manipulation | |
{1 2 3 4 5 6 7 8 9 10} | |
(array-map [1 2 ] [ 3 4]) | |
(sorted-map [ 1 2 ] [ 3 4]) | |
(hash-map [ 34 5 ] [ 345 24]) | |
(get {:name "Kvothe" :class "Bard" } :name) | |
(get {:name "awesome" :class "something"} :dick) | |
(get {:name :something} :else :ahha) | |
(:name {:name :aasdfasd}) | |
(:name {:names :asdfsad} :ahadfasdasd) | |
(def characters (hash-map (vec alphabet) (vec alphabet))) | |
(hash-map 21 34 4 5 ) | |
(def beans {:blue 10 :red 3 :green 1}) | |
(select-keys beans [:blue]) | |
(vals beans) | |
(reduce + (vals beans)) | |
((juxt :blue :red) beans) | |
((juxt :a :b) beans) | |
;; map sequencing.. | |
(def mymap {:a 1 :b 2 :c 3}) | |
(seq mymap) | |
(conj mymap [ :e 30]) | |
(into {} [[ 1 3] [ 3 4]]) | |
(zipmap [1 3 4 ] [:a :b :c]) | |
;; entry | |
(def entry (first {:a 1 :b 2})) | |
(class entry) | |
(key entry) | |
(val entry) | |
(source doc) | |
(find-doc #"defmacro") | |
(doc +) | |
(doc +') | |
;; Polymorphic Behavior | |
;; (defn area | |
;; "calculate the area of a shape" | |
;; [shape] | |
;; (let [height (:height shape) base (:base shape)] | |
;; (condp = (:type shape) | |
;; :triangle (* height base (/ 1 2)) | |
;; :rectangle (* height base) | |
;; ))) | |
;; (area {:type :triangle :base 2 :height 4}) | |
;; (area {:type :rectangle :base 20 :height 10}) | |
;; real polymorph | |
(defmulti area | |
"calculate the area of a shape" | |
:type | |
) | |
(defmethod area :rectangle [shape] | |
(* (:length shape) (:width shape))) | |
(defmethod area :circle [shape] | |
(* (. Math PI) (:radius shape) (:radius shape))) | |
(area {:type :rectangle :length 2 :width 4}) | |
(area {:type :circle :radius 3}) | |
(defprotocol Shape | |
(area [s]) | |
(perimeter [s])) | |
(defrecord Rectangle [length width] | |
Shape | |
(area [this] (* length width)) | |
(perimeter [this] (+ (* 2 length) | |
(* 2 width)))) | |
(->Rectangle 2 4 ) | |
(area (->Rectangle 2 4)) | |
(perimeter (->Rectangle 2 4 )) | |
;;polymorphism with better lives | |
(defmulti convert | |
"convert one type to another" | |
(fn [request thing] | |
[(:input-format request ) (:output-format request)])) | |
(defmethod convert [:edn-string :clojure] | |
[_ str] | |
(edn/read-string str)) | |
(defmethod convert [:clojure :json] | |
[_ thing] | |
(clojure.data.json/write-str thing)) | |
(:foo (convert {:input-format :edn-string | |
:output-format :clojure} | |
"{:foo :barr}")) | |
(convert {:input-format :clojure | |
:output-format :json} | |
{:foo [:bar :baz]}) | |
(area | |
(let [b 2 | |
h 3] | |
(reify Shape | |
(area [this] (* b h)) | |
(perimeter [this] (* 2 ( + b h)))))) | |
;; extend existing stuff of Clojure | |
(defprotocol Person | |
(first-name [person]) | |
(last-name [person])) | |
(extend-type String | |
Person | |
(first-name [s] (first (str/split s #" "))) | |
(last-name [s] (second (str/split s #" ")))) | |
(first-name "john") | |
(last-name "john smith") | |
;; core async stuff , quite fascinating. | |
(defn database-consumer | |
"accept messages and persist them to a database" | |
[] | |
(let [in (chan (sliding-buffer 64))] | |
(go-loop [ data (<! in)] | |
(when data | |
(println (format "database consumer received data %s" data)) | |
(recur (<! in)))) | |
in)) | |
(defn sse-consumer | |
"accept messages and pass them to web browsers via sse" | |
[] | |
(let [in (chan (sliding-buffer 64))] | |
(go-loop [data (<! in)] | |
(when data | |
(println (format "sse-consumer received data %s" data)) | |
(recur (<! in)))) | |
in)) | |
(defn messages | |
[] | |
(range 4)) | |
(defn producer | |
[& channels] | |
(go | |
(doseq [msg (messages) | |
out channels] | |
(<! (timeout 100)) | |
(>! out msg)))) | |
(producer (database-consumer) (sse-consumer)) | |
;;fibo, not so efficient but quiet good for the eye. | |
(def fibo (lazy-cat [ 0 1] | |
(map +' fibo ( rest fibo)))) | |
(take 10 fibo) | |
(take 20 fibo) | |
(take 40 fibo) | |
(take 50 fibo) | |
(take 51 fibo ) | |
(take 60 fibo) | |
(take 80 fibo) | |
(take 90 fibo ) | |
(take 100 fibo) | |
(take 120 fibo) | |
(take 200 fibo ) | |
(take 500 fibo) | |
;; this is kinda awesome... | |
(reduce + (take-while (partial >= 4000000) | |
(filter odd? fibo))) | |
;; this is too | |
(defn fibo2 [n] | |
(->> [ 1 1] | |
(iterate (fn [[a b]] [b (+ a b) ] )) | |
(map first) | |
(take n))) | |
;;let's learn more about transducers | |
(defn mean-reducer [memo x] | |
(-> memo | |
(update-in [:sum]+ x) | |
(update-in [:count] inc))) | |
(reduce mean-reducer {:sum 0 :count 0} (range 10)) | |
(defn increment-transducer [f1] | |
(fn [result input] | |
(f1 result | |
(inc input)))) | |
;; add functions, this is kinda awesome.CSP rocks.. | |
(reduce (increment-transducer mean-reducer ) | |
{:sum 0 :count 0} | |
(range 10)) | |
;; after upgrading everything works perfectly. | |
(reduce ((map inc) mean-reducer) | |
{:sum 0 :count 0} | |
(range 10 )) | |
;;a version without transducers | |
(->> (range 10 ) | |
(map inc) | |
(reduce mean-reducer | |
{:sum 0 :count 0})) | |
;;sequence to retrun a new transduced sequence | |
(sequence (map inc) (range 10)) | |
;;(transduce (map inc ) mean-reducer {:sum 0 :count 0} (range 10)) | |
;;(int [] (map inc) ( range 10 )) | |
(defn -main | |
[& args] | |
;; work around dangerous default behaviour in clojure | |
(println args) | |
(let [[opts args banner] (cli/cli args | |
["-h" "--help" "Print this help" | |
:default false :flag true])] | |
(println opts) | |
(println args) | |
(println banner) | |
) | |
(alter-var-root #'*read-eval* (constantly false))) | |
(def movie-graph | |
;;top level stuff | |
[ | |
[:a1 :type :FilmStudio] | |
[:a1 :name "Enterprise"] | |
[:a1 :FilmCollection :a2] | |
;; collection | |
[:a2 :type :FilmCollection] | |
[:a2 :Film :a3] | |
[:a2 :Film :a6] | |
[:a3 :type :Film] | |
[:a3 :name "Memento"] | |
[:a3 :cast :a4] | |
[:a4 :type :FilmCast] | |
[:a4 :director :a5] | |
[:a5 :type :Person] | |
[:a5 :name "Christopher Nolan"] | |
[:a6 :type :Film] | |
[:a6 :name "The Usual Suspects"] | |
[:a6 :cast :a7] | |
[:a7 :type :FilmCast] | |
[:a7 :director :a8] | |
[:a8 :type :Person] | |
[:a8 :name "Bryan Singer"] | |
]) | |
(defn directors-at | |
[graph studio-name] | |
(logic/run* [director-name] | |
(logic/fresh [studio film-coll film cast director] | |
;; studio related stuff | |
(logic/membero [studio :name studio-name] graph) | |
(logic/membero [studio :type :FilmStudio] graph) | |
(logic/membero [studio :FilmCollection film-coll] graph) | |
(logic/membero [film-coll :type :FilmCollection] graph) | |
(logic/membero [film-coll :Film film] graph) | |
(logic/membero [film :type :Film] graph) | |
(logic/membero [film :cast cast] graph) | |
(logic/membero [cast :type :FilmCast] graph) | |
(logic/membero [cast :director director] graph) | |
(logic/membero [director :type :Person] graph) | |
(logic/membero [director :name director-name] graph) | |
))) | |
;; this is logic matching related stuff | |
(directors-at movie-graph "Enterprise") | |
(logic/run 1 [q] | |
(logic/== 1 q)) | |
(logic/run 1 [q] | |
(logic/== q 1)) | |
(logic/run 1 [q] | |
(logic/== [ 1 2 3] | |
[ 1 2 q])) | |
(logic/run 1 [q] | |
(logic/== ["foo" "bar" "baz"] | |
[q "bar" "baz"])) | |
(logic/run 1 [q] | |
(logic/== 1 q) | |
(logic/== 2 q)) | |
(logic/run 1 [q] | |
(logic/fresh [ x y z] | |
(logic/== x 1) | |
(logic/== y 2) | |
(logic/== z 3) | |
(logic/== q [x y z]))) | |
(logic/run 1 [q] | |
(logic/membero q [1])) | |
(logic/run 1 [q] | |
(logic/membero 1 q)) | |
;; end of logic , this is quite amazing. | |
(println "Normally text are printed to STDOUT") | |
(do | |
(print "a") | |
(print "b")) | |
(binding [*out* *err*] | |
(println "haha")) | |
;;read console input | |
(defn show-keystroke [] | |
(print "Enter anything:") | |
(let [cr (jline.console.ConsoleReader. ) | |
keyint (.readCharacter cr)] | |
(println (format "Got %d ('%c')!") keyint (char keyint)) | |
)) | |
(->> "resources/people.edn" | |
io/resource | |
slurp | |
edn/read-string | |
(map :language)) | |
;; you need to the directory right | |
(io/copy | |
(io/file "src/resources/people.edn") | |
(io/file "src/resources/poeple.edn.io")) | |
;; clojure does not know ~ epxression in file path. keep that in mind. | |
(io/copy "测试" | |
(io/file "/tmp/clj.txt") | |
:encoding "UTF-8") | |
;;delete file,throws exception if file does not exist. | |
(io/delete-file "/tmp/clj.txt") | |
;; delete file silently | |
(io/delete-file "/tmp/clj.txt" true) | |
;; do it with try catch. | |
(try | |
(io/delete-file "/tmp/clj.txt") | |
(catch Exception e (str "exception:" (.getMessage e)))) | |
;;reading file content | |
(with-open [file (mmap/get-mmap "/tmp/clj.txt")] | |
(let [n-bytes 10 | |
file-size (.size file) | |
first-n-bytes (mmap/get-bytes file 0 1) | |
;; last-n-bytes (mmap/get-bytes file (- file-size n-bytes) n-bytes) | |
] | |
(println file-size) | |
[(String. first-n-bytes "UTF-8")] | |
)) | |
;; put something into this file... | |
;; (with-open [file (mmap/get-mmap "/tmp/clj.txt")] | |
;; (let [bytes-to-write (.getBytes "This is quite awesome" "UTF-8")] | |
;; (mmap/put-bytes file bytes-to-write 0))) | |
;; there is some issue with this code | |
;; (with-open [file (mmap/get-mmap "/tmp/clj.txt")] | |
;; (println (.size file)) | |
;; (let [bytes-to-write (.getBytes "This is the best")] | |
;; (mmap/put-bytes file bytes-to-write 0))) | |
(def my-file "/tmp/clj.txt") | |
(spit my-file "مەن") | |
(slurp my-file) | |
(slurp my-file :encoding "UTF-8") | |
(spit my-file "even more stuff\n" :append true) | |
;;read file by lines | |
(with-open [r (io/reader my-file )] | |
(doseq [line (line-seq r)] | |
(println line) | |
)) | |
(def my-temp-file (java.io.File/createTempFile "empire" ".txt")) | |
(with-open [file (io/writer my-temp-file)] | |
(binding [*out* file] | |
(dotimes [n 10] | |
(println n "awesome\n")))) | |
(slurp my-temp-file) | |
(.getAbsolutePath my-temp-file) | |
(.deleteOnExit my-temp-file) | |
;(.delete my-temp-file) | |
(doto (RandomAccessFile. "/tmp/longfile" "rw") | |
(.seek (* 1024 1024 1024)) | |
(.writeInt 1024) | |
(.close) | |
) | |
(.length (io/file "/tmp/longfile")) | |
;; read random access file and read the fucking number | |
(let [raf (RandomAccessFile. "/tmp/longfile" "r") | |
_ (.seek raf (* 1024 1024 1024)) | |
result (.readInt raf)] | |
(.close raf) | |
result) | |
;; multi processor handling | |
(defn pmap-file | |
[processing-fn input-file output-file] | |
(with-open [ r (io/reader input-file) | |
w (io/writer output-file)] | |
(let [lines (line-seq r)] | |
(dorun | |
(map #(.write w %) | |
(pmap processing-fn lines)))))) | |
(def acc (atom 0)) | |
(defn- example-row-fn | |
[row-string] | |
(str (swap! acc inc) ":" row-string )) | |
(time (pmap-file example-row-fn "/work/Ch2Uy.txt" "/tmp/output.txt")) | |
;;goodness of pmap | |
(defn long-running-job [n] | |
(Thread/sleep 3000) ; wait for 3 seconds | |
(+ n 10)) | |
(time (dorun ( map long-running-job (range 4)))) | |
(time (dorun (pmap long-running-job (range 4)))) | |
;; reducers | |
(def my-seq (vec (range 1e7))) | |
(take 10 my-seq) | |
(time (reduce + (map inc my-seq))) | |
(time (reduce + (r/map inc my-seq))) | |
(time (r/fold + (r/map inc my-seq ))) | |
(source r/fold) | |
(doc r/coll-fold) | |
(spit "data.clj" (pr-str [:a :b :c])) | |
(read-string (slurp "data.clj")) | |
;;write data structure to a file | |
(with-open [ w (io/writer "data.clj")] | |
(binding [*out* w] | |
(pr (range 1e6)))) | |
;;read a data structure from a file | |
(def variable-from-file (with-open | |
[r (java.io.PushbackReader. (io/reader "data.clj"))] | |
(binding [*read-eval* false] | |
(read r)))) | |
;; read from a file | |
(defn- read-one | |
[r] | |
(try | |
(print (read r)) | |
(catch java.lang.RuntimeException e | |
(if (re-find #"EOF" (.getMessage e)) | |
::EOF | |
(throw e)b)))) | |
;; read all of it till EOF | |
(defn read-seq-from-file | |
[path] | |
(with-open [r (java.io.PushbackReader. (io/reader path))] | |
(binding [*read-eval* false] | |
(doall (take-while #(not= ::EOF %) (repeatedly #(read-one r))))))) | |
;;C-c C-b interrupts evaluation. | |
(read-seq-from-file "data.clj") | |
(defn load-config | |
[filename] | |
(edn/read-string (slurp filename))) | |
(load-config "data.clj") | |
(defn deep-merge | |
[& values] | |
(if (every? map? values) | |
(apply merge-with deep-merge values) | |
(last values))) | |
(json/write-str [{"name" "stefan" "age" 32}]) | |
;; loading a page | |
(slurp "http://bing.com") | |
(:status (http/get "http://clojure.org")) | |
;;get cookies | |
(-> (http/get "http://www.github.com") | |
:cookies | |
keys) | |
(def bing-resutl (http/get "http://bing.com")) | |
;;async get | |
(def bing-response (httpkit/get "http://sina.com.cn")) | |
;;(print "orelly is" (.isReachable (java.net.InetAddress/getByName "orelly.com") 5000)) | |
;;(print "baidu is" (.isReachable (java.net.InetAddress/getByName "baidu.com") 10000)) | |
(defn send-request | |
"send request to port 80" | |
[host port path] | |
(with-open [sock (Socket. host port) | |
w (io/writer sock) | |
r (io/reader sock) | |
response (StringWriter.)] | |
(.append w (str "GET " path "\n")) | |
(.flush w) | |
(io/copy r response) | |
(print (str response)))) | |
(send-request "bing.com" 80 "/") | |
(realized? (range 100)) | |
(realized? (doall (range 100))) | |
(realized? (range 1e8)) | |
(def v [42 "foo" 99.2 [5 12]]) | |
(.get v 2) | |
(nth v 2) | |
(let [x (nth v 0) | |
y (nth v 1) | |
z (nth v 2)] | |
(+ x z)) | |
;; destructuring | |
(def my-vector [:a :b :c :d]) | |
(def my-nested-vector [:a :b :c :d [:x :y :z]]) | |
(let [[a b c d] my-vector] | |
(println a b c d )) | |
(let [[a _ _ d [ x y z ]] my-nested-vector] | |
(print a d x y z)) | |
(let [[a b c] my-vector] | |
(print a b c) | |
) | |
(let [[ a b & the-rest ] my-vector] | |
(print a b the-rest)) | |
(let [[ a b c d e f g] my-vector] | |
(print a b c d e f g) | |
) | |
(def my-hashmap {:a "A" :b "B" :c "C" :d "D"}) | |
(def my-nested-hashmap {:a "A" :b "B" :c "C" :d "D" :q {:x "X" :y "Y" :z "Z"}}) | |
(let [{a :a d :d} my-hashmap] | |
(print a d)) | |
(let [{a :a b :b {x :x y :y} :q} my-nested-hashmap] | |
(print a b x y)) | |
;;when there is nothing to find | |
(let [{a :a b :b not-found :not-found} my-hashmap] | |
(println a b not-found)) | |
;; when there is no such key , you can set default by :or command | |
(let [{a :a not-found :not-found :or {not-found ":)"}} my-hashmap] | |
(println a not-found)) | |
;; destructuring | |
(let [{a :a b :b :as all } my-nested-hashmap] | |
(println a b all)) | |
(let [{:keys [a d]} my-nested-hashmap] | |
(println a d )) | |
(let [{:keys [a b ] ,{:keys [x y]} :q :as all dest :dest :or {dest "fuck you " }} my-nested-hashmap] | |
(println a b x y all dest)) | |
(let [{:keys [ a b not-found] :or {not-found ":D"}} my-hashmap] | |
(println a b not-found)) | |
(let [{:strs [a d]} {"a" "A" "d" "D"} ] | |
(println a d)) | |
(let [{:syms [a d]} {'a "A" 'd "DDDDDD"} ] | |
(println a d)) | |
(let [{:keys [a b]} '(:a "A" :b "BBBBBB")] | |
(println a b )) | |
(defn embedded-rep | |
[] | |
(print (str (ns-name *ns*) ">>>> ")) | |
(flush) | |
(let [expr (read) | |
value (eval expr)] | |
(when (not= :quit value ) | |
(println value) | |
(recur) | |
))) | |
(= "boot" (str "bo" "ot")) | |
(= nil nil) | |
(= false nil) | |
(reduce max (repeatedly 10 rand)) | |
(apply max (repeatedly 10 rand)) | |
;; reducing with works like a charm | |
(reduce | |
(fn [m v] | |
(assoc m v (* v v )) | |
) | |
{} | |
(into [] (range 10))) | |
;; very useful thing to do | |
((complement pos?) 5) | |
((complement string?) "asdfasdf") | |
((complement string?) :hello) | |
(take 10 (repeatedly #(rand-int 10))) | |
;;awesome part | |
(take 3 (repeatedly (fn [] (Thread/sleep 1000) | |
(System/currentTimeMillis)))) | |
(apply hash-map [:a 5 :b 6]) | |
(def args [2 -2 10 ]) | |
(apply * 0.5 3 args) | |
(#(filter string? %) ["a" 5 "b" 6]) | |
(#(filter % [:a "a" "b" :b 6 7 ]) string?) | |
(string? :a) | |
(type :a) | |
(#(map * %1 %2) [ 1 2 3 ] [ 4 5 6] ) | |
;; this does not work with only using map | |
(#(apply map * %&) [ 1 2 3] [ 4 5 6]) | |
;; this is kinda awesome | |
((partial map *) [ 1 2 3] [4 5 6] [7 8 9]) | |
(def negated-sum-str (comp str - +)) | |
(negated-sum-str 10 12 3.4) | |
(def camel->keyword (comp keyword | |
str/join | |
(partial interpose \-) | |
(partial map str/lower-case) | |
#(str/split % #"(?<=[a-z])(?=[A-Z])"))) | |
(camel->keyword "CamelCase") | |
(defn camel-keyword-fun | |
[s] | |
(->> (str/split s #"(?<=[a-z])(?=[A-Z])") | |
(map str/lower-case) | |
(interpose \-) | |
str/join | |
keyword | |
)) | |
(camel-keyword-fun "halaMadridYiNadaMas") | |
'(a b :name 12.5) | |
{Math/PI "~3.141592653589793238462643383279502884197" | |
[:composite "key"] 42 | |
nil "nothing"} | |
(def my-vec [ 1 2 3]) | |
(conj my-vec 4) | |
(conj my-vec 4 5 ) | |
(seq my-vec) | |
(def m {:a 5 :b 6}) | |
(conj m [:c 7]) | |
(seq m) | |
(def s #{1 2 3}) | |
(conj s 10) | |
(conj s 3 4) | |
(seq s) | |
(def lst '(1 2 3)) | |
(conj lst 0) | |
(conj lst 0 -1) | |
(into my-vec [ 4 5 ]) | |
(into m [[:c 7 ] [:d 8]]) | |
(into #{ 1 2}(vec (range 0 19))) | |
(into [1] {:a 1 :b 2}) | |
(conj '(1 2 3) 4) | |
(into '(1 2 3) [:a :b :c]) | |
(defn swap-pairs | |
[sequential] | |
(into (empty sequential ) | |
(interleave | |
(take-nth 2 (drop 1 sequential)) | |
(take-nth 2 sequential)))) | |
(do | |
(println (swap-pairs ( range 10))) | |
(println (swap-pairs (vec (range 10))))) | |
(source conj) | |
(source conj) | |
;;cons will add item to the head ,wheather list or vec | |
(cons 4 [ 1 2]) | |
(cons 4 '(1 2)) | |
;; conj result varies by coll properties | |
(conj [ 1 2 ] 4 ) | |
(conj '(1 2) 4) | |
(log->file "Hello World!") | |
(defn multi-logger | |
[& logger-fns] | |
#(doseq [f logger-fns] | |
(f %))) | |
(def log (multi-logger | |
(print-logger *out*) | |
(file-logger "msg.log"))) | |
(log "Hello Again") | |
(defn timestamped-logger | |
[logger] | |
#(logger (format "[%1$tY-%1$tm-%1$te %1$tH:%1$tM:%1$tS] %2$s" | |
(java.util.Date.) %))) | |
(def log-timestamped (timestamped-logger | |
(multi-logger | |
(print-logger *out*) | |
(file-logger "msg.log")))) | |
(log-timestamped "adios, mi amor") | |
(count [ -1 0 1]) | |
(defn prime? | |
[n] | |
(cond | |
(== 1 n) false | |
(== 2 n) true | |
(even? n) false | |
:else (->> (range 3 (inc (Math/sqrt n) )2) | |
(filter #(zero? (rem n %))) | |
empty? | |
))) | |
(prime? 31) | |
(time (prime? 1125899906842679 )) | |
;; this thing is quite awesome | |
(source memoize) | |
(let [m-prime? (memoize prime?)] | |
(time (prime? 1125899906842679 )) | |
(time (prime? 1125899906842679 )) | |
) | |
(repeatedly 10 ( partial rand-int 10)) | |
(repeatedly 10 ( partial (memoize rand-int) 10)) | |
(defn map-map | |
[f m] | |
(into (empty m) | |
(for [[k v] m] | |
[k (f v)] | |
))) | |
(map-map inc (hash-map :z 5 :c 6 :m 8)) | |
(count {:a 1 :b 2 :c 3}) | |
(count '(1 2 3)) | |
(seq "Clojure") | |
(source seq) | |
(map str "Clojure") | |
(map str (seq "Clojure")) | |
(set "Programming") | |
(first "Clojure") | |
(rest "Clojure") | |
(next "Clojure") | |
(rest [1]) | |
(next [1]) | |
(rest nil) | |
(next nil) | |
(def xx (vec (range 10))) | |
;;they could be the same, in the sense that next could be nill, but the rest will be empty list all the time | |
(= (next xx) | |
(seq (rest xx))) | |
(doseq [x (range 3 )] | |
(println x)) | |
(let [ r ( range 10 ) | |
rst (rest r)] | |
(prn (map str rst)) | |
(prn (map #(+ 100 % ) r )) | |
(prn (conj r -1 ) (conj rst 42)) | |
) | |
(let [s (range 1e6) | |
] | |
(time (count s))) | |
(let [s (apply list (range 1e6))] | |
(time (count s))) | |
(cons 0 ( range 1 5 2)) | |
(cons :a [:b :c :d]) | |
(cons 0 ( cons 1 ( cons 3 ( range 4 10)))) | |
(time (lazy-seq [ 1 2 3 4 5])) | |
(time (seq [ 1 2 3 4 5 ])) | |
(defn random-ints | |
[limit] | |
(lazy-seq | |
(println "realizing random number") | |
(cons (rand-int limit) | |
(random-ints limit)))) | |
(def rands (take 10 ( random-ints 50))) | |
(source iterate) | |
(apply str (reverse "fuck")) | |
(reverse (vec (range 10))) | |
(set "aeiouy") | |
(apply str (remove (set "aeiou") "vowel are useless ! or maybe not ")) | |
(split-with neg? (range -5 5 )) | |
(let [[t d] (split-with #(< % 12) (range 1e8))] | |
[(count d) (count t)] | |
) | |
(def m {:a 1 :b 2 :c 3}) | |
(get m :b) | |
(get m :d) | |
(get m :d "not-found") | |
(assoc m :d 4) | |
(dissoc m :b) | |
(assoc m | |
:x 4 | |
:y 5 | |
:z 6) | |
(def v [1 2 3]) | |
(get v 1) | |
(get v 10) | |
(get v 10 "fc....") | |
(assoc v | |
1 4 | |
0 -12 | |
2 :p) | |
(assoc v 3 10) | |
(get #{ 1 2 3 } 2) | |
(get #{ 1 2 3 4 } 10) | |
(get #{ 1 3 3445 } "not-found") | |
(when (get #{1 2 3 } 2) | |
(println "it contains `2`''")) | |
(contains? [1 2 3] 0) | |
(contains? [ 1 2 3] 3) | |
(contains? {:a 5 :b 6} :a) | |
(contains? #{ 1 2 3} 1) | |
(get "Clojure" 3) | |
(into-array [ 1 2 3]) | |
(doc into-array) | |
(get {:ethel nil} :lucy) | |
(get {:ethel nil} :ethel) | |
(find {:ethel nil} :asdfasd) | |
(find {:a 6 } :a) | |
(if-let [ e ( find {:a 5 :b 6} :a) ] | |
(format "found %s => %s" (key e) (val e)) | |
"not found") | |
(if-let [[k v] (find {:a 5 :b 10} :a)] | |
(format "found %s => %s " k v) | |
"not found" | |
) | |
(nth [ :a :b :c] 2) | |
(get [:a :b :c ] 2) | |
(nth [ :a :b :c] 10) | |
(nth [:a :b :c ] -1) | |
(get [:a :b :c] -1) | |
(nth [:a :b :c] -1 :not-found) | |
(get [:a :b :c ] -1 :not-found) | |
(get 42 0) | |
(nth 42 0) | |
(conj '() 1) | |
(conj '(2 1) 3) | |
(peek '(3 2 1)) | |
(pop '(3 2 1)) | |
(pop '(1)) | |
(conj [] 1) | |
(conj [1 2 ] 3) | |
(peek [ 1 3 4]) | |
(get #{ 1 2 3} 2) | |
(get #{ 345 2345 234 } 100 :not-found-agein) | |
;; disjoining stuff from set | |
(disj #{ 1 2 3} 4 5 3) | |
(def sm (sorted-map :z 5 :x 9 :y 0 :b 2 :a 3 :c 4)) | |
(keys sm) | |
(vals sm) | |
(rseq sm) | |
(subseq sm <= :c) | |
(subseq sm > :b <= :y) | |
(compare 2 2 ) | |
(compare "ab" "abc") | |
(compare "2" "2") | |
(compare [:a :b :c] [:b :c :d]) | |
(sort < (repeatedly 10 #(rand-int 100))) | |
(map-indexed vector "Clojure") | |
((comparator <) 1 4) | |
(sorted-map-by compare :z 5 :x 9 :y 0) | |
(sorted-map-by (comp - compare) :z 5 :x 9 :y 0) | |
(defn magnitude | |
[x] | |
(-> x | |
Math/log10 | |
Math/floor)) | |
(magnitude 1000) | |
(defn compare-magnitude | |
[a b] | |
(neg? (- (magnitude a) (magnitude b )))) | |
(neg? (- (magnitude 10) (magnitude 10))) | |
(source comparator) | |
(source cond) | |
((comparator compare-magnitude) 10 1000) | |
((comparator compare-magnitude) 100 10) | |
((comparator compare-magnitude) 77 77) | |
(sorted-set-by compare-magnitude 10 1000 500) | |
(conj *1 100000) | |
(conj #{10 500 1000} 600) | |
(contains? *1 1239) | |
(defn compare-magnitude | |
[a b] | |
(let [diff (- (magnitude a) (magnitude b))] | |
(if (zero? diff) | |
(compare a b) | |
diff))) | |
(sorted-set-by compare-magnitude 10 1000 50) | |
(conj *1 600) | |
(disj *1 750) | |
(sorted-set-by compare-magnitude 10 1000 500 670 1239) | |
(def ss *1) | |
(subseq ss > 500) | |
(map :name [{:age 21 :name "David"} | |
{:gender :f :name "Suzanne"} | |
{:name "Sara" :location "NYC"}]) | |
(some #{ 1 3 7 }[ 0 2 4 5 6]) | |
(some #{ 1 3 7 }( take-nth 1 (range 10))) | |
(filter :age [{:age 21 :name "David"} | |
]) | |
(remove #{ 5 7 } (cons false (range 10))) | |
(remove (partial contains? #{5 7 false} )(cons false (range 10))) | |
'(1 2 3) | |
(list 1 2 (+ 1 2)) | |
(vector 1 2 3) | |
(vec (range 5 )) | |
(defn euclidian-division | |
[x y] | |
[(quot x y) (rem x y)]) | |
(euclidian-division 42 8) | |
(def point-3d [ 42 26 -7]) | |
(print point-3d) | |
(def travel-legs [["LYS" "FRA"] ["FRA" "PHL"] ["PHL" "RDU"]]) | |
(print travel-legs) | |
#{1 2 3} | |
(hash-set :a :b :c :d) | |
(set [ 1 6 1 8 3 7 7 ]) | |
(apply str (remove (set "aeiou") "vowels are useless")) | |
;; writing | |
(defn numeric? [s] (every? (set "0123456789") s)) | |
(numeric? "123") | |
(numeric? "42b") | |
{:a 5 :b 6} | |
(def playlist | |
[ | |
{:title "Elephant" :artist "The White Stripes" :year 2003}]) | |
(map :title playlist) | |
(defn summarize [{:keys [title artist year]}] | |
(str title " / " artist " / " year)) | |
(map summarize playlist) | |
(def version1 {:name "Chas" :info {:age 31}}) | |
(def version2 (update-in version1 [:info :age] + 3)) | |
(print version2) | |
(def x (transient [])) | |
(def y (conj! x 1)) | |
(count y ) | |
(count x) | |
(doc transient) | |
(defn naive-into | |
[coll source] | |
(reduce conj coll source)) | |
(into #{} (range 5)) | |
(time (do (into #{} (range 1e6)) nil)) | |
(time (do (naive-into #{} (range 1e6))nil)) | |
(into #{} (range 5)) | |
(= (into #{} (range 500)) | |
(naive-into #{} (range 500))) | |
(defn faster-into | |
[coll source] | |
(persistent! (reduce conj! (transient coll) source))) | |
(time (do (faster-into #{} (range 1e6)) nil)) | |
(defn transient-capable? | |
[coll] | |
(instance? clojure.lang.IEditableCollection coll)) | |
(def v [1 2]) | |
(def tv (transient v)) | |
(transient-capable? v) | |
(transient-capable? tv) | |
(conj v 3) | |
(get tv 0) | |
(get v 0) | |
(persistent! tv) | |
(doc persistent!) | |
(nth (transient [ 1 3 ]) 1) | |
(get (transient {:a 1 :b 2}) :a) | |
((transient [ 1 2 ]) 1) | |
(let [ tm (transient {})] | |
(doseq [x (range 100)] | |
(assoc! tm x 0)) | |
(persistent! tm)) | |
(let [ t (transient {})] | |
@(future (get t :a))) | |
(persistent! (transient [(transient {})])) | |
;; this is kinda interesting. | |
(= (transient [ 1 2 ]) (transient [ 1 2])) | |
(def a ^{:created (System/currentTimeMillis)} | |
[1 2 3]) | |
(:created (meta a)) | |
(meta ^:private [ 1 2 3]) | |
(meta ^:private ^:dynamic [1 2 3]) | |
(print a) | |
(def b (with-meta a (assoc (meta a) | |
:modified (System/currentTimeMillis)))) | |
(meta b) | |
(meta a) | |
(print a b ) | |
(def b (vary-meta a assoc :modified (System/currentTimeMillis))) | |
(doc vary-meta) | |
(= a b) | |
(= ^{:a 5} 'any-value | |
^{:b 5} 'any-value) | |
(meta (conj a 500)) | |
(defn empty-board | |
[w h] | |
(vec (repeat w (vec (repeat h nil))))) | |
(defn populate | |
[board living-cells] | |
(reduce (fn [board coordinates] | |
(assoc-in board coordinates :on)) | |
board | |
living-cells | |
)) | |
(empty-board 10 10) | |
(def glider (populate (empty-board 6 6 ) #{[2 0] [2 1] [2 2 ] [1 2] [0 1]})) | |
(defn neighbours | |
[[x y]] | |
(for [dx [-1 0 1] dy [ -1 0 1] :when (not= 0 dx dy)] | |
[(+ dx x) (+ dy y)])) | |
(defn count-neighbours | |
[board loc] | |
(count (filter #(get-in board %) (neighbours loc)))) | |
(def d (delay (println "running...."))) | |
(deref d) | |
(def a-fn (fn [] | |
(println "Running") | |
:done! | |
)) | |
(a-fn) | |
(defn get-document | |
[id] | |
{:url "http://www.mozilla.org/about/manifesto.en.html" | |
:title "The Mozilla Manifesto" | |
:mime "text/html" | |
:content (delay (slurp "http://www.baidu.com"))} | |
) | |
(def d (get-document "some-fucking-id")) | |
(realized? (:content d)) | |
(deref (:content d)) | |
(print d) | |
(def long-calculation (future (apply + (range 1e8)))) | |
(deref long-calculation) | |
@(future (Thread/sleep 5000) :done!) | |
(deref (future (Thread/sleep 5000) :done!) 1000 :impatient!) | |
(defn get-document | |
[id] | |
{ | |
:url "http://www.mozilla.org/about/manifesto.en.html" | |
:title "The" | |
:mime "text/html" | |
:content (future (slurp "http://www.bing.com"))}) | |
(def p (promise)) | |
(realized? p) | |
(deliver p 42) | |
(realized? p) | |
(def a (promise)) | |
(def b (promise)) | |
(def c (promise)) | |
(future | |
(deliver c (+ @a @b)) | |
(println "develivery completed")) | |
(deliver a 15) | |
(deliver b 34) | |
(def a (promise)) | |
(def b (promise)) | |
(future (deliver a @b)) | |
(future (deliver b @a)) | |
(realized? a ) | |
(realized? b) | |
(deliver a 234) | |
(deref a) | |
(deref b) | |
(realized? a) | |
(realized? b) | |
(defn call-service | |
[arg1 arg2 callback-fn] | |
(println "args:" arg1 arg2) | |
(future (callback-fn (+ arg1 arg2) (- arg1 arg2)))) | |
(defn sync-fn | |
[async-fn] | |
(fn [& args] | |
(let [result (promise)] | |
(apply async-fn (conj (vec args) #(deliver result %&))) | |
@result | |
))) | |
((sync-fn call-service ) 8 7) | |
(defn phone-numbers | |
[string] | |
(re-seq #"(\d{3})[\.-]?(\d{3})[\.-](\d{4})" string)) | |
(phone-numbers "sunil:234.234.3244, Betty:343.423.3318") | |
(def files (repeat 100 | |
(apply str | |
( concat (repeat 100000 \space ) "sunil:617.555.3333" | |
)))) | |
(time (dorun (map phone-numbers files))) | |
(time (dorun (map phone-numbers files))) | |
;; this is quicker , you need to know this. | |
(time (->> files | |
(partition-all 250) | |
(pmap (fn [chunk] (doall (map phone-numbers chunk)))) | |
(apply concat) | |
dorun)) | |
@(atom 12) | |
@(agent {:c 13}) | |
(map deref [(agent {:c 42}) (atom 12) (ref "http://clojure.org") (var +)]) | |
(defmacro futures | |
[n & exprs] | |
(vec (for [_ (range n) | |
expr exprs] | |
`(future ~expr) | |
))) | |
(defmacro wait-futures | |
[& args] | |
`(doseq [f# (futures ~@args)] | |
@f# | |
)) | |
(def sarah (atom {:name "Sarah" :age 23 :wear-glasses? false})) | |
(swap! sarah update-in [:age] + 3) | |
(print sarah) | |
(swap! sarah (comp #(update-in % [:age ] inc) | |
#(assoc % :wear-glasses? true) )) | |
(print sarah) | |
(def xs (atom #{1 2 3})) | |
(wait-futures 1 (swap! xs (fn [v] | |
(Thread/sleep 50) | |
(println "trying 4") | |
(conj v 4) | |
))) | |
@xs | |
(def x (atom 2000)) | |
(swap! x #(Thread/sleep %)) | |
(compare-and-set! xs :wrong "new value") | |
@xs | |
(compare-and-set! xs @xs "new value") | |
@xs | |
(def xs (atom #{ 1 2})) | |
(compare-and-set! xs #{1 2} "new value") | |
(deref xs) | |
(reset! xs :y) | |
@xs | |
;; watch an variable for any changes | |
(defn echo-watch | |
[key identity old new] | |
(println key old "=>" new)) | |
(def sarah (atom {:name "sarah" :age 25})) | |
(add-watch sarah :echo echo-watch) | |
(swap! sarah update-in [:age ] inc) | |
(add-watch sarah :echo2 echo-watch) | |
(swap! sarah update-in [:age] inc) | |
(remove-watch sarah :echo2) | |
(swap! sarah update-in [:age] inc) | |
(reset! sarah @sarah) | |
(def history (atom ())) | |
(defn log-list | |
[dest-atom key source old new] | |
(when (not= old new) | |
(swap! dest-atom conj new))) | |
(def n (atom 1 :validator pos?)) | |
(swap! n + 500) | |
(swap! n - 1000) | |
(set-validator! sarah :age) | |
(swap! sarah dissoc :age) | |
(set-validator! sarah #(or (:age %) | |
(throw (IllegalStateException. | |
"People must have `:age`s!''")))) | |
(swap! sarah dissoc :age) | |
;; merging stuff after creating. this is just way to fucking cool | |
(defn character | |
[name & {:as opts}] | |
(ref (merge {:name name :items #{} :health 500} | |
opts | |
))) | |
(def smaug (character "Smaug" :health 500 :strength 400 :items (set (range 500)))) | |
(def bilbo (character "Bilbo" :health 100 :strength 100)) | |
(def gandalf (character "Gandalf" :health 75 :mana 750)) | |
;; move your assses | |
(defn loot | |
[from to ] | |
(dosync | |
(when-let [item (first (:items @from))] | |
(alter to update-in [:items] conj item) | |
(alter from update-in [:items] disj item)))) | |
(wait-futures 1 | |
(while (loot smaug bilbo)) | |
(while (loot smaug gandalf))) | |
@smaug | |
@bilbo | |
@gandalf | |
(map (comp count :items deref)[bilbo gandalf]) | |
(filter (:items @bilbo) (:items @gandalf)) | |
(source http/get) | |
(http/get "http://secret.ly") | |
(defn gcd [a b] | |
(if (zero? b) | |
a | |
(gcd b (mod a b)))) | |
(gcd 10 5) | |
(gcd 200 24) | |
(defmacro runtime-gcd [a b] | |
(list 'gcd a b)) | |
(macroexpand '(runtime-gcd 10 5)) | |
(defmacro runtime-gcd-quote [ a b] `(gcd ~a ~b)) | |
(defn runtime-gcd-fun [a b] (list 'gcd a b)) | |
(list 'gcd 12 8) | |
(runtime-gcd-fun 12 8) | |
;; macros are quite powerful. | |
(runtime-gcd-quote 12 8) | |
(defmacro runtime-gcd [a b] (list 'gcd a b)) | |
(defmacro my-print [arg ] | |
`(do | |
(println ~arg) | |
~arg | |
)) | |
(my-print (* 23 34)) | |
(def a 8) | |
`~(quote a) | |
(type a) | |
(type 'a) | |
(type '~a) | |
(type `~a) | |
(type `~'a) | |
(defmacro awesome-printer [arg] | |
(println "compile time printer" arg | |
) (list println "runtime printer" arg)) | |
(defmacro dions [arg] | |
(list 'println "Runtime: " arg) | |
(println "compile time:" arg)) | |
(dions "fuck") | |
(defmacro assert-equals [actual expected] | |
(= expected actual)) | |
(assert-equals (inc 6 ) 7) | |
(eval 7) | |
(awesome-printer (+ 345 345)) | |
(awesome-printer (* 23 34)) | |
(defmacro assert-equals [arg1 arg2] | |
(list '= arg1 arg2)) | |
(macroexpand '(assert-equals (inc 7) 8)) | |
= | |
(defmacro foreach [[ sym coll] & body] | |
`(loop [coll# ~coll] | |
(when-let [[~sym & xs#] (seq coll#)] | |
~@body | |
(recur xs#) | |
))) | |
(foreach [x [1 2 3]] | |
(println x)) | |
;;my own version of foreach. kinda suck , I still can't get part of it. | |
(defmacro my-foreach [[sym coll] & body] | |
`(loop [coll# ~coll] | |
(when-let [[~'sym & xs#] (seq coll#)] | |
~@body | |
(recur xs#)))) | |
(my-foreach [x [1 2 3]] (println x)) | |
(macroexpand-1 '(my-foreach [x [ 1 2 3]] | |
(println x))) | |
(def message "good job!") | |
(defmacro with-mischief | |
[& stuff-to-do] | |
(concat (list 'let['message ""])) | |
) | |
(defmacro report [to-try] | |
`(if ~to-try | |
(println (quote ~to-try) "was successful" ~to-try) | |
(println (quote ~to-try) "was not succcessful" ~to-try))) | |
(macroexpand '(report (do (Thread/sleep 1000) (println "doing it now") (+ 1 1)))) | |
(defmacro report | |
[to-try] | |
`(let [result# ~to-try] | |
(if result# | |
(println (quote ~to-try) "was successful" result#) | |
(println (quote ~to-try) "was not" result#)))) | |
(macroexpand '(report (do (println "ahhaasdfasd")))) | |
(defrecord Person [first-name last-name]) | |
(defrecord SanePerson [^String first-name ^String last-name]) | |
(defprotocol Greeet | |
(say-hello [this])) | |
(defrecord GreekPerson [first-name last-name] | |
Greet | |
(say-hello [this] (println "Hello my name is " first-name))) | |
(defn area | |
[shape] | |
(condp = (:type shape) | |
:triangle (* (:base shape) (:height shape) (/ 1 2)) | |
:rectangle (* (:length shape)(:width shape)) | |
)) | |
(area {:type :triangle :base 2 :height 4}) | |
(area {:type :rectangle :length 2 :width 4}) | |
(defmulti area | |
:type | |
) | |
(defmethod area :rectangle [shape] | |
(* (:length shape)(:width shape))) | |
(defmethod area :cirlce [shape] | |
(* (. Math PI) (:radius shape)(:radius shape))) | |
(area {:type :cirlce :radius 1}) | |
(defprotocol Shape | |
(area [s] "calculate the area of a shape") | |
(perimeter [s] "calculate the perimeter of a shape")) | |
(defrecord Rectangle [length width] | |
Shape | |
(area [this] (* length width)) | |
(perimeter [this](+ (* 2 length) | |
(* 2 width)))) | |
(->Rectangle 2 4) | |
(area (->Rectangle 2 4)) | |
(perimeter (->Rectangle 2 4)) | |
(import 'java.net.URL) | |
(def cnn (URL. "http://bing.com")) | |
(.getHost cnn) | |
(slurp cnn) | |
Double/MAX_VALUE | |
(Double/parseDouble "3.141592653589793238462643383279502884197") | |
(type (let [alist (java.util.ArrayList.)] | |
(.add alist 1) | |
alist | |
)) | |
(let [llist (java.util.LinkedList.)] | |
(.add llist 1) | |
llist | |
) | |
(doto (java.util.ArrayList.) | |
(.add 1) | |
(.add 2) | |
(.add 3) | |
) | |
(dir clojure.string) | |
(dir clojure.core) | |
(ns-aliases *ns*) | |
(ns-aliases *ns*) | |
(ns-publics *ns*) | |
(def x 0) | |
(identical? 5/4 (+ 3/4 1/2)) | |
(use 'clojure.test) | |
(is (= 5 ( + 4 3)) " i am good at math") | |
(is(re-find #"foo" "foobar")) | |
(println "awesome") | |
(quote (+ 1 1 )) | |
(reverse '(+ 1 1 )) | |
;; creating frozen data | |
(def frozen-stress-data (nippy/freeze nippy/stress-data)) | |
(nippy/thaw frozen-stress-data) | |
(def ^:dynamic *base-url* "https://news.ycombinator.com") | |
(def ^:dynamic *rosetta-clojure-code* "http://rosettacode.org/wiki/Category:Clojure") | |
(def ^:dynamic *rosetta-base-url* "http://rosettacode.org/") | |
(def ^:dynamic *algo-detail* "http://rosettacode.org/wiki/100_doors") | |
(defn fetch-url [url] | |
(html/html-resource (java.net.URL. url))) | |
(fetch-url *base-url*) | |
(def clojure-algos (:body (http/get *rosetta-clojure-code*))) | |
(print clojure-algos) | |
(def all-algorithms (map :attrs (html/select (html/html-resource (html/html-snippet clojure-algos)) [:div#mw-pages :div.mw-content-ltr :li :a]))) | |
(apply str (concat *rosetta-base-url* (first (map :href all-algorithms)))) | |
(def algo-urls (doseq [line (map :href all-algorithms)] | |
(println (apply str (concat *rosetta-base-url* line))))) | |
(def clojure-pres (html/select (html/html-resource (html/html-snippet (:body (http/get *algo-detail*)))) [:pre.clojure])) | |
(print clojure-pres) | |
(print (html/text (first clojure-pres))) | |
(print "awesome") | |
(defn hn-headlines [] | |
(map html/text (html/select (fetch-url *base-url*) [:td.title :a]))) | |
(defn hn-points [] | |
(map html/text (html/select (fetch-url *base-url*) [:td.subtext html/first-child] ))) | |
(defn print-headlines-and-points [] | |
(doseq [line (map #(str %1 %2) (hn-headlines) (hn-points))] | |
(println line) | |
)) | |
(print-headlines-and-points) | |
(def ^:dynamic coursera-url "https://accounts.coursera.org/api/v1/login") | |
(def ^:dynamic my-email "awklsgrep@gmail.com") | |
(def ^:dynamic my-password "asdfasdf123") | |
(def ^:dynamic clojure-cheatseet "http://clojure.org/cheatsheet") | |
(def ^:dynamic lds-url "http://see.stanford.edu/see/materials/lsoeldsee263/handouts.aspx") | |
(def clojure-names (html/select (html/html-resource (html/html-snippet (:body (http/get clojure-cheatseet)))) [:div#WikiContent :div.page :a])) | |
(def linear-dynamic-systems (html/select (html/html-resource (html/html-snippet (:body (http/get lds-url)))) [:td :a])) | |
(def pdf-url (get-in (first linear-dynamic-systems) [:attrs :href])) | |
(str "/tmp/" (last (.split pdf-url "/"))) | |
(def pdf-sources [ | |
"http://see.stanford.edu/see/materials/lsoeldsee263/exams.aspx" | |
"http://see.stanford.edu/see/materials/lsoeldsee263/assignments.aspx" | |
"http://see.stanford.edu/see/materials/lsoeldsee263/handouts.aspx" | |
]) | |
(defn get-page-as-res [url selector] | |
(html/select (html/html-resource (java.net.URL. url )) selector)) | |
(defn get-page-res-links [url] | |
(map #(get-in % [:attrs :href]) (get-page-as-res url [:td :a]) )) | |
(defn download-file [url dir] | |
(let [my-file (last (.split url "/"))] | |
(if-not (.exists (io/as-file (str dir my-file))) | |
(try | |
(with-open [ in (io/input-stream url) | |
out (io/output-stream (str dir my-file))] | |
(io/copy in out) | |
(println my-file " has been downloaded.") | |
) | |
(catch Exception e (str "caught exception:" (.getMessage e)))) | |
(print my-file "is already there")))) | |
;; You have to dorun mapped futures, cause map returns lazy sequences and they wont be evaluated until you force them | |
(doseq [link pdf-sources] | |
(dorun (map #(future (download-file % "/work/weekly readings/LinearDynamicSystems/")) (get-page-res-links link)))) | |
(map #(first (:content %)) clojure-names) | |
(map #(get-in % [:attrs :href] ) clojure-names ) | |
(def clj-essense (map (fn [m] | |
{:name (first | |
(:content m) | |
) | |
:url (get-in m [:attrs :href]) | |
}) clojure-names)) | |
(print (map :name clj-essense)) | |
(second clj-essense) | |
(defn print-doc [url] | |
(map :content | |
(html/select ( -> (http/get url) | |
html/html-snippet | |
html/html-resource) | |
[:section :div :pre]))) | |
(defn print-doc2 [url] | |
(first (:content (first (html/select (html/html-resource (java.net.URL. url) ) | |
[:section :div.docstring :pre] | |
))))) | |
(defn print-example [url ] | |
(html/select (html/html-resource (java.net.URL. url)) [:div.var-examples])) | |
(html/html-resource (java.net.URL. "http://clojuredocs.org/clojure.repl/find-doc")) | |
(map (fn [m] | |
{:name (:name m) :doc (print-doc2 (:url m))}) clj-essense) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment