This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-12-21
Channels
- # beginners (201)
- # boot (125)
- # cider (3)
- # cljs-dev (21)
- # cljsrn (165)
- # clojars (8)
- # clojure (332)
- # clojure-belgium (1)
- # clojure-gamedev (8)
- # clojure-russia (75)
- # clojure-spec (25)
- # clojure-uk (96)
- # clojurebridge (2)
- # clojurescript (130)
- # code-reviews (16)
- # cursive (26)
- # datomic (20)
- # devops (6)
- # emacs (6)
- # hoplon (90)
- # jobs (9)
- # luminus (2)
- # off-topic (4)
- # om (65)
- # onyx (5)
- # pedestal (4)
- # protorepl (6)
- # re-frame (34)
- # reagent (12)
- # ring (4)
- # ring-swagger (7)
- # specter (2)
- # test-check (8)
- # untangled (2)
- # vim (1)
- # yada (6)
I’m not sure if this is the right place or format, but I’m really struggling with getting file uploads to work through compojure/clj-http. I’ve posted an SO question with more details: http://stackoverflow.com/questions/41253088/422-unprocessable-entity-response-when-posting-file-upload-in-clojure
I have a question. A function has become easily longer like "namespace + function". How can I define another shorten name?
user=> (def d clojure.repl/doc)
CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.repl/doc, compiling:(/private/var/folders/c8/ynqzx6vs51nfv5jzxb11tr600000gn/T/form-init7130854364890860285.clj:1:1)
ichise.masashi: you can use require with :as or rename
or with clojure.repl, even just use
(though use is not recommended in general)
(use 'clojure.repl) (doc +)
thanks. I konw about use
. the way is dangerous.
and require ... :as
shorten only namespace.
phoenix.core=> (require '[clojure.repl :as r :refer [doc] :rename {doc d}])
nil
phoenix.core=> (d +)
-------------------------
clojure.core/+
([] [x] [x y] [x y & more])
Returns the sum of nums. (+) returns 0. Does not auto-promote
longs, will throw on overflow. See also: +'
nil
so that lets you refer and rename together
I couldn't get it to rename without referring though
ohhh, thank you very much. I had wanted just like this.
Is it possible to display something like 1 2 3 4 ...... 398 399 400
as pagination and change that when we are for example on page 3 where 2 3 4 5 398 399 400
must be displayed
@roelofw not sure what your trying to 'paginate' but you could use drop
and take
to very simply select a range of items from a collection. For example:
(let [numbers (range 1 401)]
(take 10 (drop 10 numbers)))
@agile_geek I m trying to find a way I can display more paintings.
@roelofw so one way of doing this would be to store the id's in the session and then use take
and drop
to retrieve the appropriate 'page' of id's (you would need to store the index of the first id on the current page and the page size (number of paintings per page) as well.
@agile_geek so store all the id's in a sesssion ?
That's one way.
Alternatively as the id's don't change often you could store them in an atom when the server starts up (make the get id's api call just once at start up) and then just store the index of the first id on current page and the page size for each user in their session
Not really
You can call that function and store the results
Ah I see what you mean
Is there an API call that can fetch all painting id's in one call?
You could rewrite your fn to make that call and store the results.
If you do that at server startup and store in an atom it would only delay the start of your server but it wouldn't have to call for every user
see this page : http://rijksmuseum.github.io/
Ah OK. Still you could make the calls at server startup as the ids won't change much over time.
It would mean any new paintings wouldn't appear until you restarted the server (or you added a timer to refresh the cache of ids [the atom] every few hours)
I'd have to look it up. Check the documentation
never used liminus
sorry, I mean here : https://github.com/weavejester/lein-ring#general-options
@agile_geek do you sometimes fork my project to take a look at it
I did yes
You could just add the call inside the Def of the atom then it would run on load of the app
You might want to use defonce rather than def if you are using reload middleware otherwise you'll call the API everytime you reload your code in development
You're not adding a fn to an atom (although you could) you're constructing the atom from the results of a fn call
So instead of nil
call a fn to return the vector of ids
(def apple-price (atom (get-apple-price)))
Or probably better (defonce apple-price (atom (get-apple-price)))
oke, and that one has to be repeated some 470 time where the number repeated is the page number
Well you'll need to write one fn that makes all calls necessary and returns one vector of ids
that I could do with (defonce apple-price( atom ( for x [ 1 .. 470] (get-apple-price x ))))
@roelof If you were sitting next to me and I would be incorporating you I would tell you to start way earlier. Just define an atom that you initialize on application startup with a static value. Make that work first.
I trying now with google and reading to find out how I can initialize a function or a atom on startup
Don't use for
either as it's lazy evaluated. See your experiment the other day
If you are passing in a number to the api calling function (like in your for
example) you can user mapv
over a list of numbers:
(mapv get-apple-price (range 1 471))
Where get-apple-price
takes a number as an argument
Note: the range is (range 1 471)
as the end index is exclusive that will produce (1 2 3 4....470)
Presumably you are going to have to write a fn to call the api that fetches id's based on some parameter to the api? I am guessing that's not a number?
nope, it something like this XX-X-NN where X is a character of [a-z] and n is a number between 1 and 99
I mean't that you need a vector of all the painting id's. If you can only fect so many ids in each call how will you make the second call to get the next lot of ids? At the moment I think your query getting the ids is fetching all the ids for a specific painting collection?
(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)})))
I am not sure how you would change that url to fethc the next lot of ids?
Do you need a vector of collection types that you mapv
over?
so it will be something like this :
options {:as :json :query-params {:key (env :key) :format "json" :type "schilderij" :toppieces "True" :p p :ps 10 }}]
@agile_geek that part is clear to you
The API supports those P and PS arguments?
I even can make two calls where one will be a Dutch text and the other a English text so a user could choose the language
calls this function :
(defn read-numbers
"Reads the ids of the paintings"
[response]
(->> (:body response)
:artObjects
(map :objectNumber)))
which needs this one :
(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/fetch-paintings-and-images-front-page)})))
You need to mapv a fn that makes an API call. read-numbers
just gets data from the response from the API call
@agile_geek agreed ?
TBH I'm not sure. I haven't got time to investigate the API.
at second thought it not the right place. Then it's get called everytime we visit a page
Yeah I think you need to make your api calls in a function that you call from the atom def
I disagree about adding features. You just need to refactor some of your code into other functions.
The issues you are experiencing are not to do with Clojure but are about the design of the app and an understanding of the api's you are calling. This can happen in any language.
I made this one earlier in rails but then I had the luck that there were plugins that could do a lot of work for me
Ah but if you wanted to do something the plugins couldn't you would be in a worse position. That's why a lot of experienced developers prefer composing functions in the way clojure does. It's a steeper learning curve but it pays off in the long run
I think I understand the api that im calling but have a lack of understanding how to use it in a way I can use so I can add things later
@roloef There is a difference between programming a system and plugging things together. You can get work done with both. So I am on no side here. Its just that, both things also serve different goals / a different audience with different drawbacks. If you have something that works, why write it in a new language?
True. Although you are wroking with different constraints in both cases.
@agile_geek maybe a solution to find out if I can make it work that the call to the api will be on startup
@sveri no problem. I only try to give you a answer to your question why make something on clojure where I have made it with rails
@agile_geek could that idea work ?
@roelofw calling the api on startup? Yes. that's what I was suggesting. Call it to retrieve the ids and store them in an atom that you can page over. However if the api supports pages you may not even need to do that. Simply store the current page number in the session and extract that from the session for every request and pass it to the api to show a page full of id's.
I have to study this page well : https://github.com/ring-clojure/ring/wiki/Sessions
I mentioned this a few days back. By default sessions in ring are stored in an in memory store https://github.com/ring-clojure/ring/wiki/Sessions
so there is some state (data saved per session) but you don't have to worry about managing it.
If you use the encrypted cookie version of ring sessions you end up passing the session data as an encrypted cookie in the request/response so your server would actually be stateless. I would just use the in memory default for now.
Oké So if i understand you right, store the current page number in a session and use that for aan request to the api
I think they are seeing as both usernames use 'oke' instead of the normal 'okay'. It's a clear sign imo
the idea is to store the current page in a session and use that for displaying a few numbers before and after it and use that for request to a api, Do I understand the idea well ?
Basically- yes
@roelof I would like to stress that again. Take your plan and split it down into very small tasks that build upon each other. Start as easy as possible and try to write tests for your functions.
The only things that do not have test in my app are the tests where everything is read and the routes
@roelofw actually I've been a bit stupid. You can do this without sessions. If you pass page number as a query parameter from a link on your home page. i.e. you have a link on home page for next page that passes the next page number (i.e. 2 if you're on page 1) in the query params of the href i.e. /?page-num=2 You can then change your home-page fn and the route for home-page to get the page-num from the query string and pass it to the query for the api call. You would need to return some new data in the rendered page i.e. next page number and previous page number. You would also need to add {% if %} excpressions to work out if you want to render the 'next page' and 'prev page' links depending on their values i.e. if next page number is < 470 render next page link otherwise don't as you have the last page.
oke, I can do that also. Then I could make a seq a few numbers smaller then the current one and some more
I have then to check two things. The numbers smaller cannot be smaller then 1 and not bigger then 470
what is the best way to transform a vector into arguments?
I have a vector of strings that I want to use as arguments to a format function (format "%s \n %s, %s" ["a" "b" “c”])
like this but I need to remove the vector
roelof reduce takes a two argument function
@josh_tackett you mean something like the last example ?
(apply format format-string data)
nope like this ^^^
@roelof the join doesn’t add the formatting string
@josh_tackett oke, which format do you want it to be then
@roelof I already figured it out
this was the answer: (apply format "%s \n %s, %s" ["a" "b" “c”])
@josh_tackett , when I try your solution I see error messages
@roelof that solution actually works though
@roelof also, you can use your direct messages window to try out plugins without spamming the channel if you don't know what the result will be
phoenix.core=> (apply format "%s \n %s, %s" ["a" "b" "c"])
"a \n b, c"
I see this on my repl :
(apply format "%s \n %s, %s" ["a" "b" "c"])
CompilerException java.lang.RuntimeException: Unable to resolve symbol: in this context, compiling:(C:\Users\rwobb\AppData\Local\Temp\form-init5435960750035625814.clj:1:984)
=> "a \nb, c"
looks like you copy pasted an nbsp at the beginning of the line before the code - the code ran
(and had the right result even)
Hello guys, i have troubles understanding this reduce
output:
(reduce (fn [acc x] (when (odd? x) (assoc acc x x))) {} [1 2 3])
{3 3}
I was expecting {1 1, 3 3}
- what am i missing?Try using reductions
instead of reduce
to see the intermediate output
I quite like the cond->
form for reducing fns to avoid snafus like this
(fn [acc x] (cond-> acc (odd? x) (assoc x x)))
(linked at the bottom of http://clojuredocs.org/clojure.core/cond)
ha ha yeah, there are symbols that don’t play nicely with search engines
doc
and source
are two of my best friends
well, that's something actually missing from clojuredocs (unless the link was formatted wrong)