tutorial online example clojure

online - ¿Cuál es la cosa más útil que has hecho en menos de 50 líneas de Clojure?



clojure vs scala (9)

Clojure parece que podría tener una buena oportunidad de ser un Lisp popular. Me preguntaba cuántas personas lo han adoptado para resolver algunos de los problemas pequeños pero reales que han encontrado. Como Clojure no tiene una entrada en Pleac , pensé que sería genial si las personas publicaran sus pequeñas soluciones a los problemas que han resuelto en Clojure.


Bueno, este código realmente fue para mí y para nadie más. El otro día lo tiré en veinte minutos para un curso sobre los procesos de Markov. Ciertamente lo encontré útil. Lo utilicé para convencer al profesor de que mi análisis teórico de un problema era correcto. Honestamente, la parte genial (¡creo!) En realidad es solo la primera función, sample . Utilizo una función como esa en muchos de mis proyectos, y de alguna manera, al solucionar esto rápidamente, encontré mi mejor solución todavía.

(defn sample "Samples once a discrete random distribution defined by a vector. E.g., (sample [0.25 0.2 0.1 0.45]) should output ''0'' 25% of the time, ''1'' 20% of the time, etc." [p] (let [r (rand)] (count (take-while #(< % r) (reductions + p))))) (defn transition "Given a transition matrix and a history vector, returns the history with an additional time step added." [m h] (conj h (sample (nth m (last h))))) (defn process-gen "Takes a transition probability matrix, initial state probabilities, and a function. The initial state probs should take the form [p .. q]. The function should accept the full process history and return true if the process should stop. Returns a function of no arguments that returns a full simulated history of the process." [m i f] (fn [] (loop [h [(sample i)]] (if (f h) h (recur (transition m h)))))) (defn transition2 "Given a transition matrix and the current state, returns a sampled state for the next time step." [m s] (sample (nth m s))) (defn lazy-process "Takes a transition probability matrix, initial state probabilities, and a function. The initial state probs should take the form [p .. q]. Returns a function which, when run, produces an infinite lazy list sampling the process." [m i] (fn [] f ([] (f (sample initial))) ([s] (let [i (transition2 m s)] (cons i (lazy-seq (f i)))))))

Eliminando comentarios:

(defn sample [p] (let [r (rand)] (count (take-while #(< % r) (reductions + p))))) (defn transition [m h] (conj h (sample (nth m (last h))))) (defn process-gen [m i f] (fn [] (loop [h [(sample i)]] (if (f h) h (recur (transition m h)))))) (defn transition2 [m s] (sample (nth m s))) (defn lazy-process-gen [m i] (fn [] f ([] (f (sample initial))) ([s] (let [i (transition2 m s)] (cons i (lazy-seq (f i)))))))

Ejemplo de uso:

user=>(def squirrel-matrix [[0.8797 0.0212 0.0981 0.0010] [0.0382 0.8002 0.0273 0.1343] [0.0527 0.0041 0.8802 0.0630] [0.0008 0.0143 0.0527 0.9322]]) user=>(def my-process (process-gen squirrel-matrix [1 0 0 0] #(and (> (count %) 1) (= 0 (last %))))) user=> (/ (reduce + (map (comp dec count) (repeatedly 1000000 my-process))) 1000000.) 5.820319 user=> (let [hs (reduce + (filter #(> % 1) (map (comp dec count) (repeatedly 1000000 my-process))))] (/ (reduce + hs)) (count hs))) 5002699/120880 ; ~41.386

Estos dos números responden, a través de una simulación bastante excesiva, dos interpretaciones diferentes de la pregunta here .

Debo confesar que limpié un poco mi código para todos ustedes. El día que escribí esto fue el día en que descubrí que Clojure permitía Unicode en los nombres de los símbolos. Puede que haya ido un poco por la borda en la modificación del idioma. ;-) Entonces ... ¡las primeras tres funciones se ven así en mi archivo!

(Λ σ [p] (let [r (rand)] (|| (take-while #(< % r) (∮ + p))))) (Λ Δ [Ξ ξ] (⊞ ξ (σ (§ Ξ (last ξ))))) (Λ Π [Ξ i ω] (λ [] (⟳ [ξ [(σ i)]] (⇒ (ω ξ) ξ (⟲ (Δ Ξ ξ))))))


Clojure probablemente tiene una función de poder, pero me emocioné mucho al darme cuenta de esto:

(defn pow [base exp] (reduce * (replicate exp base)))


Escribiendo aplicaciones Swing, las cosas de JMenuBar siempre son molestas. Gracias a dorun / map es mucho más fácil:

(let [menus [ {:name "File" :mnemonic /F :items [ {:name "Open" :mnemonic /O :fn file-open} :separator {:name "Exit" :mnemonic /x :fn file-exit} ] } {:name "Help" :mnemonic /H :items [ :separator {:name "About..." :mnemonic /A :fn help-about} ] } ] menu-fns (into {} (mapcat (fn [menu] (map (fn [item] [(:name item) (:fn item)]) (:items menu))) menus)) ui-frame (proxy [JFrame ActionListener] ["UI Frame"] (actionPerformed [event] (let [command (.getActionCommand event) menu-fn (get menu-fns command)] ;; Handle menu commands (if menu-fn (apply menu-fn [this])) )) ) ] (defn new-menu [listener] (let [menubar (JMenuBar.)] (dorun (map (fn [x] (let [menu (JMenu. (:name x))] (.setMnemonic menu (int (:mnemonic x))) (.add menubar menu) (dorun (map (fn [item] (if (= :separator item) (.addSeparator menu) (let [menu-item (if (:mnemonic item) (JMenuItem. (:name item) (int (:mnemonic item))) (JMenuItem. (:name item)))] (.addActionListener menu-item listener) (.add menu menu-item)))) (:items x))))) menus)) menubar))

En este momento no necesito submenús, pero es un cambio trivial a new-menu para obtenerlos. También agregar iconos, estado activo / inactivo, etc. es simplemente más campos en los menus .


Esto crea una miniatura de una imagen. La imagen puede ser un archivo local, una URL remota o cualquier otra cosa que javax.imageio.ImageIO pueda leer (¡gracias Java!). La salida puede ser de cualquier formato de imagen que javax.imageio.ImageIO pueda escribir.

(use ''(clojure.contrib java-utils)) (defn make-thumbnail "Given an input image (File, URL, InputStream, ImageInputStream), output a smaller, scaled copy of the image to the given filename. The output format is derived from the output filename if possible. Width should be given in pixels." ([image out-filename width] (if-let [format (re-find #"/.(/w+)$" out-filename)] (make-thumbnail image out-filename width (nth format 1)) (throw (Exception. "Can''t determine output file format based on filename.")))) ([image out-filename width format] (let [img (javax.imageio.ImageIO/read image) imgtype (java.awt.image.BufferedImage/TYPE_INT_RGB) width (min (.getWidth img) width) height (* (/ width (.getWidth img)) (.getHeight img)) simg (java.awt.image.BufferedImage. width height imgtype) g (.createGraphics simg)] (.drawImage g img 0 0 width height nil) (.dispose g) (javax.imageio.ImageIO/write simg format (as-file out-filename)))))

Crea una miniatura de JPG desde un PNG local:

(make-thumbnail (java.io.File. "some-image.png") "thumb.jpg" 150)

Crea una miniatura de GIF desde un JPG remoto:

(make-thumbnail (java.net.URL. "http://blog..com/wp-content/uploads/justice-league-small.jpg") "small.gif" 250)


Esto imprime un pronóstico del tiempo a través de Yahoo! El clima

(ns weather (:use (clojure [xml :only [parse]] [zip :only [xml-zip]]) (clojure.contrib duck-streams str-utils pprint) (clojure.contrib.zip-filter xml))) (defn fetch-xml [uri] (xml-zip (parse (org.xml.sax.InputSource. (java.io.StringReader. (slurp* (java.net.URI. (re-gsub #"/s+" "+" (str uri))))))))) (defn yahoo-weather ([loc-code] (yahoo-weather loc-code "c")) ([loc-code unit] (let [rss (fetch-xml (str "http://weather.yahooapis.com/forecastrss?p=" loc-code "&u=" unit))] (if (= (text (xml1-> rss :channel :item :title)) "City not found") "City not found. Go to http://weather.yahoo.com/, search for your city, and look in the URL for the location code." (let [[units loc wind atm ast] (map #(xml1-> rss :channel (keyword (str "yweather:" %))) ["units" "location" "wind" "atmosphere" "astronomy"]) conditions (xml1-> rss :channel :item :yweather:condition) date (re-find #"/d+:/d+.*" (xml1-> rss :channel :item :pubDate text)) fors (xml-> rss :channel :item :yweather:forecast)] (cl-format true "Weather for ~a, ~a (~a) Temperature: ~a/u00B0 ~a Wind Chill: ~a/u00B0 ~a, ~a ~a Conditions: ~a Humidity: ~a% Barometer: ~a ~a Sunrise/Sunset: ~a / ~a Forecast: ~{ ~{~a: ~a. Hi ~2d, Lo ~2d.~}~^~%~} " (attr loc :city) (attr loc :region) date (attr conditions :temp) (attr units :temperature) (attr wind :chill) (attr units :temperature) (attr wind :speed) (attr units :speed) (attr conditions :text) (attr atm :humidity) (attr atm :pressure) (attr units :pressure) (attr ast :sunrise) (attr ast :sunset) (map #(list (attr % :day) (attr % :text) (attr % :high) (attr % :low)) fors)))))))

Por ejemplo:

user> (weather/yahoo-weather "CAXX0328") Weather for North Vancouver, (10:00 am PDT) Temperature: 14° C Wind Chill: 14° C, 8.05 kph Conditions: Light Rain Shower Humidity: 88% Barometer: 1018 mb Sunrise/Sunset: 6:01 am / 8:32 pm Forecast: Thu: Few Showers. Hi 18, Lo 12. Fri: AM Showers. Hi 19, Lo 12. nil


Lo más útil que he escrito para mí en Clojure es la función casi trivial:

(defn tally-map " Create a map where the keys are all of the unique elements in the input sequence and the values represent the number of times those elements occur. Note that the keys may not be formatted as conventional Clojure keys, i.e. a colon preceding a symbol." [aseq] (apply merge-with + (map (fn [x] {x 1}) aseq)))

Uso esto todo el tiempo en el trabajo que hago. Muy útil para los histogramas.

Brian Carper tuvo la amabilidad de sugerir la siguiente forma mejorada de la función.

(defn tally-map [coll] (reduce (fn [h n] (assoc h n (inc (or (h n) 0)))) {} coll))


No es particularmente útil por sí mismo, pero la idea es similar a JSON en Javascript: puede mover las estructuras de datos de Clojure desde y hacia el sistema de archivos. Adoptado del ejemplo de la base de datos de Practical Common Lisp :

(ns storage (:import (java.io File PushbackReader FileReader FileWriter))) (defn load-data "Loads data from the given file." [filepath] (do ;; the let block creates the file if it doesn''t exist ;; reader throws an exception if there''s no parsable data struct (let [file (new File filepath)] (if (not (.exists file)) (do (.createNewFile file) (doto (new FileWriter filepath) (.write "{}") .close)))) (read (new PushbackReader (new FileReader filepath))))) (defn dump-data "Exports data structure to a file." [filepath data] (doto (new FileWriter filepath) (.write (str data)) .close))

Ejemplo de uso:

user=> (dump-data "test.dat" {:a [1 2 3] :b "hello" :c true}) #<FileWriter java.io.FileWriter@186df0f> user=> (load-data "test.dat") {:a [1 2 3], :b "hello", :c true}

Sin duda, es mejor escribir su propio mecanismo de guardado (complejo) para su programa. Estoy seguro de que leer solo desde una cadena es posible simplemente cambiando algunos de los lectores proporcionados a través de Java.


Una respuesta más seria esta vez:

A menudo me frustra la función de seguimiento de pila REPL que solo muestra ocho líneas. Así que ahora está en el archivo de desarrollo para todos mis proyectos:

(defn stack [n] (clojure.stacktrace/print-stack-trace (clojure.stacktrace/root-cause *e) n))

Quiero argmin y argmax todo el tiempo .

(defn argmin ([f x] x) ([f x y] (if (< (f x) (f y)) x y)) ([f x y & more] (reduce (partial argmin f) (argmin f x y) more))) (defn argmax ([f x] x) ([f x y] (if (> (f x) (f y)) x y)) ([f x y & more] (reduce (partial argmax f) (argmax f x y) more)))

Y, finalmente, para evaluar los algoritmos de forma robusta, uso esta función en conjuntos de datos mucho:

(defn kfolds "Given an integer k and a collection of data, this partitions the data into k non-overlapping collections, then returns a list of length k, where the ith item is itself a list of two items: (1) the union of all but the ith partition (2) the ith partition. If (count data) is not divisible by k, a few points (< k) will be left out." [k data] (let [total (count data) fold-size (int (/ total k)) folds-test (take k (partition fold-size fold-size [] data)) folds-train (map #(apply concat %) (map #(take (dec k) (drop % (cycle folds-test))) (range 1 (inc k))))] (map list folds-train folds-test)))


99 botellas de cerveza

(defn bottles [n & [capitalize]] (str (if (> n 0) n (if capitalize "No more" "no more")) " bottle" (if (= 1 n) "" "s") " of beer" )) (defn bot-wall [n & cap] (str (bottles n cap) " on the wall")) (defn sing ; Default is 99 times. ([] (sing 99)) ([stock] (doseq [i (range stock -1 -1)] (printf "%s, %s./n%s./n/n" (bot-wall i true) (bottles i) (apply str (if (> i 0) ["Take one down and pass it around, " (bot-wall (dec i))] ["Go to the store and buy some more, " (bot-wall stock)] )))))) (sing)

http://99-bottles-of-beer.net/language-clojure-1996.html