Fork me on GitHub
#beginners
<
2015-07-29
>
chris02:07:50

is midje the best way to run tests? I’ve only ever used clojure.test

surreal.analysis02:07:22

@chris: I like Speclj, as their autorunner is great

surreal.analysis02:07:35

But in general I think clojure.test, midje, and speclj are the main choices

chris02:07:14

ok, thanks

upgradingdave14:07:18

Hi all, I'm struggling with this ... I'd like to take a tree-like structure like this: {"foo" {"bar" "1" "baz" "2"}} and recursively traverse while remembering the path from the root in order to produce something like this: ["foo/bar/1", "foo/baz/2"]. Any suggestions?

upgradingdave14:07:41

I've played around with clojure.walk but I get stuck because not able to keep track of where I am in the tree, maybe there's a way to do clojure.walk and maintain some context?

colin.yates14:07:29

you should look at clojure zippers

colin.yates14:07:27

@upgradingdave: this might help http://josf.info/blog/2014/03/21/getting-acquainted-with-clojure-zippers/ Be aware that you will have to provide an fn when you create the zipper so it can recognise a node. map? might be sufficient based on your example.

upgradingdave14:07:19

@colin.yates: I came across zippers and they look really interesting, looking forward to digging deeper, thx for the link 😉

curtosis14:07:35

if I want to remove from a map, is there a more idiomatic way than (into {} (remove (fn [[k v]] (predicate? k)) coll)?

roberto14:07:10

@curtosis: dissoc

curtosis14:07:49

dissoc takes a key, not a predicate

curtosis14:07:53

I want to remove entries from the map where some predicate is true.

roberto14:07:11

(dissoc my-map (fn-that-returns-keys-based-on-predicate my-map)) ??

roberto14:07:57

I don’t know which one is more idiomatic, but at first glance, I would know what dissoc is doing to a map. While the other snippet requires a little bit more effort.

curtosis15:07:32

I suppose... so that would look like: (apply dissoc m (mapv predicate? m))?

curtosis15:07:11

(where predicate takes [[k v]])

curtosis15:07:04

it's certainly fewer characters. simple_smile

roberto15:07:11

yeah, or

(->> m
   (mapv predicate?)
    dissoc)

roberto15:07:26

haven’t tried that last one tho, just theorizing

curtosis15:07:49

dissoc needs the apply to flatten the keys, but yeah

curtosis15:07:53

I do like that, as you point out, dissoc is clear as to what is really happening. remove creates (at least notionally; not sure about actually) a list of vectors that then go into a map again.

curtosis15:07:37

I mean "actually" as in the context of a lazy seq being fed to into.

curtosis15:07:16

oh, whoops... it needs to be filterv, not mapv.

curtosis15:07:03

strike that... it's actually a reduce, I think. once more, with feeling!

curtosis15:07:14

which, on 1.7, means I can probably collapse the whole thing down into a reduce-kv.

roberto15:07:34

didn’t know about reduce-kv, that is really handy.

curtosis15:07:50

neither did I until today simple_smile

curtosis15:07:50

I haven't seen a lot of letfns in the wild... is that because they're not common, or I'm not looking at the right code?

curtosis15:07:52

^ long-time Lisper, used to liberally using flet and macrolet...

potetm15:07:40

@curtosis: I think the general consensus is that you only use it when you need to let a recursive function. No reason in particular as far as I can tell. Just the way it’s come about for idiomatic clojure.

pataprogramming15:07:49

Lisp-1 vs. Lisp-2 is probably a contributing factor.

curtosis15:07:36

Interesting. I tend to use it for fns I use in map etc. calls... instead of, say, (fn [x] (contains? s (:id x)) I'll close over s and give it a name. Especially when it's more than a line or two.

potetm15:07:47

You can’t do that with just a let? Or you don’t prefer it?

curtosis15:07:23

ah, that would get to @pataprogramming 's point. I never thought of doing it in a let. 😉

curtosis16:07:42

I could go either way on it, then.... letfn communicates intent better, but is essentially noise (= additional enclosing form)

potetm16:07:00

Right. Early on I certainly preferred letfn because I find it more explicit. After working in a clojure codebase for a couple of years, I’ve reverted to let simply because it’s more idiomatic.

curtosis16:07:27

cursive also annoyingly indents to the args under letfn and I haven't found the setting to fix it. This may be dispositive. simple_smile

curtosis16:07:01

(IIRC emacs does the same with ootb clojure-mode)

potetm16:07:01

Yeah, I always ended up putting the fn args on their own line for that reason IIRC.

curtosis16:07:37

which I can't help but hear as "f'n args" 😛

pataprogramming16:07:00

Naming inline (fn foo? [x] ...) can be helpful, both for intent and stacktraces. Doesn't help with longer functions, though.

pataprogramming16:07:48

That is, it doesn't help make the code read more cleanly for multi-line lambdas, which are still messy.

roberto16:07:36

I’m ocd about having small functions, that is why I don’t use letfn. I’m a total newbie and still finding my way, so maybe I need to get over my obsession with small functions.

curtosis16:07:55

ISTR something recently about why there's not-any? but not any?... ring a bell? do I just use (complement not-any?) ?

potetm16:07:13

@roberto: It’s actually really interesting that my clojure fns tend to be much longer than, say, my java methods. I was obsessive in java about making my methods just a few lines. But in clojure, I routinely (map … (filter … (map … coll))) without a second thought.

potetm16:07:20

@curtosis: some?

curtosis16:07:32

some isn't a predicate

curtosis16:07:58

I mean, I guess it still returns a truthy/nontruthy value

potetm16:07:02

then some?

potetm16:07:36

But I’m a little confused. Maybe an example would help.

curtosis16:07:38

some? is just a test for not-nil

potetm16:07:34

not-any is just an alias for (comp not some)

potetm16:07:48

So… some is the “inverse"

pataprogramming16:07:52

Truthiness punning is idiomatic for most predicates. There's nothing sensible to return for not-any?, but there is for some. The naming is not the best, I'd agree.

curtosis16:07:32

what I want is (remove #(any? my-pred? (:ids %)) coll)

curtosis16:07:56

but yeah, nil punning should work there, I think

potetm16:07:54

(remove
  (comp
    (partial some my-pred?)
    :ids)
  coll)

pataprogramming16:07:37

As long as you aren't trying to remove logically false values, which is what I vaguely recall was an argument for the existence of any?.

curtosis16:07:43

no, I need to apply my-pred?.

potetm16:07:36

As in, you need to use apply? The above removes all items from coll that have at least one :ids matching my-pred?.

potetm16:07:50

I believe.

curtosis16:07:44

sorry, bad choice of word. simple_smile I want to remove all items from coll that have at least one element in :ids for which my-pred? is true.

potetm16:07:19

Right. I think the above does it. Have you tested the output?

curtosis16:07:32

not yet. I've got a different logic bug I'm puzzling through. I'm translating some Scala code that is a (groupBy (filterNot (groupBy (exists (forall (contains s x))))))

curtosis16:07:39

to horribly abuse notation

potetm16:07:36

Well, feel free to holler if you get stuck simple_smile Let me know if the above works for you when you get around to it.

curtosis17:07:56

kind of ugly, but (IMO) easier to read than the Scala original.

potetm18:07:08

Yeah, sometime data manipulation is just complicated.

potetm18:07:14

s/sometime/sometimes/