This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-12-19
Channels
- # beginners (240)
- # boot (9)
- # braveandtrue (2)
- # bristol-clojurians (2)
- # cider (2)
- # cljsrn (84)
- # clojars (1)
- # clojure (195)
- # clojure-belgium (9)
- # clojure-china (5)
- # clojure-denmark (4)
- # clojure-italy (7)
- # clojure-mke (1)
- # clojure-norway (1)
- # clojure-russia (16)
- # clojure-spec (74)
- # clojure-uk (15)
- # clojurescript (78)
- # clr (3)
- # code-reviews (4)
- # datascript (8)
- # datomic (71)
- # emacs (9)
- # hoplon (18)
- # jobs (3)
- # kekkonen (32)
- # klipse (19)
- # lambdaisland (2)
- # luminus (15)
- # off-topic (6)
- # om (35)
- # om-next (62)
- # onyx (17)
- # overtone (5)
- # pedestal (1)
- # perun (1)
- # planck (31)
- # protorepl (1)
- # re-frame (135)
- # reagent (34)
- # ring-swagger (6)
- # rum (54)
- # specter (3)
- # untangled (14)
- # yada (14)
https://www.reddit.com/r/Clojure/comments/5j0j86/absolute_newbie_question_do_i_need_to_learn/
it'll be hard to get an entry-level job with python (opinion again from reading a lot of job postings), same with elixir
@nur I read your post there, I'd say just learn Clojure. The way of doing things will carry over into more languages, for the better. I know I got better. With regard to work, I work as a contractor (and I hire subcontractors here), and I do 95% Clojure. The other 5% is split between Python and JS. But naturally it'll be easier to get work in JS overnight if you want into the oldest profession.
Yes, almost always. I market myself as a consultant, rather than as a code monkey. A lot of team building, architecture, and such for new products or refactoring old ones.
(defn- start-long-running-method []
(let [start-ts (ts/now)]
(jmx/register-mbean
(jmx/create-bean (ref {:time-elapsed (- (ts/now) start-ts)}))
“my.namespace:name=Foo")
(start-long-running-method)))
but when I try to do (jmx/read “my.namespace:name=Foo” :time-elapsed)
I keep getting 0
Try passing :time-elapsed
as a lambda (an anonymous function) :time-elapsed #(- (ts/now) start-ts)
Not sure that will work with interop but worth a try
qq, I'm trying to flatten a nested JSON structure into a map with the leaf key being the new key.
=>(let [test {:foo {:bar {:baz 123}} :qux false}]
(flatten-record test)
=> {:baz 123, :qux false}
(defn flatten-record
"Take a nested record and recursively flatten "
[record]
(into {}
(for [[k v] record]
(if (map? v)
(flatten-record v)
{k v}))))
@poooogles clojure.walk/postwalk
seems relevant.
@poooogles I think your solution is good as it is really.
hello guys
how can i generate all dates between two dates ?in string format like "yyyy-MM-dd"
@abdullahibra There are ways to format using SimpleDateFormatter: http://stackoverflow.com/a/14757757
To generate the dates, I'm not so sure there's a built-in way. So you'll need to use loop/recur or lazy-seq
or something to generate them.
https://github.com/clj-time/clj-time#clj-timeperiodic you can do something like (take-while #(time/before? % my-end-date) (time.periodic/periodic-seq start-date (time/days 1)))
@dominicm thanks i figured it out : (mapv #(.withFieldAdded start (DurationFieldType/days), %) (range 0 (inc ndays)))
(mapv #(str (.withFieldAdded start (DurationFieldType/days), %)) (range 0 (inc ndays)))
I have this routes file in luminus :
(ns paintings2.routes.home
(:require [paintings2.layout :as layout]
[compojure.core :refer [defroutes GET]]
[ring.util.http-response :as response]
[ :as io]
[paintings2.api-get :as api]
[compojure.route :refer [resources]]
[environ.core :refer [env]]
[paintings2.api-get :as api]
[clj-http.client :as client]))
(defn home-page []
(let [url ""
options {:as :json :query-params {:key (env :key) :format "json" :type "schilderij" :toppieces "True"}}]
(layout/render
"home.html" {:paintings (-> (client/get url options)
api/read-numbers
api/do-both-in-parallel-front)})))
(defn detail-page [id]
(layout/render
"detail.html" {:paintings (-> api/do-both-in-parallel-detail)}))
(defroutes home-routes
(GET "/" [] (home-page))
(resources "/")
(GET "/detail/:id" [] (detail-page (:id)))
(resources "/detail/:id"))
what I try to do it that the id of the url is passed on to the detail page function so the right data can be downloaded from a external api. Right now I see this error message :
Wrong number of args passed to keyword: :id
(GET "/detail/:id" [] (detail-page (:id)))
-> (GET "/detail/:id" [id] (detail-page id))
and this
(defn detail-page [id]
(layout/render
"detail.html" {:paintings (api/do-both-in-parallel-detail id)}))
`you can find the functions here: https://github.com/rwobben/paintings/blob/master/src/clj/paintings2/api_get.clj
Right, this is a result of using map
- LasySeq. You can use mapv
if you expect vactor in response from api/do-both-in-parallel
@roelofw your code in the home.html template is probably forcing the realisation of the lazy seq. Remember 2 or 3 weeks ago I mentioned that map produced a lazy seq and it was not good practice to use map only for side effects (like IO- for example the calls to the api). mapv
forces the lazy seq into a vector those realising the entire data structure. Another option would be to rewrite to use doseq
instead of mapv
@agile_geek so I can better rewrite the parallel reading of the two data streams that I want to display on the pages ?
You can just use mapv
for now.
@dominicm I was just about to link to that! 😉
@roelofw as an exercise, try writing an application that maps over lines read from a file using line-seq
and prints them to sys out and run it from the main method. You will find it does nothing.
I get the feeling that this first web application is more then I can chew at the moment
@agile_geek so I have to make a file with some lines and use line-seq to read them and display them on a webpage or on the console ?
@roelofw lazy sequences are something that takes a little getting used to when you come from an imperative language
@roelofw just try and print them to console in the main method by maping println
over the sequence returned from line-seq
and you'll see it does nothing.
Then see if what happens with mapv
then try rewriting to use doseq
@roelofw It's worth figuring out how lazy sequences work so you understand how they impact your desing with regard to I/O
Try looking at the docs page for line-seq
Depends what path you passed to the reader- assuming you are using a http://clojure.java.io/reader?
If your jsut specified the filename with no path it will expect to find it in the top level project directory.
So if you put that file in same dir as your project.clj
it should find it
I would give the file an extension tho or it will get confused with test/
directory
i.e. call the file test.txt
and use that in your string passed to the reader
and
C:\Users\rwobb\Desktop\clojure\read-file>dir
Volume in drive C has no label.
Volume Serial Number is C0BB-040D
Directory of C:\Users\rwobb\Desktop\clojure\read-file
19-12-2016 18:09 <DIR> .
19-12-2016 18:09 <DIR> ..
19-12-2016 17:50 110 .gitignore
19-12-2016 17:50 134 .hgignore
19-12-2016 18:09 <DIR> .idea
19-12-2016 17:50 796 CHANGELOG.md
19-12-2016 17:50 <DIR> doc
19-12-2016 17:50 11.433 LICENSE
19-12-2016 17:50 275 project.clj
19-12-2016 17:50 1.281 read-file.iml
19-12-2016 17:50 249 README.md
19-12-2016 17:50 <DIR> resources
19-12-2016 17:50 <DIR> src
19-12-2016 17:50 <DIR> target
19-12-2016 17:50 <DIR> test
19-12-2016 17:56 61 test.txt
8 File(s) 14.339 bytes
8 Dir(s) 757.095.403.520 bytes free
Where is the with-open
code? Which file?
in the first sentence of my question I stated :
I did : (with-open [rdr (
Where was that code executed? Where did you put the code above?
Did you put that in core.clj or in the REPL or elsewhere?
put the test.txt file in your resources directory and you will be able to read it with
function.
(ns read-file.core)
(defn read-with-line-seq
"read a file and display the contents woith line-seq"
[]
(with-open [rdr ( "test.txt")]
(println (line-seq rdr)))
)
(read-with-line-seq)
@roelofw and you got file not found exception?
yes, then I see this as output :
Exception in thread "main" java.io.FileNotFoundException: test.txt (Het systeem kan het opgegeven bestand niet vinden), compiling:(C:\Users\rwobb\Desktop\clojure\read-file\src\read_file\core.clj:11:1)
at clojure.lang.Compiler.load(Compiler.java:7391)
at clojure.lang.Compiler.loadFile(Compiler.java:7317)
at clojure.main$load_script.invokeStatic(main.clj:275)
at clojure.main$script_opt.invokeStatic(main.clj:335)
at clojure.main$script_opt.invoke(main.clj:330)
at clojure.main$main.invokeStatic(main.clj:421)
at clojure.main$main.doInvoke(main.clj:384)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.lang.Var.invoke(Var.java:379)
at clojure.lang.AFn.applyToHelper(AFn.java:154)
at clojure.lang.Var.applyTo(Var.java:700)
at clojure.main.main(main.java:37)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: java.io.FileNotFoundException: test.txt (Het systeem kan het opgegeven bestand niet vinden)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at $fn__9520.invokeStatic(io.clj:229)
at $fn__9520.invoke(io.clj:229)
at $fn__9433$G__9426__9440.invoke(io.clj:69)
at $fn__9532.invokeStatic(io.clj:258)
at $fn__9532.invoke(io.clj:254)
at $fn__9433$G__9426__9440.invoke(io.clj:69)
at $fn__9494.invokeStatic(io.clj:165)
at $fn__9494.invoke(io.clj:165)
at $fn__9446$G__9422__9453.invoke(io.clj:69)
at $reader.invokeStatic(io.clj:102)
at $reader.doInvoke(io.clj:86)
at clojure.lang.RestFn.invoke(RestFn.java:410)
at read_file.core$read_with_line_seq.invokeStatic(core.clj:7)
at read_file.core$read_with_line_seq.invoke(core.clj:4)
at read_file.core$eval12.invokeStatic(core.clj:11)
at read_file.core$eval12.invoke(core.clj:11)
at clojure.lang.Compiler.eval(Compiler.java:6927)
at clojure.lang.Compiler.load(Compiler.java:7379)
... 16 more
Process finished with exit code 1
As @dpsutton suggests you could put it in resources (you'll have to create it)
and use
instead of
It will probably be not finding the file because you are running the compiled cod ein your target dir and the file is not getting copied to the target directory
putting it in resources will fix that as resources get copied to target
now a new error-message :
Exception in thread "main" java.lang.IllegalArgumentException: No matching field found: close for class java.net.URL, compiling:(C:\Users\rwobb\Desktop\clojure\read-file\src\read_file\core.clj:11:1)
at clojure.lang.Compiler.load(Compiler.java:7391)
at clojure.lang.Compiler.loadFile(Compiler.java:7317)
at clojure.main$load_script.invokeStatic(main.clj:275)
at clojure.main$script_opt.invokeStatic(main.clj:335)
at clojure.main$script_opt.invoke(main.clj:330)
at clojure.main$main.invokeStatic(main.clj:421)
at clojure.main$main.doInvoke(main.clj:384)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.lang.Var.invoke(Var.java:379)
at clojure.lang.AFn.applyToHelper(AFn.java:154)
at clojure.lang.Var.applyTo(Var.java:700)
at clojure.main.main(main.java:37)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: java.lang.IllegalArgumentException: No matching field found: close for class java.net.UR
That's because resource
doesn'tr return a reader - jsut a url to the file
Basically you can wrap your (
in a
within the with-open
This works :
(defn read-with-line-seq
"read a file and display the contents woith line-seq"
[]
(with-open [rdr ( ( "test.txt"))]
(println (line-seq rdr)))
)
(read-with-line-seq)
and gives this as output : ("ik ben regel 1 " "ik ben regel 2 " "en ik ben regel 3" )
So you are printing the entire collection of lines so you can see them all. Try setting up a -main
method that calls you (read-with-line-seq)
function and run it from the terminal using lein run
moment, I have to make a main in project.clj : No :main namespace specified in project.clj.
@agile_geek then I see the same output : ("ik ben regel 1 " "ik ben regel 2 " "en ik ben regel 3" )
now I have to find out how I can make it work with mapv , I need somehow a map as input where rdr is a io object
Right now change your function so that instead of printing the whole sequence you map println over each element in the sequence returned by lien-seq
:
(map println (line-seq rdr))
and call it using lien run
not in the repl
Wierd, when I do what you said
(defn read-with-line-seq
"read a file and display the contents woith line-seq"
[]
(with-open [rdr ( ( "test.txt"))]
(map println (line-seq rdr))))
Right!
line-seq
returns a lazy sequence
when you map a function that has only side effects (like input and output) over a lazy sequence it has no effect as nothing forces the sequence to realise itself
try changing map
to mapv
which forces the sequence to be realised and put into a vector
I did that already and see this as output :
"ik ben regel 1 "
"ik ben regel 2 "
"en ik ben regel 3"
with this as code :
(defn read-with-line-mapv
"read a file and display the contents woith line-seq"
[]
(with-open [rdr ( ( "test.txt"))]
(mapv println (line-seq rdr)))
)
So read that link that @dominicm posted and see if you can see why?
BTW if you call the -main
function in the REPL it will throw a Stream closed exception
that's cos the REPL forces the print of the first element of the sequence (the P in REPL stands for print) but when it loops back to print the next element the reader has closed.
that's why I asked you to run it via lein run
In that page there is nothing about mapv but it seems that mapv is not lazy so the line-seq gets executed
That's right
mapv
has to realise the whole sequence to put it in a vector
Lazy sequences may seem like something you don't want to I/O but think about reading a huge file.
If you realise the whole file in memory it will take a long time and you will probably run out of memory
So once you understand lazy seq's they are very useful
as long as you don't keep hold of the whole collection in memory
oke, then I have to find another way to read two responses in parallel and merge the 2 responses in one respons so I can parse them so I can display the right info
if I do it after each other the user has to wait long before he/she sees something on the screen
Problem is that I have to have the ids first of the paintings before I can "download" the data and the image of each painting
so 3 request to three different urls where 2 depends on the outcome of the first respons
You can jsut use mapv
instead of map
in your fn's for now
also for this one :
(defn do-both-in-parallel-front
[ids]
(let [paint-thread (future (pmap #(read-data-front-page (read-json-data %)) ids))
image-thread (future (pmap #(read-image-url (read-image-data %)) ids))]
(map merge @paint-thread @image-thread)))
Yeah not sure why you need futures
That's probably cos of the lazyness. You may have to look at using doall
although if you change your map merge
to mapv merge
that should work without futures
(defn do-both-in-parallel-front
[ids]
(let [paintings (pmap #(read-data-front-page (read-json-data %)) ids)
images (pmap #(read-image-url (read-image-data %)) ids)]
(mapv merge paintings images)))
@agile_geek that code works well
Can we do the same with this function :
(defn do-both-in-parallel-detail
[ids]
(let [paint-thread (future (pmap #(read-data-detail-page (read-json-data %)) ids))
image-thread (future (pmap #(read-image-url (read-image-data %)) ids))]
(mapv merge @paint-thread @image-thread)))
There's no need for separate threads in futures as the pmap
spins up it's own threads to make calls in parallel
The mapv
is required as pmap
is semi-lazy so you have to force it to realise similar to map
in that read-file example
oke, I get the feeling that my code is not optimal. We have to use "tricks" to make things work
You could probably use map
instead of mapv
depending on how your page displays the data. i.e. if the templating functions always consume the whole sequence.
I am not sure what Selmer does
Nothing wrong with your code for that really. It would be good if you could make one call to the api to fetch the whole list of paintings with their names, etc. but that's the api you are calling not your code
There are other ways of fetching the images and painting details and merging them together but not sure they are much better, just different
Anyway I'm heading home now
I am trying to use ring-transit, but it doesn't seem to convert the response to transit form. Is there anyway to debug why this is happening?
Response that I am trying to send is something like ({:songs [{:path "song1.mp3", :id 0, :track-number "2", :album "Album1"} {:path "song2.mp3", :title "Song 1", :id 1, :track-number "9", :album "Album1})
You mean character encoding? I am not setting anything for that so it is what it is by default
sorry, I mean this one : https://www.refheap.com/
so first part has the routes definitions and under that I copy pasted relevant functions from my other code files
@neurogoo You are passing handler
as the “options” argument in your wrap-middleware
function. The ->
macro already passes handler
as the first argument. You want (wrap-transit-response {})
— replace {}
with whatever specific options you want.
Also you seem to have a typo — /daa
in your routes? If you correct that (to /data
) then you can remove the explicit (GET “/song/:id/data” …)
route.
No, that is not typo 😄 It was just temp route to tryout that context thing. But thanks for the first tip! I will fix that see if that helps
@mlev That code will run when you load that namespace, before any app code runs. I doubt that’s what you want? Shouldn’t that be in a function that gets invoked?
@seancorfield , makes sense to me. Within the Luminus app I have a home.html template file with the following code:
{% extends "base.html" %}
{% block content %}
<div id="content" ></div>
{% endblock %}
and a base.html template file with the following code section:
<!-- scripts -->
{% script "/assets/jquery/jquery.min.js" %}
{% script "/assets/tether/dist/js/tether.min.js" %}
{% script "/assets/bootstrap/js/bootstrap.min.js" %}
<script type="text/javascript">
var context = "{{servlet-context}}";
</script>
{% script "/js/app.js" %}
{% block page-scripts %}
{% endblock %}
I may be missing something elementary here, but I figured others may be running into a similar issue 🙂Perhaps I am looking at the wrong port? I am typing LocalHost:3000
into my browser. Here is the actual output from lein run
though:
-=[guestbook started successfully using the development profile]=-
2016-12-19 16:10:00,672 [main] INFO luminus.http-server - starting HTTP server on port 3000
2016-12-19 16:10:00,750 [main] INFO org.xnio - XNIO version 3.3.6.Final
2016-12-19 16:10:00,938 [main] INFO org.projectodd.wunderboss.web.Web - Registered web context /
2016-12-19 16:10:00,953 [main] INFO luminus.repl-server - starting nREPL server on port 7000
2016-12-19 16:10:00,953 [main] INFO guestbook.core - #'guestbook.config/env started
2016-12-19 16:10:00,969 [main] INFO guestbook.core - #'guestbook.db.core/*db* started
2016-12-19 16:10:00,969 [main] INFO guestbook.core - #'guestbook.handler/init-app started
2016-12-19 16:10:00,969 [main] INFO guestbook.core - #'guestbook.core/http-server started
2016-12-19 16:10:00,969 [main] INFO guestbook.core - #'guestbook.core/repl-server started
Thanks, @gdeer81 , always appreciate your help as well. Here is the error screen:
2 errors: Failed to load resource: the server responded with a status of 404 (Not Found)
@mlev did you update your project.clj file to tell cljsbuild where to output the compilation to?
@gdeer81 , my project.clj file contains the following:
:cljsbuild
{:builds {:app {:source-paths ["src/cljs"]
:compiler {:output-to "target/cljsbuild/public.js/app.js"
:output-dir "target/cljsbuild/public/js/out"
:main "guestbook.core"
:asset-path "/js/out"
:optimizations :none
:source-map true
:pretty-print true}}}}
:clean-targets
^{:protect false}
[:target-path
[:cljsbuild :builds :app :compiler :output-dir]
[:cljsbuild :builds :app :compiler :output-to]]
The main keys under my :defproject are:
:source-paths ["src/clj"]
:resource-paths ["resources" "target/cljsbuild"]
:target-path "target/%s/"
and there are a few additional keys under :defproject:
:profiles
{:uberjar {:omit-source true
:aot :all
:uberjar-name "guestbook.jar"
:source-paths ["env/prod/clj"]
:resource-paths ["env/prod/resources"]}
:dev [:project/dev :profiles/dev]
:test [:project/dev :project/test :profiles/test]
:project/dev {:dependencies [[prone "1.1.4"]
[ring/ring-mock "0.3.0"]
[ring/ring-devel "1.5.0"]
[pjstadig/humane-test-output "0.8.1"]]
:plugins [[com.jakemccrary/lein-test-refresh "0.14.0"]]
:source-paths ["env/dev/clj" "test/clj"]
:resource-paths ["env/dev/resources"]
:repl-options {:init-ns user}
:injections [(require 'pjstadig.humane-test-output)
(pjstadig.humane-test-output/activate!)]}
:project/test {:resource-paths ["env/test/resources"]}
@mlev so when you did lein cljsbuild once
did you get any errors? you shouldn't be getting a 404 on app.js if the compiler did its job. Is app.js in your output directory?
@gdeer81 , I reran the lein cljsbuild once
, received the message:
Compiling ClojureScript...
2016-12-19 17:11:04,206 [main] DEBUG org.jboss.logging - Logging Provider: org.jboss.logging.Slf4jLoggerProvider
Then reran lein run
and can still see both tabs but no "Hello, Reagent."pardon me good folks, how would I set up my lein project.clj
to make (use 'clojure.java.jdbc)
not crash when I use lein run
?
:dependencies [[org.clojure/clojure "1.8.0"],
[clojure.java.db]]
does not seem to work 😞that should be clojure.java.jdbc and it needs a version string
is there a way to do "latest"?
yes, and don't
hahaha! very well! any recommendations?
@mlev the code snippet you posted above said that it was supposed to say "Hello world"
goomba [org.clojure/java.jdbc "0.6.1"]
should be good http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.clojure%22%20AND%20a%3A%22java.jdbc%22
ah, yes, thank you 😄
I suppose I could've googled that 😞
but you're all so friendly and helpful!!
goomba there's a lein plugin called lein ancient
that can help you find out about newer versions of libraries, but I don't recommend just using "latest version always"
my problem was finally solved by explicitly setting header Content-Type to "applicaiotn/transit+json" -_- And I have troubleshooted this so long....
generally you'll find the latest release via maven or clojars too
@mlev the code you posted was from the previous section, your code should look totally different now
another fun trick is seeing what version everybody open source is using https://crossclj.info/
@gdeer81 , I apologize, I am trying to display the the Reagent version based on the following code in my core.cljs file:
(ns guestbook.core
(:require [reagent.core :as reagent :refer [atom]]))
(defn home []
[:h2 "Hello, Reagent"])
(reagent/render
[home]
(.getElementById js/document "content"))
@mlev you might have to just push your project to github to make it easier to review all the code to make sure it matches what the book is expecting. I feel like I'm debugging blind
@gdeer81 , github may be the way to go on this one, true. Here is the code in my C:\...\guestbook\target\cljsbuild\public.js\app.js file:
var CLOSURE_UNCOMPILED_DEFINES = null;
if(typeof goog == "undefined") document.write('<script src="/js/out/goog/base.js"></script>');
document.write('<script src="/js/out/cljs_deps.js"></script>');
document.write('<script>if (typeof goog == "undefined") console.warn("ClojureScript could not load :main, did you forget to specify :asset-path?");</script>');
document.write('<script>goog.require("guestbook.core");</script>');