This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-01-06
Channels
- # architecture (8)
- # aws (2)
- # beginners (156)
- # boot (163)
- # cider (22)
- # cljs-dev (2)
- # cljsrn (11)
- # clojars (6)
- # clojure (328)
- # clojure-austin (7)
- # clojure-dusseldorf (10)
- # clojure-italy (2)
- # clojure-russia (19)
- # clojure-spec (178)
- # clojure-uk (86)
- # clojurescript (81)
- # cursive (17)
- # datomic (33)
- # funcool (40)
- # hoplon (8)
- # jobs (5)
- # klipse (13)
- # leiningen (1)
- # luminus (21)
- # off-topic (140)
- # om (49)
- # om-next (4)
- # onyx (29)
- # planck (5)
- # protorepl (2)
- # re-frame (58)
- # reagent (2)
- # remote-jobs (4)
- # ring-swagger (16)
- # testing (1)
- # untangled (26)
- # yada (27)
tbh i'm not sure... i'm trying to create several sets of permutations of nested lists
oy... that's reaching back too far for me sorry, I haven't done them in haskell in like 6 years
cool cool. and yeah I think it's non-obvious what for
is for, and it's a lot more powerful than you would expect
right. i was originally trying map
, but i would have needed several passes through the function to build up long one list per element in each nested list
not sure which doco you're looking at, but clojuredocs has a lot more examples https://clojuredocs.org/clojure.core/for
it’s pretty straightforward: each element of the list, even if it’s a list, is bound to the variable you name, and it’s substituted in the body as such
i tried building this up from simpler parts and was confused by this: (for [x '((1 4 3) (8 2 1) (1 0 4) (5 1 0)) v (range (count x))] v)
returning (0 1 2 0 1 2 0 1 2 0 1 2)
(for [x '((1 4 3) (8 2 1) (1 0 4) (5 1 0)) v (range (count x))] {:x x :v v})
=>
({:x (1 4 3), :v 0}
{:x (1 4 3), :v 1}
{:x (1 4 3), :v 2}
{:x (8 2 1), :v 0}
{:x (8 2 1), :v 1}
{:x (8 2 1), :v 2}
{:x (1 0 4), :v 0}
{:x (1 0 4), :v 1}
{:x (1 0 4), :v 2}
{:x (5 1 0), :v 0}
{:x (5 1 0), :v 1}
{:x (5 1 0), :v 2})
so in that simple case it seems to be counting the list of length 4 as 3 and then iterating through it four times
every time through x (that’s 4 times), v
is given, and v
is defined at the beginning to be: (range 4)
so it takes the two lists you bound to x and v, and combines their values in all possible permutations
rather, (range (count x))
where every time (count x)
is 3, since each element in x is 3 elements long
@joshjones then shouldn't it be (0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3)
?
honestly having the list bindings reference each other like that is super confusing. I didn't even know that worked
though it’s not a for
loop as in the for (int i = 0; i ....
sense, it still behaves the same way:
(for [x [a b]
y [c d]]
(* x y))
; yields [(* a c) (* a d) (* b c) (* b d)]
ok so... count will return the number of elements in each nested list, but then functions like first
and nth
still work as expected in the :let
part?
(for [x [1 2 3] y (range x)] x y) ==
for(x : [1 2 3]) {
for(y : range(x)) {
result.push(x,y);
}
}
:let
simply creates a binding for any particular value of (in above example) x
and y
on that “iteration"
perhaps what i want is to use a map
inside the :let
? so that way it will map the bindings through the sublists?
well my other thought was to use a closure and mutate the list...but then i'd need to create copies of it, which seems silly
thanks @joshjones!
@sophiago any for expression should have a direct translation into haskell do syntax for the list monad
it's GIGOing
my psuedocode translation
(for [x (first s)]
(for [v (drop 1 (range (+ (count s) 1))]
(let [y (if (not= (nth x v) 0)
(list (* (first x)
(nth x v))
(drop-last v (next x))
(- (nth x v) 1)
(nthnext x v)))]
(if (< v (count s))
(.add result y)
STOP
))
@wei no reason that I know of
maybe it will be an error when get
has a spec. ie does not match predicate associative?
or whatever
(associative? [])
=> true
(associative? {})
=> true
(associative? #{})
=> false
(associative? '())
=> false
well, it returns the value mapped to a key. associative says a thing has keys associated with its values. hence you can get values from a map using the key, and values from a vector using the index
@bfabry it seems if i call (nth s v)
then it's indexed on the entire list, but if i call (nth x v)
i get an error that i'm trying to index a scalar...but i'm not using two for
s in my version
no, you definitely don't, your code above is the equivalent to having two. I was trying to explain that multiple bindings in a for
is like nesting for loop's
ok, so this example: (for [x '((1 4 3) (8 2 1) (1 0 4) (5 1 0)) v (count x) :let [y (first x)] :while (< v (count x))] y)
if s looks like '((1 2 3)) then I would expect you to get that error, because (first s) returns '(1 2 3) and then x is bound to 1, then 2, then 3. except that it will error out on 1 because (nth 1 0) is nonsense
no, because you're trying to iterate over the result of (count x) which is just a number
(for [x '((1 4 3) (8 2 1) (1 0 4) (5 1 0)) v (count x) :let [y (first x)] :while (< v (count x))] y)
for(x : '((1 4 3) (8 2 1) (1 0 4) (5 1 0))) {
for(v : x.count()) {
y = x.first();
if (v < x.count())
result.add(y)
else
STOP
i'm not sure what language your pseudocode is supposed to approximate, but fwiw it's not one that really helps me
i guess i should clarify what :while
does? you're saying it defines what the :let
binding iterates over? i assumed it was the condition for the loop to stop...
(doseq [x '((1 4 3) (8 2 1) (1 0 4) (5 1 0))]
(doseq [v (count x)]
(let [y (first x)]
(if (< v (count x))
(.add result y)
STOP))))
ok, so if you put the range back where I think you're going to, it looks like
(doseq [x '((1 4 3) (8 2 1) (1 0 4) (5 1 0))]
(doseq [v (range (count x))]
(let [y (first x)]
(if (< v (count x))
(.add result y)
STOP))))
so you want 4 results?
(1 8 1 5)
?
why isn't it just (for [x '(...)] (first x))
?
(or (map first '(...))
for that matter)
ok, but then what if i actually want to be able to refer to the index of what it's iterating in my :let
binding? that's why i had the v part
map-index
might help?
to do what with it?
Sorry, map-indexed
. #n00bwarning
user=> (find-doc "map-index")
-------------------------
clojure.core/map-indexed
([f] [f coll])
Returns a lazy sequence consisting of the result of applying f to 0
and the first item of coll, followed by applying f to 1 and the second
item in coll, etc, until coll is exhausted. Thus function f should
accept 2 arguments, index and item. Returns a stateful transducer when
no collection is provided.
nil
so clearly i don't want that v binding there...but then how do i reference the index?
partial derivative with respect to x? so the third component stays the same?
each element in your top-level list is processed independently, right?
if so, this conversation would be easier if we write a function to do just one element, and then we can translate it back to a for
(defn deriv [s] (map deriv-of-one-thing s))
it looks like you also need the count
so you could (defn deriv [s] (let [c (count s)] (map #(deriv-of-one-thing c %) s)))
sorry I haven't been following the whole conversation closely
s
is a list
one element of s
your output in your example has only 2 elements
I guess I missed that since you said earlier you wanted a list of 4 things
map
doesn't work then
but apparently list comprehensions are actually worse than map in that they don't let you even refer to the index?
what do the three elements of ((4 3 3) (16 1 1) (5 0 0))
mean?
okay and the other half is w.r.t. y
?
and you want a function for just x/y exprs or for arbitrary number of variables?
okay; so if s
has lists of N elements, the output has N-1 elements in it?
the if
statement determines how many variables you're making partial derivatives of?
I'm just trying to figure out how many elements should be in the output list
Your example has two because there are two variables
If there are three variables it should have three?
I have to put my kids to bed. I'll be back in a bit.
While we take a pause from calculus, I have a potentially dumb question (I'm a n00b, so looking at the source didn't enlighten me) - does clojure.math.combinatorics/combinations
guarantee that the results will be returned in the same order as the input?
For example, (clojure.math.combinatorics/combinations [:a :b :c :d] 2)
produces ((:a :b) (:a :c) (:a :d) (:b :c) (:b :d) (:c :d))
, which is ordered as per the input (i.e. it pairs up :a
with the other elements first, then :b
, then :c
), but is that a guarantee or merely a coincidence?
That would be a question for @puzzler I think.
(he maintains that library)
I used vectors instead of lists because it made the code a bit easier
@deactivateduser10790 seems to hold true:
(let [position (fn [coll x] (.indexOf coll x))
LEN 2]
(tc/quick-check 200
(prop/for-all [v (gen/such-that #(<= LEN (count %)) (gen/vector-distinct gen/int))]
(every? #(apply < (map (partial position v) %))
(comb/combinations v 2)))))
;=> {:result true, :num-tests 200, :seed 1483667711921}
@adambros Cool! Yeah it seems to in the current version - I guess my question is more about whether that behaviour is guaranteed over time (i.e. in new versions). #paranoidn00b
you could leave that in your tests, and then it’ll then fail if that ever stops being true
@gfredericks i need lists though... i was just trying nested maps, but didn't get it quite right
What are "tests"? 😜
@sophiago what do you need lists for?
But thanks @adambros - that's helpful!
np, was fun to play with boot & test.check
I was only using vectors at the lowest expr level, so if you don't need laziness there then it would be fine
Just extra numbers I think
Easy to experiment
That's why I like vectors for this kind of work. No need for all that bookkeeping.
it's more you used laziness and i couldn't think of anything better than that clunky nth and nthnext
oh i was a little brusk there...i was considering using vectors earlier in case i could swap out parts of this code for the reducers library
the deal with this is i have a series composition function (which i also still need to expand to the multivariate case) and then i map these linear maps with that, in other words the chain rule
no, i think parallelism is out for anything meaningful now that i think about it. a little fuzzy by this hour tho...
I'm having trouble finding this on Google. Is there a nice Clojure DSL for generating Python code? I'm a big fan of the Tensorflow / Numpy libraries, but I really don't like Python as a language. Ideally, I'd write my math in a Clojure DSL, have it compile down to Python numpy/tensorflow -- and run that. Unfortunately, I can't seem to bind any libraries for generating Python from Clojure. Note: I don't have to compile all of Clojure. "Embedded Clojure DSL => Python" is perfectly fine. I just need something that outputs valid Python, along with all its whitespace indentation fun.
@sophiago glad you guys worked it out -- in general, ditch lists unless you need them for laziness. vectors are more idiomatic for data representation and have some advantages over lists
@joshjones yeah i go back and forth often because i do a lot of stream processing, which is the basis for this entire technique really, but oftentimes vectors are much easier to reason about
ideally i'd like to have both a lazy sequential version and a strict parallel version of this if possible, but not sure how to make the latter work. and at the moment i just need to focus on getting an implementation together rather than adding more features 😛
and thanks again @gfredericks! i'd love to know what you think of this library when i have to it together. seems like something you might be into? it's an interesting technique for computing partial differential equations i picked up from the haskell folks (although pretty sure the clojure version will be faster...) and i'm interested in how people will use it who have more domain knowledge than i do.
@qqq Is this what you're looking for? Not actually clojure, but close, and compiles to python. https://github.com/hylang/hy
@madstap: good try; but I 'm realyl hopping for clojure dsl -> py, so I can write things like:
(let
[a ...
b ...
c (+ (* a b) + 1)]) ...
and have it compile down to numpy/tesorflow matrix opsunfortunately, java API is experimental... when Google first announced TF they touted multiplataform support a lot, but apparently it feel thru the cracks
it is very multiplatform for: 1) evaluating tensorflow models 2) hardware you can run tensorflow with ... just not so much so with the languages you can train with
a noob question i posted this as a question on the plumatic/schema github page. any help would be much appreciated https://github.com/plumatic/schema/issues/378
@qqq the first announcement stressed that they wanted to support other languages. the Java API is mentioned on the official page, but we're 1 year in and it's still experimental
adoption was quick so it seems they settled on Python as good enough
@hcarvalhoaves i'm working on an automatic differentiation library/dsl rn!
@sophiago 🆒 I'm interested on this topic myself, lets chat in off
@deactivateduser10790 The ordering of the combinatorics functions such as combinations
are guaranteed to remain the same in the future (i.e., I wouldn't accept a patch that was faster but produced the combinations in a different order), BUT before you rely on order make sure you understand the special handling of inputs that have duplicates. When the input has duplicate items, they are grouped together in the order in which they are initially seen from left to right before proceeding with the algorithm, and the algorithm takes duplicates into account so the pattern will be different than if the items were distinct. So (combinations [:a :b :a :c :b] 2)
becomes (combinations [:a :a :b :b :c])
which yields ((:a :a) (:a :b) (:a :c) (:b :b) (:b :c))
.
when using cljs for spa on client, clj on server; what is a nice way to structure the app so that the server/client code lies in the same directory
so a typical app would have multiple parts, and I'd like, for each part, to have client/server grouped together
probably the recent NYC talk, a vimeo link
Thanks. I'm in the middle of it right now, and it does not really ring the bells, but maybe I need to finish it first :)
another spec talk by rich hickey - https://www.youtube.com/watch?v=oyLBGkS5ICk&t=325s
@dottedmag: pretty sure that was Stu Halloway's talk
@tbaldridge Yes! Thank you.
@dottedmag ah, then share a link! 🙂
My personal story: I liked Clojure as an idea, but lack of something like spec kept my internal angst saying again and again "you can't do any large systems in it". Then I stumbled upon this talk accidentally, which dissipated this anxiety.
A bit off topic. Anybody very familiar with ssl? I seem to be getting rst from the server. Is this normal?
question on specs: if you do lein test
do the instrumented functions get tested automatically?
@carocad no, only the ones that you put in deftests
@tbaldridge so you mean doing something like this:
(deftest foo (is (:result (:clojure.spec.test.check/ret (first (stest/check `hypobus.conjectures.core/hypothize))))
I found this online, has anybody tried it? http://stackoverflow.com/questions/40697841/howto-include-clojure-specd-functions-in-a-test-suite
hello guys, does anyone knows how can I check that one entry of my map is a fn
with specs => e.g:
(s/keys :req-un [::id ::fn])
I don’t want to check args of the fn or :ret but only if it’s a function
I can use`ifn?` but maps also implement it
well a map is a function, so why does it matter if it's a map or not?
you are right
it does not indeed
Repeating this question from yesterday: How do I get rid of a reflection warning in a gen-class when calling the superclass’s method which has been renamed locally by exposes-methods? Example: https://www.dropbox.com/s/59bkl4m9pvi8xni/Screenshot%202017-01-05%2022.44.38.png?dl=0 Should I just ignore it and trust there is no reflection when it’s executed, since I type hinted?
Nope, still: https://www.dropbox.com/s/qnflquzl12wjj83/Screenshot%202017-01-06%2018.18.50.png?dl=0
you are type hinting with the short name, which is same between the class you are defining, and the class you are extending
and you are importing the class you are extending, so likely the short name is refering to that class
which of course doesn't have the new method, so the compiler can't find it, so reflection
@hiredman It doesn’t work. Still says: method parentIsMyType can’t be resolved. Which is true, because there is no such method, it’s just the locally renamed method.
I hope that still works when I aot this… because isn’t there a bootstrapping problem here?
but that is the way the expose method stuff works, it isn'tsome magic locally renamed method
What would it do in cljs mode?
no but you can write a macro that detects the compiler env and emits the code as necessary
I'm using compojure. I already have a basic example like:
(defroutes app
(compojure.route/resources "/public")
(GET "/" [] (redirect "/public/index.html"))
(GET "/test" []
(response (str "This is updated")))
(GET "/api/qa/list-questions" []
(println "hit /api/qa/list-questions")
(response (str {:msg "hello world"})))
(POST "/api/qa/new-question" req
(println "POST /api/qa/new-question")
(println req))
(GET "/new/:name" [name] (write-db name))
(route/not-found "<h1>Page not found.</h1>"))
now, what I want to say is all GET requests on '/demos/*" goes to this other defroutes handler -- how do I say that?so instead of one "defroutes", I'd like "defroutes app" and "defroutes demos-app", and have all of "/demos" gets routed to demos-app routes [end question]
@qqq You would defroutes again in another part of code, and do all "/demos/" routes there
@captainlexington : can you point me at an working example? I feel like if there's something I could copy, this would make alot more sense.
(defroutes demo-routes
(GET "/demos/demo-1" [] (demo-1-call)))
And then
(defroutes app
(compojure.route/resources "/public")
demo-routes
(GET "/" [] (redirect "/public/index.html"))
@captainlexington : interesting. Would it be correct to say: "You can't nest routes; but you can concat routes" ?
Syntactically may not 100% correct, but that's essentially how it works
Yeah, that's basically it.
Also in usage it "feels" like nesting them. I'm pretty sure it can go arbitrarily deep
But there isn't any routing syntax for nesting them. It just happens automatically when you nest defroutes
Yes. There may be some way for defining sub-paths relative to some prefix, but a) I've never had occasion to use it, and b) that behavior would be independent of putting different routes
collections together
This is going to be a 1-2 knockout with captainlexington providing the concating routes and hireman providing relative paths
https://github.com/weavejester/compojure/blob/master/src/compojure/core.clj#L299-L313
So pretty!
compojure "routes" are ring handlers that return a response if they match and nil if they don't
@captainlexington @hiredman : I'm happy now. Anything else I should know before I jup back into coding?
(defroutes gae-app
(GET "/" [] (response "from gae demos"))
(GET "/test" []
(response (str "This is updated")))
(route/not-found "<h1>Demos: Page not found.</h1>"))
(defroutes app
(compojure.route/resources "/public")
(GET "/" [] (redirect "/public/index.html"))
(context "/gae/" []
g.apps.gae-s/gae-app)
(route/not-found "<h1>Page not found.</h1>"))
localhost:8080/gae/ <-- works fine
localhost:8080/gae/test <-- "Demos: page not found."
What am I doing wrong?FWIW I would also probably put the context
in gae-app
rather than wrapped around it in app
So you don't forget that it's there, and so gae-app
works as expected even if you have to reuse it
somewhere else in the code
Unhandled java.lang.NoSuchMethodError clojure.core.async$do_alts$fn__12286.<init>(Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V
let’s say they’re a java library foo 0.3.0
that I want to write a clojure wrapper for. Should I start my foo-clj
library at version 0.1.0
or try to mirror the java library version?
I have pros and cons of each method
don't mirror the java library version because you will end up having bug fixes of your own that will prompt a release
when foo 0.3.1
is updated, that would require me to release foo-clj 0.3.1
@jr that was exactly my biggest con
also consider that using your library should not require the user knowing that foo 0.3.1 is the exact dependency
@bostonaholic: why not use the Java lib?
we’re just writing a thin wrapper around it for convenience
and the java library makes use of internal classes when that could be hidden from the app itself
There are very few reasons to write Clojure wrappers, most of the time it's better to just use the java library itself
the benefit I see here is that a function in the java lib requires you send a Props
class as an argument. When really I should just as easily send a clojure map and let the wrapp instantiate a new Props
class
that’s just 1 benefit I see in this case
and remove the need for stateful (doto thing (.setFoo “foo”) (.setBar “bar”)))
etc.
But how many times are you going to make those Props classes? It might be better to just have a ns in your app that handles your app specific interfaces with that library.
sure, a ns in my app or a library that all of our other apps can use as well
A doto is much less to maintain compared to a library
Well many times when writing an app, I'd have this code in a data model layer or something of that nature.
Not sure what this is interfacing with, but I'd assume its some sort of DB/queue/service/etc.
3rd party service
analytics to be specific
Sure, so put the JVM code right in your business logic interface. That way you can still write it once, and yet not end up writing an abstraction that may not save you a ton of time
we’d have to write it multiple times for different apps
What you will find is that writing a wrapper library will get you into too many situations where you'll be thinking "Eh...do I need feature X or not".
Wrappers hide information and they create impudence miss-matches. You'll be tempted to not use a feature if you have to cut a new release of your lib every time you want to enable something the wrapper hides
that makes sense
atm there isn’t plans to add more features
just make it easier to use with clojure
So that's kindof my point...you'll have to maintain an interface with a backend...just make that backend the JVM code, don't make it another backend