This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-06-07
Channels
- # admin-announcements (4)
- # beginners (63)
- # boot (67)
- # clara (29)
- # cljs-dev (38)
- # cljsjs (10)
- # clojars (7)
- # clojure (336)
- # clojure-belgium (3)
- # clojure-dev (22)
- # clojure-greece (30)
- # clojure-nl (1)
- # clojure-russia (9)
- # clojure-spain (3)
- # clojure-spec (169)
- # clojure-uk (12)
- # clojurescript (45)
- # clojurex (4)
- # core-matrix (3)
- # cursive (58)
- # datascript (3)
- # datomic (18)
- # events (38)
- # hoplon (228)
- # immutant (5)
- # lambdaisland (6)
- # leiningen (3)
- # luminus (8)
- # off-topic (11)
- # om (113)
- # om-next (2)
- # onyx (10)
- # parinfer (7)
- # planck (22)
- # re-frame (11)
- # reagent (25)
- # robots (7)
- # spacemacs (3)
- # specter (10)
- # yada (3)
how do I filter out from collection by given kv pairs? e.g. from:
({:id 1, :f “a”, :x “foo"} {:id 2, :f “a”, :x “bar"} {:id 3, :f “b”, :x “foo"} {:id 4, :f “c”, :x “bar"})
if given {:f “a”}
or {:f “a” :id 1}
should return the first el@ag use select-keys
and =
I found this mentioned about clojure keywords "They cannot contain '.' or name classes.". Does naming a class mean it cannot be used for a name of a class?
@nathanmarz: yeah, ended up using filter
=
vals
,`keys` and select-keys
… sorry, being lazy
(= ( reduce (fn [x y] (if (= (first (last (quote x))) y)
(conj (pop (quote x)) (conj (last (quote x)) y))
(conj (quote x) (list y)))) [1 1 2 1 1 1 3 3]) '((1 1) (2) (1 1 1) (3 3)))
oops, posted that too soon, anyway, I'm working through the 4clojure exercises and I'm having a hard time with the function I wrote for my reduce
it should read:
I’m guessing you don’t want all those quote
calls in there?
(= ( reduce (fn [x y] (if (= (first (last (quote x))) y)
(conj (pop (quote x)) (conj (last (quote x)) y))
(conj (quote x) (list y)))) [] [1 1 2 1 1 1 3 3]) '((1 1) (2) (1 1 1) (3 3)))
Howdy seancorfield! When I step through the if block manually, the function seems to work fine. The boolean test is true when I think it should be true and false when I think it should be false. And, on their own, each of the branches return what I would expect. But when I nest the if block in my function I get IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Symbol clojure.lang.RT.seqFrom (RT.java:528)
Well (quote x)
produces the symbol x
— it does not evaluate x
.
So those four quote
calls are almost certainly wrong.
And it sounds like this might be a better conversation for #C053AK3F9 so that other folk learning Clojure may benefit from this discussion?
Ok, that would explain why my manual input of a collection produced desirable results. Thanks seancorfield, I will head over to the beginner forum after reconsidering my use of quote.
Ha, I deleted every instance of quote and the tests passed; now to understand why. Thanks again seancorfield!
Happy to help! 4clojure is addictive.
give it a hug
lift it into a function
something like that maybe
and i want that behavior to not come with any assumptions about the structure of the program / it shouldn't make any assumptions in general about what that functionality depends on argument wise
[{... :name "default" :type "head" :health 100.0 :power -10.0 :weight 5.0 :ammo 15 :texture "player1.png" :update do-nothing} ...]
if you want to build compound transformations over entities, then maybe transducers would be a good fit
better than trying to monkey with ->
So the input to each "smart function" is the world (the vector of entities) and the output of each "smart function" is… also the world?
in the end if performance is an issue i'll have entities responsible for being a "middle man"
Let’s just see if I’m on the same page as you: you start with a vector of entities, for each entity in the vector, you apply its :update
function to the world to produce a new world, and you keep going though the original world’s entities until they’re all done, then you start again with the new world?
Well (:update entity)
singular since entities
is a vector 🙂
So my question is: what happens if you’re processing entity 4 of 20 and it removes entity 5 — do you still run entity 5’s :update
on the world so far (i.e., at the start of this update phase)?
at this point i know the overall picture of what i want, but don't care about details very much
Or, similarly, if entity 4 removes entities 0, 1, 2, 3, 4 — how do you know what is the next entity to run?
My sense is that you need to let every entity try to update the world in order, then start over with the end result of that...
In which case your update phase is just a reduce
...
(reduce (fn [world entity] ((:update entity) world)) entities entities)
there are alot of ways to do what i'm thinking of, but they each have subtle differences
So you start with entities
as your world, you walk through every entity (in the "original" world) and let it update the "current" world and when every entity has had its chance, you have a "new" world — and you run that process again.
The reduce
is accumulating the "effect" of running each entity’s :update
function.
Your accumulator is the whole world
.
Each entity
runs its :update
function on the (current) world
to produce a (new) world
.
The world
starts out as entities
.
Does this make it clearer? (let [world entities] (reduce (fn [w e] ((:update e) w)) world entities))
That’s what you said, yes?
Because the initial "world" is your vector of entities
var world = entities;
for ( var entity in entities) {
world = entity.update( world );
}
That’s what the reduce
is doing.
Sometimes the accumulator for reduce
is non-obvious.
the part that i got hung up on was thinking that if i didn't tell reduce what the "seed" should be it should assume that its the entire world
Cool. Glad that helped.
my programming buddies are telling me that designing anything with an expected n^2 performance complexity is a recipe for disaster
i tell them optimization is the root of all evil, but even as I say it I have second thoughts
making a number of worlds dynamically equal to the number of entities in the world...
i don't know if modern computers can even handle that for a modrate number of entities
At any point you’ll only have two worlds: the one that starts this update phase, and the current accumulated-so-far world.
i don't actually have to make copies of the worlds because clojure uses persistent data structures right?
reduce is O(n) so your update phase will be anything from O(n) to O(n^2) depending on what your :update
functions do...
And, yes, the hardest thing to shift when you learn FP is "forgetting" the state-mutating OOP mindset. Even loops are different.
@seancorfield: that's one of the reasons I thought Clojure was a good language to learn FP with (unlike Scala) as it makes it quite 'unnatural' to mutate state (and explicit when you do)
(defmacro catch-pg-key-error [[field details] & body]
`(~'catch org.postgresql.util.PSQLException e#
(let [sem# (.getServerErrorMessage e#)
det# (.getDetail sem#)
[_ field# _] (re-find #"Key \((.*)\)=\((.*)\) already exists." det#)
~field (or field# :no-field)
~details det#]
~@body)))
the idea is to use it like
(try
,,, ; some stuff that might cause a duplicate key error
(catch-pg-key-error [f d]
(println "field" f "caused" d)))
catch
isn't a special form, try
is. -- try
looks for sequences starting with catch
in its body without doing any macroexpansion
alright, thanks. That's good to know. I ended up just wrapping the stuff inside the catch
not really; many functions don't have names in that sense anyhow
if you're controlling where the functions come from, you can use #'select-keys
instead of select-keys
and can convert that to a string more easily (e.g. (subs (str v) 2)
)
There are some obvious Clojure idioms which map to various monads like maybe, list, etc. Is there an idiomatic way to express the sort of thing you would do with the State monad? I'd like to be able to write computations which thread through some state without explicitly passing and returning it from every function.
dave.dixon: what's the broader use case?
@dave.dixon: Something like pairing update-in
with comp
?
Threading a sequence of random numbers through various computations, like sampling from more complex distributions. Sometimes they take an unknown number from the sequence. Would like to make it repeatable for testing.
splittable random number generators!!!
⇑ use one of those and you don't need the state monad anymore
@dave.dixon: stylistically, the ->
and ->>
macros often fill the role of a State monad.
@stuartsierra: I think I need something which will let me bind to intermediate results, i.e. I need to thread the random sequence through all operations, but in some cases I need to pull out the result of some calculation in the middle and input it to other steps.
@stuartsierra: and it's nice when done in the monad, since the random sequence part is abstracted away, and samplers can be composed hierarchically without having to directly manage the state part.
with splittable RNGs you just have to pass the RNG down the stack, not back up
works much better with laziness and other tactics
@gfredericks: Yeah, that would be nice. Going to play around with it a bit and see how it shakes out.
@gfredericks: Could you point me toward any particularly good examples of this use-case? I assume they're floating around in test.check somewhere...
test.check probably doesn't have any pithy examples of :/
Seems like these should compose nicely, right? E.g. I can build a splittable generator of normally distributed numbers from a splittable uniform, and splitting the normals just means I make two new instances splitting the uniforms.
yeah I think that's right
just treat the RNG as an opaque object that you can split and have a function rng->normal
or rng->normals
(to return one normal or an infinite seq of them, whichever is more useful)
1.9.0-alpha5 https://groups.google.com/d/msg/clojure/D_s9Drua6D4/CTWk12cXDQAJ
I use "oops" for most of my passwords
this isn't logged is it?
totally not logged! Also, when's your birthday? Will send you a present
Hi, first timer on Slack here! My name is Devin and my mother's maiden name is Faulkner, my first pet's name was Gertrude, and my high school mascot was the Condor. Looking forward to getting to know all of you!
@gfredericks: Out of curiosity, why can't you split just by taking a number from one sequence and using as the seed for the new one? I assume there's some reason that breaks down.
my favorite new feature in clojure 1.9: boolean? predicate - hurray! 🙂 i’ve written that dopey function 200 times
yeah ditto
I wrote it 200 times while we were implementing spec alone
@gfredericks: Never mind, just realized that's a silly question, since the split sequences in that case would basically just be copies of each other, delayed.
@alexmiller: what's the rationale for including bytes?
and not i.e. longs?
?
my guess would be: byte arrays are way more common than long arrays, so while playing with an implementing spec, they needed a bytes? function so it got added, and a longs? function never came up
dave.dixon: that's a common question, and it's not guaranteed to be a terrible idea but you have to assume that the RNG was designed to be used that way
a splittable RNG is essentially an RNG that's explicitly designed for that use case
@hiredman yeah, that pretty much
but that doesn't preclude a possible future addition for other array types. I didn't actually participate in a lot of the decision process for this as I was on vacation last week so there may be other reasons too, not sure.
btw as much as I'm loving all the new features coming in 1.9, I'm probably going to hate forever s/def
, IMHO s/spec!
would be a much better name
Hey guys I am using version 0.11.0 of Specter. Everytime I try to run my tests with midje 1.8.3 I get an error message: java.lang.RuntimeException: No such var: specter/transform. However, I do not get this error when I am running my code in ring. Anybody run into this before?
@john.carnell: what namespace is "specter" referring to there?
specter/transform
that's not a namespace
is it com.rpl.specter or com.rpl.specter.macros?
sorry. Gotcha
hold on one moment
[com.rpl.specter :refer :all]
Thats what we have been using to import in all of our namespaces using specter
all the select/transform/etc. operation got changed to macros and moved to the com.rpl.specter.macros namespace in 0.11.0
So I should use: com.rpl.specter.macros
I'm surprised any of your code would be working without making the appropriate updates
you need both
com.rpl.specter contains the function versions of those operations as well as all the navigators
Cool. So I should require both namespaces while working.
Cool. Let me give me a shot. BTW: Love this library. I showed it to my team this morning and it has been spreading like wildfire 🙂
@nathanmarz: can't remember if I already asked you this but -- it would be a bit of an abuse of the feature, but couldn't you make those functions :inline
and have the macro and the function version in the same var rather than making them macros in a separate namespace?
well the separate namespace thing is for clojurescript
i've never used :inline
how does it work exactly?
user=> (defn foo {:inline (fn [& args] `(inc 1))} [& args] 3)
#'user/foo
user=> (foo (println "FOO"))
2
user=> (apply foo [(println "FOO")])
FOO
3
direct calls of foo will be routed through the inline version, HOF ones to the fn version
wow, cool
how is this related to definline
?
I'll look into it, thanks
@nathanmarz: keep in mind that this is a somewhat internal feature, don't know if it's documented anywhere
@nathanmarz I am still getting the same error when I run my tests. Here is my (ns declaration) . Am I doing this correctly?
(ns edge-provisioning.handlers.v2.get-edges-state (:require [compojure.api.sweet :refer :all] [compojure.core :excludes [defroutes]] [inin-clojure.logging :as log] [edge-provisioning.provisioners.provisioners :as provisioners] [edge-provisioning.utils.constants :refer :all] [edge-provisioning.utils.general :as general] [edge-provisioning.utils.constants :refer :all] [edge-provisioning.utils.properties :as properties] [com.rpl.specter :refer :all] [com.rpl.specter.macros :refer :all]) (:use [slingshot.slingshot :only [throw+ try+]]))
We are only have the java.lang.RuntimeException: No such var: specter/transform error when we run our midge-based tests
@john.carnell: this is clojure right, not clojurescript?
Correct
Clojure
No we are not even writing tests yet for the code.
We were just playing with it and hitting an endpoint
I found this while trying to research the issue: https://github.com/nathanmarz/specter/issues/112
oh i know
midge is using specter
and you're overriding the dependency
it's using the old API where transform was in com.rpl.specter namespace
midge needs to be updated to work with 0.11.0
updating is really easy, just requires namespace changes
or if it's also defining its own navigators, some straightforward name changes
Ok. Ill see if they made the change, I will see if I can do a PR
it looks like the dependency is through the structural-typing library https://github.com/marick/structural-typing/blob/master/project.clj#L22
is there a way to dynamically generate the bindings vector for the
for
special form, outside of wrapping the whole thing in a macro?"dynamic" is also not the word you want here, you want "at runtime" or "at compile time" or "at macro expand time"
I'm admittedly trying to be clever out of laziness, but it feels like I am missing something nonetheless. I'm trying to get the exact behaviour of "for" but the number of bindings isn't known until the function is exected.
clojure's lexical environment is fixed at compiled time, if you want to do something like that at runtime, you want a map
so one reason you may want some kind of runtime associative structure is the name and the value come in as an argument that get passed on to something else
user=> (for [{:keys [name value]} [{:name "a" :value 1}]] {name value})
({"a" 1})
user=>
So how would this apply to a case where I want the behavior of:
(for [x [1 2 3] y [4 5 6]] [x y])
or: (for [x [1 2 3] y [3 6 7] z [0 9 6]] [x y z])
But I don't know until runtime how many arrays will need to be "for"ed over?
The maps code you posted looks like I'm just destructuring something I already know the format of.well, not entirely, of course, because for is a cartisian product, but something like that
you can also do what I usually call a recursive for, which comes are fairly often (for me)
something like (fn this-fn [some-stuff] (for [a some-stuff i (this-fn some-stuff)] i))
Just found this online, looks like exactly what you were saying:
(defn cart [colls]
(if (empty? colls)
'(())
(for [x (first colls)
more (cart (rest colls))]
(cons x more))))
Do you know of a book that goes over patterns like that? or is it just something that comes with time?
I think the best way to think about for
is in is the SELECT statement for clojure data
but that only helps if you are kind of familiar with subselects that kind of weirder sql stuff
http://programming-puzzler.blogspot.com/2013/03/logic-programming-is-overrated.html is nice example of a complicated for
a transducer is a function that takes a stepping function and returns a stepping function
what do you want to do?
so given a transducer is a function from stepping function to stepping function, where does folding fit in to that?
reduce will take collection and "divide and conquer" on it. It will split up the collection into subcollections and apply reduce to each part.
oh, you mean like fold as in clojure.core.reducers?
in so much as fold can take a step function, you can use transducers to produce that step function
there is no parallel transducible process (yet)
partitions in fold are reduced so you can use transducers on each partition of a fold
there are some examples of that floating around
its not like my life depends on it, so I guess the most pragmatic thing would be to wait for it to enter the standard (you said "yet")
a transducer is a function that takes a step function and returns a step function, so you can use transducers to build such functions and use them anywhere such a function can be used
it's something we've talked about and I know Rich has ideas about it
not currently something we're working on for 1.9
i'm wondering if spec could be used to make guarantees on data about associativity and commutativity
that's an interesting idea
I don't think we would (for performance reasons)
but it's interesting :)
oh well, i have to say clojure is light years ahead of anything i've seen in any other language
personally, I'd put a higher priority on primitive support in transducers than fold - that's much harder to do outside the core than fold (see Tesser for example)
i guess you wouldn't really have to use "spec" to assure commutativity, you could just offer a protocol that ensures that the order of the arguments for an operator are arbitrary
another way to say "commutative function" is to say "the arguments of the function are a set, not a vector"
i guess you could do it with a macro like (associative (...) (...) (...) (...) (...))
normally functions like map and filter and such will return a transducer if you don't supply a collection
what you want in that case is to say something about the associativity of the transducers you have
i think adding support to clojure for SETS of arguments, rather than just ordered sets (vectors) of arguments, would enable a quick and idiomatic solution to the problem of representing associativity and commutativity for a variety of applications, like "folding" transducers and such