This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-12-09
Channels
- # adventofcode (187)
- # aws (1)
- # aws-lambda (1)
- # beginners (162)
- # boot (64)
- # cljs-dev (6)
- # cljsjs (2)
- # cljsrn (32)
- # clojure (357)
- # clojure-greece (1)
- # clojure-korea (4)
- # clojure-russia (63)
- # clojure-sanfrancisco (3)
- # clojure-spec (91)
- # clojure-uk (63)
- # clojurescript (74)
- # clojurex (10)
- # code-reviews (55)
- # core-async (4)
- # core-typed (1)
- # cursive (17)
- # datascript (36)
- # datomic (43)
- # devcards (4)
- # dirac (3)
- # emacs (59)
- # hoplon (286)
- # jobs-discuss (399)
- # luminus (4)
- # mount (9)
- # off-topic (30)
- # onyx (53)
- # protorepl (3)
- # re-frame (88)
- # reagent (4)
- # spacemacs (1)
- # specter (14)
- # untangled (1)
- # vim (42)
Can functions be invoked at the top level in clojure? I have this situation where I want to generate the definitions for a bunch of functions from some data in an array of maps. I'd like to have a top level function call that iterates over the array and builds and binds one function per map using def. I don't know if clojure supports this level of dynamicism though.
@bcbradley I think technically you can do that using alter-var-root
, but I’m curious what use case is motivating you to do such a thing.
@kumarshantanu I'm making a clojure library for https://www.khronos.org/registry/spir-v/specs/1.1/SPIRV.html by leveraging https://github.com/clojurewerkz/buffy but I have found it easiest / least error prone to codify the api as something resembling a table, and then convert the tabulated data into functions and documentation programmatically
for instance, OpSourceContinued looks like https://www.khronos.org/registry/spir-v/specs/1.1/SPIRV.html#OpSourceContinued looks like
{:name "source-continued" :code 2 :operands [{:name "continued-source" :type :literal-string}]}
If you just provide a factory fn, which given a table would create and return the fns, would that not suffice? If the fns are created at runtime, the user can create vars from those, probably also instrumenting those if required etc.
I don’t think there’s any perf penalty in that approach
in fact, if you define a var and don’t enable direct-linking then you may incur a perf penalty
or use the table to generate a library and then let the library be visible to the user
Would the table ever need to be manipulated, visualized, stored in DB etc? Imagine the use cases a user may want to use it in. If the answer is yes, then it needs to be a first class concept in your API.
Actually, I don’t know anything about graphical shaders, so can’t comment personally, but I’d suggest that you consider the various use cases a user may have, then take a call.
i do feel like it is pretty nice to be able to view the salient details of the entire api as a table
@hippo look here for a example : https://github.com/clojure-cookbook/clojure-cookbook/blob/master/04_local-io/4-09_read-write-files.asciidoc
Hey guys, which is the best practices in case you lazy iterate on collection and you should check that rows not duplicates?
@rustam.gilaztdinov I would do it like this (
so I make a set of it and compare it to the orginal. if there are no duplicates both are the same
Yes, i do the same, but i don’t won't to force my collection into set
Think about distinct
, may be
And this may be solution
(defn distinct-by
"Returns elements of xs which return unique
values according to f. If multiple elements of xs return the same
value under f, the first is returned"
[f xs]
(let [s (atom #{})]
(for [x xs
:let [id (f x)]
:when (not (contains? <@U06QXASV8> id))]
(do (swap! s conj id)
x))))
@rustam.gilaztdinov then you have to make a function to for comparision
Check this out
(let [coll (repeatedly 1000000 #(do
{:id (rand-int 500000)
:a (rand-int 100000)
:b (rand-int 100000)}))]
(println "distinct-by"
(with-out-str
(time
(plumbing.core/distinct-by :id coll))))
(println "group-by"
(with-out-str
(time
(->> coll (group-by :id) (vals) (map first))))))
distinct-by "Elapsed time: 0.054141 msecs"
group-by "Elapsed time: 1113.419474 msecs"
plumbing.core/distinct-by
— this is it
https://clojurians.slack.com/archives/beginners/p1481272651001037
@rustam.gilaztdinov yeah but you are not comparing the same things there. vals
forces the entire lazy sequence to realise after you've already walked it with group-by
Of course if you really want performance you can step into the world of mutable data structures (yeuch!) but I would confine them to the scope of you fn not globally
This is exactly what @weavejester has done in his implementation https://weavejester.github.io/medley/medley.core.html#var-distinct-by using volatile!
@bcbradley I think you're definitely looking for macros
I've seen a few libraries do what you're looking for. It's perfectly acceptable to use macros to automate calls to def
https://github.com/SevereOverfl0w/bukkure/blob/7fd1cb6dc875f137698dee78deea149d31e4d2e5/src/bukkure/config.clj#L12-L32 this is similar to what you want. I don't know if it's a best practice the way it's written here. I can't recall any of the other libs that do this though!
Is it right that if I refractor all the client/get out only do-both-in-parallel is not pure in the api-get.clj file ?
I’d have to see the latest version of your code but that sounds likely, from what I remember of your code.
Are you keeping an up-to-date copy of the code up on GitHub now?
OK, so you have client/get
in three functions and the do…parallel
calls two of them, so everything is non-pure there.
we talked in the clojure channel that I can refractor the client/get to the home route
Given that both read-data-painting
and read-image-url
are dependent on their id
argument to call client/get
, you can’t do much about that.
and i like that those keep the client/get call inside of them because the function is type (id -> data about the thing with that id)
Is there a higher order function or idiomatic way to convert a sequence of maps to a map based on a key fn? Or is it just reduce
ex. (reduce #(assoc %1 (:id %2) %2) {} [{:id 1} {:id 2}]) ;;=> {1 {:id 1}, 2 {:id 2}}
I change the read-numbers to this :
(defn read-numbers
"Reads the ids of the paintings"
[response]
(->> :body
:artObjects
(map :objectNumber)))
and the home.route to this :
(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 have this test :
(deftest test-app
(testing "get numbers"
(is (= [ "1234" "abcd"] (api/read-numbers [ {:objectNumber "1234"} {:objectNumber "abcd"} ])))))
and I see this output :
AIL in (test-app) (api-get.clj:9)
get numbers
expected: (= ["1234" "abcd"] (api/read-numbers [{:objectNumber "1234"} {:objectNumber "abcd"}]))
actual: (not (= ["1234" "abcd"] ()))
found it but ran into another issue : Im testing now with
(read-numbers [{:body {:artObjects {:objectNumber "1234"} {:objectNumber "abcd"}}} ])
but in repl I see these error messages :
RuntimeException Map literal must contain an even number of forms clojure.lang.Util.runtimeException (Util.java:221)
RuntimeException Unmatched delimiter: } clojure.lang.Util.runtimeException (Util.java:221)
RuntimeException Unmatched delimiter: ] clojure.lang.Util.runtimeException (Util.java:221)
RuntimeException Unmatched delimiter: ) clojure.lang.Util.runtimeException (Util.java:221)
fixed but something is still wrong. See this repl :
(read-numbers [{:body {:artObjects [{:objectNumber "1234"} {:objectNumber "abcd"}]}} ])
=> ()
the function looks like this :
(defn read-numbers
"Reads the ids of the paintings"
[response]
(->> (:body response)
:artObjects
(map :objectNumber)))
Changed it : (read-numbers [{:body {:artObjects ({:objectNumber "1234"} {:objectNumber "abcd"})}} ])
oke, changed it again : (read-numbers ({:body {:artObjects {{:objectNumber "1234"} {:objectNumber "abcd"}}}} ))
(read-numbers {:body {:artObjects {{:objectNumber "1234"} {:objectNumber "abcd"}}}} )
(read-numbers {:body {:artObjects [{:objectNumber "1234"} {:objectNumber "abcd"}}]}})
newbie question re core async – how should I think the size of my buffers? do they want to roughly correspond to processors available? memory available? something else? does it depend on workload?
i fel like i ask this every other day, but whats the best way to do this?
(??? [[1 2] [3 4] [5 6]])
=> [[1 3 5] [2 4 5]]
@drewverlee apply map vector
-> transpose
yep, thats it. but i cant grok why. i dont think i understand what apply does
ok, i understand apply. I think its actual some behavior or map i wasn’t aware of/ wasn’t using: Returns a lazy sequence consisting of the result of applying f to the set of first items of each coll
thanks jswart!
in the future i might be able to ask a barliman. https://www.youtube.com/watch?v=er_lLvkklsk
will byrd is one of the smartest and also funniest people I ever had the pleasure to meet
I’m going to make it to the next conj, clojure job or not 🙂
is there version of take with a predicate? like “only take if predicate"
take-while ?
clojure.core/take-while
([pred] [pred coll])
Returns a lazy sequence of successive items from coll while
(pred item) returns true. pred must be free of side-effects.
Returns a transducer when no collection is provided.
Or filter
, if you want to skip elements that don’t match the predicate, rather than stop take
ing entirely at the first failure.
right, i suppose i’m looking to skip elements i dont match, not stop when i reach one i dont need.
(Though I’d use (remove nil? …)
instead of (filter (complement nil?) …)
in the latter case
@agile_geek. More specially, i’m not sure how to grow a collection to a certain point.
Grow a collection until it meets a predicate (coll count is greater then 10). I can see using while
to make this work, but (maybe incorrectly) i feel while isn’t the right idea.
@roelofw I get the impression you're struggling a little with syntax. Here is a little reminder that might help:
A list is a datastructure in Clojure that is accessible only in sequence from the first element i.e to get to third element you have to read the first and second element. A list is written inside parenthesis (a b c)
Clojure's compiler will interpret the first thing in a list as a function and will try to evaluate it using the subsequent things in the list as arguments e.g. (fn arg1 arg2)
. This is why when you put your map inside parens you got an arity error as a map is a fn that takes the key to use to look up a value but you just had the map inside the parens so you were missing the key argument.
If you want to write a list as a literal and not have the first element evaluated as a function then use a quote e.g. '(1 2 3)
is a list of the integers 1,2 and 3.
A vector is an indexed (associative) data structure so you can access an element using it's index. It's written using brackets (square) like so; [1 2 3]
. A vector is also used in the context of a function definition to represent an argument or in a let
, loop
, etc. to bind a value to a symbol (a name) e.g. (defn add-3[x] (+ x 3))
or (let [a 1 name "Chris"] .....)
A map is an associative data structure that consists of key-value pairs and is written using braces e.g. {:a 1 "b" 2}
I know you know most of this but if you are struggling to work out why something is giving arity errors or an error mentioning Ifn
(the interface for a function in Clojure) it's often a syntax problem i.e you have parens in the wrong place, so remember the syntax of Clojure is summed up by my friend @krisajenkins as:
The first thing in a list is a function.
The first thing in a list is a function.
and the first thing in a list is a function
Hope that helps?
@drewverlee what do you mean by grow? You can write a function that produces a lazy sequence of things infinitely and then take only the number you need.
E.g. for first 10 natural numbers: (take 10 (iterate inc 1))
@agile_geek thanks, I struggeling because I learned a lot of things and mixed up things now
so you could def natural numbers and take 10 like this:
(def natural-numbers (iterate inc 1))
(take 10 natural-numbers)
@roelofw no problem it's part of learning. We all do it.
trying to figure out why this isn't working:
(defn get-one-from-table [table id]
(jdbc/query mysql-db ["select * from ? where id = ?" table id]))
seems to insert strings within the query string:
"select * from 'account' where id = '1'"
The jdbc prepared statement interpreter assumes that ?
params refer to query literal values, not, um, ddl symbols?
@kyle_schmidt I don't think you can substitute the table name using a placeholder like that
or what @donaldball said
I seem to recall the syntax for mysql is backticks if you need to escape the table name
You’ll have to do your own sanification if you can’t trust the table name of course, sadly
If you’re going to be doing query composition widely, you might want to look at using e.g. honeysql, which handles cases like this nicely
awesome thank you! I took a look at honeysql and seems to get at the general formatting that I need because I do this for most tables in my database
The other lib people like to use atop clojure.java.jdbc is I think hugsql these days. It eschews query composition (largely) and advocates resource files of queries.
Never tried but you might be able to construct the query with the table using str
or clojure.string/join
like so:
(defn get-one-from-table [table id]
(jdbc/query mysql-db [(str "select * from " table " where id = ?" id]))
Also you could pass it to prepared-statement
and then call the resulting statement.
@agile_geek that works too!
This might be useful too http://www.shrayas.com/dynamic-prepared-statements-in-clojure.html
also just curious because I've never used a build tool before (coming from Python) but what is the Clojure way to connect to a database? Is that something I should configure in the application itself or within project.clj?
If you get really stuck I'm sure @seancorfield would help out. He's a nice guy and one of the lead contributors to clojure.java.jdbc
I realize I'm probably opening up a can of worms but any resources around this topic are greatly appreciated
@kyle_schmidt usually you would either construct the connection or connection pool in the code using parameters that you pick up from an edn file or more often environemnt variables. If you use environment variables you might want to look at environ which lets you provide defaults in either your project.clj
or, even better, a separate profiles.clj
that you keep out of version control system if you have passwords etc. in it.
You can parse an old fashioned properties file too.
@kyle_schmidt I think the Luminus framework has good examples
i've been using properties files. I check in sample ones and let the person make a real one from the sql.properties.config
version
but it starts you off with an H2 database for developing and then when you're going to certification or prod you run your ddl and migration if there is data you want to put into cert and prod
if you have a better build system than us, you can have it replace a checked in version with the actual production connection strings, secrets, etc
cool! thank you for the help!
@kyle_schmidt Happy to help — just got back from lunch — and I can try to answer any java.jdbc questions!
There’s also the (community-maintained) documentation for java.jdbc here: http://clojure-doc.org/articles/ecosystem/java_jdbc/home.html
And I’ll +1 @agile_geek suggestion to use a connection pool (there are examples in the above docs for two such libraries!) and build that at application startup and pass that around for java.jdbc to get connections from.
The SQL DSL I usually point people at, to use on top of java.jdbc, is HoneySQL https://github.com/jkk/honeysql — I really like that it lets you compose SQL fragments, which is very helpful if you’re dealing with complex, dynamically constructed queries.