two files
types.clj:
(ns test.types)
(defrecord Price [date price])
(defrecord ProductPrice [name prices])
core.clj (It's OK)
(ns test.core
(:use [test.types])
(:use [clojure.string :only (split)]))
(defn read-data [file]
(let [name (subs (.getName file) 0 4)]
(with-open [rdr (clojure.java.io/reader file)]
(doall (map #(apply ->Price (split % #"\t")) (drop 2 (line-seq rdr)))))))
core.clj (java.lang.IllegalArgumentException: Unable to resolve classname: ProductPrice)
(ns test.core
(:use [test.types])
(:use [clojure.string :only (split)]))
(defn read-data [file]
(let [name (subs (.getName file) 0 4)]
(with-open [rdr (clojure.java.io/reader file)]
(ProductPrice. name (doall (map #(apply ->Price (split % #"\t")) (drop 2 (line-seq rdr))))))))
core.clj (It's OK)
(ns test.core
(:use [test.types])
(:use [clojure.string :only (split)]))
(defrecord tProductPrice [name prices])
(defn read-data [file]
(let [name (subs (.getName file) 0 4)]
(with-open [rdr (clojure.java.io/reader file)]
(tProductPrice. name (doall (map #(apply ->Price (split % #"\t")) (drop 2 (line-seq rdr)))))))
core.clj (java.lang.IllegalStateException: ->ProductPrice already refers to: #'test.types/->ProductPrice in namespace: test.core)
(ns test.core
(:use [test.types])
(:use [clojure.string :only (split)]))
(defrecord ProductPrice [name prices])
(defn read-data [file]
(let [name (subs (.getName file) 0 4)]
(with-open [rdr (clojure.java.io/reader file)]
(ProductPrice. name (doall (map #(apply ->Price (split % #"\t")) (drop 2 (line-seq rdr)))))))
I totally confused about these exceptions. And I can't find any more usage about 'record' except some simplest examples from clojure.org and books.
Any help, Thank you very much!
defrecord creates a java class in the package named after the current namespace. (ProductPrice. ...) is a call to the constructor of that type; this is java interop - not a plain function call.
You cannot refer to a class defined outside of java.lang or the current namespace unless you explicitly import it or specify the full package name. This includes calling its constructor.
So, to fix the problem you need to import Price and ProductPrice.
(ns test.core (:import [test.types Price]))
(Price. ...)
or call the full class+package name:
(test.types.Price. ...)
Related
I want to filter and modify output of tail command. This is what I come up with:
#!/usr/bin/env bb
(ns script
(:require
[clojure.java.io :as io]
[clojure.string :as str]
))
(->> (line-seq (io/reader *in*)
(filter #(re-find #"^\[.*CONSOLE" %))
(map #(str "carpenter " %)))
It works for normal tail. But I want to use it for "tail -f" command.
Any ideas?
Thx
This example starts writing to a file two kinds of messages: HELLO and BYE. Then it starts a tail -f process to watch the file and then reads from the output of that process and only captures the BYE lines and prints them with a custom string in front.
(ns tail-example
(:require [babashka.process :as p]
[clojure.java.io :as io]))
(future
(loop []
(spit "my-file.txt" "HELLO\n" :append true)
(spit "my-file.txt" "BYE\n" :append true)
(Thread/sleep 1)
(recur)))
(def tail (p/process
(p/tokenize "tail -f my-file.txt")
;; send stderr to stderr of bb, leave out stream unmodified
{:err :inherit}))
(let [rdr (io/reader (:out tail))]
(binding [*in* rdr]
(loop []
(when-let [l (read-line)]
(when (re-matches #"BYE" l)
(println (str "[log] " l)))
(recur)))))
I'm trying to parse HTML with CSS into Hiccup in a Reagent project. I am using Hickory. When I parse HTML with inline CSS, React throws an exception.
(map
as-hiccup (parse-fragment "<div style='color:red'>test</div>")
)
The above generates [:div {:style color:red} "test"] & Reactjs returns exception from Reactjs:
Violation: The style prop expects a mapping from style properties to values, not a string.
I believe [:div {:style {"color" "red"}} "test"] must be returned instead.
Here is the code view:
(ns main.views.job
(:require [reagent.core :as reagent :refer [atom]]
[hickory.core :refer [as-hiccup parse parse-fragment]]))
(enable-console-print!)
(defn some-view [uid]
[:div
(map as-hiccup (parse-fragment "<div style='color:red'>test</div>"))
])
The whole repo is here and it works. I added the parsing from style tag to a map for React in the core.cljs file:
(ns hickory-stack.core
(:require [clojure.string :as s]
[clojure.walk :as w]
[reagent.core :as reagent :refer [atom]]
[hickory.core :as h]))
(enable-console-print!)
(defn string->tokens
"Takes a string with syles and parses it into properties and value tokens"
[style]
{:pre [(string? style)]
:post [(even? (count %))]}
(->> (s/split style #";")
(mapcat #(s/split % #":"))
(map s/trim)))
(defn tokens->map
"Takes a seq of tokens with the properties (even) and their values (odd)
and returns a map of {properties values}"
[tokens]
{:pre [(even? (count tokens))]
:post [(map? %)]}
(zipmap (keep-indexed #(if (even? %1) %2) tokens)
(keep-indexed #(if (odd? %1) %2) tokens)))
(defn style->map
"Takes an inline style attribute stirng and converts it to a React Style map"
[style]
(tokens->map (string->tokens style)))
(defn hiccup->sablono
"Transforms a style inline attribute into a style map for React"
[coll]
(w/postwalk
(fn [x]
(if (map? x)
(update-in x [:style] style->map)
x))
coll))
;; Test Data
(def good-style "color:red;background:black; font-style: normal ;font-size : 20px")
(def html-fragment
(str "<div style='" good-style "'><div id='a' class='btn' style='font-size:30px;color:white'>test1</div>test2</div>"))
;; Rendering
(defn some-view []
[:div (hiccup->sablono
(first (map h/as-hiccup (h/parse-fragment html-fragment))))])
(reagent/render-component [some-view]
(. js/document (getElementById "app")))
This function takes a list of a files and is supposed to return a list of artists:
(defn get-artists [files]
(map #(.get-artist (->Mp3 %)) files))
Here the rest of the code:
(ns musicdb.filesystem
(:use [green-tags.core]))
(import '(java.io.File) '(java.net.url) '(java.io))
(require '[clojure.string :as str])
(defn get-files [search-path]
(let [directory (clojure.java.io/file search-path)
files (file-seq directory)
fonly (filter #(.isFile %) files)]
(map #(last (str/split (.toString %) #"/")) fonly)))
(defprotocol MusicFile
(get-artist [this])
(get-song [this])
(get-album [this]))
(defrecord Mp3 [filename]
MusicFile
(get-artist [this]
(:artist (get-all-info filename)))
(get-song [this]
(:title (get-all-info filename)))
(get-album [this]
(:album (get-all-info filename))))
And here are my tests:
(ns musicdb.core-test
(:require [clojure.test :refer :all]
[musicdb.core :refer :all]
[musicdb.filesystem :refer :all]
[clojure.pprint :refer :all]
))
(deftest test_0
(testing "getFiles returns valid result"
(is (> (count (get-files "/home/ls/books/books")) 50))))
(deftest test_1
(testing "check for file included"
(is (some #{"02 Backlit.mp3"} (get-files "/home/ls/Musik")))))
(deftest test_2
(testing "creating music file record"
(let [myfile (->Mp3 "/home/ls/Musik/Panopticon/02 Backlit.mp3")]
(is (= "Isis" (.get-artist myfile)))
(is (= "Backlit" (.get-song myfile))))))
(deftest test_3
(testing "testing get-artists"
(let [artists (get-artists (get-files "/home/ls/Musik"))
]
(is (> (count artists) 10)))))
(deftest test_4
(testing "testing get-artists check for artist"
(let [artists (get-artists (get-files "/home/ls/Musik"))
]
(is (some #{"Isis"} artists))))) ;artists is [nil nil nil ...]
From this tests only the last fails, which returns a list of nils.
If you want to reproduce ths be sure to include the green-tags dependency in your leiningen project.clj:
[green-tags "0.3.0-alpha"]
Your get-files function doesn't return the full path of the file so get-all-info just returns nil (https://github.com/DanPallas/green-tags/blob/master/src/green_tags/core.clj#L59 in combination with https://github.com/DanPallas/green-tags/blob/master/src/green_tags/core.clj#L120).
Here is a simple example that works:
(map (comp :artist get-all-info)
(filter #(.isFile %)
(file-seq (java.io.File. "/home/vema/Downloads/mp3"))))
;=> ("Yo Yo Honey Singh (DJJOhAL.Com)")
(Humoristic?) disclaimer: The MP3 should not be taken as an example of my musical taste, it was just the first free MP3 I found online.
Here is a parsing example using Enlive. Would there be differences with Enliven?
(ns parse.enlive
(:require [net.cgrand.enlive-html :as html]))
(def ^:dynamic *base-url* "https://news.ycombinator.com/")
(defn fetch-url [url]
(html/html-resource (java.net.URL. url)))
(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)))
If there are not much differences in that simple example, where would Enliven be different when doing some web scraping?
Thanks!
I'm trying to add the following Hiccup template function to my file
(defn d3-page [title js body & {:keys [extra-js] :or {extra-js []}}]
(html5
[:head
[:title title]
(include-css "/css/nv.d3.css"))
(include-css "/css/style.css")]
[:body
(concat
[body]
[(include-js "http://d3js.org/d3.v3.min.js")
(include-js (str "https://raw.github.com"
"/novus/nvd3"
"/master/nv.d3.min.js")]
(map include-js extra-js)
[(include-js "/js/script.js")
(javascript-tag js)])]))
but keep getting an unmatched delimiter when I run lein ring server. This comes from Clojure Data Cookbook, so I am surprised to find an error and suspect the error is just on my end. Below is the rest of the code in the file:
(ns web-viz.web
(:require [compojure.route :as route]
[compojure.handler :as handler]
[clojure.string :as str])
(:use compojure.core
ring.adapter.jetty
[ring.middleware.content-type :only
(wrap-content-type)]
[ring.middleware.file :only (wrap-file)]
[ring.middleware.file-info :only
(wrap-file-info)]
[ring.middleware.stacktrace :only
(wrap-stacktrace)]
[ring.util.response :only (redirect)]
[hiccup core element page]
[hiccup.middleware :only (wrap-base-url)]))
(defn d3-page...as above
...)
(deftype Group [key values])
(deftype Point [x y size])
(defn add-label [chart axis label]
(if-not (nil? label)
(.axisLabel (aget chart axis) label)))
(defn add-axes-labels [chart x-label y-label]
(doto chart (add-label "xAxis" x-label)
(add-label "yAxis" y-label)))
(defn populate-node [selector chart groups transition continuation]
(-> (.select js/d3 selector)
(.datum groups)
(.transition)
(.duration (if transition 500 0))
(.call chart)
(.call continuation)))
(defn force-layout-plot []
(d3-page "Force-Directed Layout"
"webviz.force.force_layout();"
[:div#force.chart [:svg]]))
(defroutes site-routes
(GET "/force" [] (force-layout-plot))
(GET "/force/data.json" []
(redirect "/data/census-race.json"))
(route/resources "/")
(route/not-found "Page not found"))
(def app (-> (handler/site site-routes)))
In line 5
(include-css "/css/nv.d3.css"))
There's an extra ) there.
And in line 13,
"/master/nv.d3.min.js")]
There's one ) missing. Should be
"/master/nv.d3.min.js"))]
You should use an editor which can do the matching of braces, parentheses, and brackets, etc. automatically.