Fork me on GitHub
#clojure
<
2015-07-01
>
goodwind8902:07:39

@alexmiller: Thanks for the reference. My confusion is to see when transducer would be useful. I managed to find some explanation on HN: https://news.ycombinator.com/item?id=9806755

seancorfield02:07:23

For us a transducer was a great fit for an operation that had a complex way of removing internal duplicates from a sequence and ended with a customized sort operation — that we also needed to combine with pagination of the result.

seancorfield02:07:37

the "collapsing" transducer could use a volatile internally for tracking duplicates, and it could easily be composed with the pagination logic (`drop` and take)

seancorfield02:07:20

It was much nicer than the accumulating reduce operation it replaced.

seancorfield02:07:05

Now if only java.jdbc result sets were reducible, it could be even faster simple_smile

seancorfield02:07:19

I joke because there’s a JIRA ticket open for exactly that.

goodwind8902:07:40

@seancorfield: wow definitely the stuff I'm drooling over

goodwind8902:07:53

currently to imitate the "collapsing" transducer functionality I have been writing some loop recur stuff, which does not seem as elegant

seancorfield02:07:43

Yeah, the big simplification and speed up for us with this case was that we could have a volatile inside the transducer and just vswap! values into it as we processed the data. Each step is clearly separated out. And it’s composable.

seancorfield02:07:50

We were like "so much win!"

arrdem02:07:56

692645c73c86d12c93a97c858dc6e8b0f4280a0b looks like Rich did have a "real" commit on 1.7

goodwind8902:07:29

@seancorfield: do you have the URL/keyword for the java.jdbc JIRA ticket?

goodwind8903:07:06

@seancorfield: I noticed that we can pass some function to the result set, :row-fn and :result-set-fn. Will this ticket affect that?

Alex Miller (Clojure team)03:07:05

arrdem: what does that mean?

arrdem03:07:46

@alexmiller someone on the mailing list observed that you didn't list rich in your contributors credits and I was mildly amused to find him when I read the log.

arrdem03:07:14

Just an idle observation while reading.

Alex Miller (Clojure team)03:07:03

well, he did all of the symbol and keyword re-work, all of the initial transducers work, and the printing changes, so plenty involved :)

Alex Miller (Clojure team)03:07:46

Rich has never been included on the list of patch contributors in previous release emails either afaik

seancorfield04:07:47

@goodwind89: I don't know yet what form the reducible version will look like but it will maintain backward compatibility. At least for a few versions :)

sveri07:07:59

Hi, what are people using to access H2 text columns? When using korma one gets back a java Reader object, which has to be parsed while the db is still in transaction, being a bit cumbersome. Is there an "easier" way, maybe using a different library or plain sql?

arrdem07:07:44

Well I just updated Grimoire with 1.7 docs... but they don't show up due to a version sorting issue. Neat. http://conj.io/store/v1/org.clojure/clojure

xhh08:07:38

@arrdem: it seems to still missing on the left sidebar

arrdem08:07:05

@xhh: yeah that's hand coded somewhere since I don't want to show all the snapshots and minor versions

arrdem08:07:23

just did a dataset redeploy not a whole site rebuild

arrdem08:07:34

will fix that tho, thanks

Pablo Fernandez09:07:22

I’m new to Clojure and I want to modify some libraries I’m using. Is this the correct procedure: cloning them from github, running lein install and then just using it normally in my project. Or should I do something different?

danielcompton09:07:26

@pupeno: depends on whether you want to share the changes with others. But that method should suffice for development

danielcompton09:07:54

Although be sure to bump the version to make sure you know which one you're using

Pablo Fernandez09:07:58

@danielcompton: yes, my plan is to send a pull request. What’s the procedure to go back to the mainstream version after that? Am I relaying on remembering to change version numbers?

danielcompton09:07:30

If you're just going to do a PR then you can let the library author update the versions

danielcompton09:07:56

But if you're waiting for changes you can do a non canonical fork to clojars

Pablo Fernandez09:07:06

@danielcompton: that’s not what I meant, I mean in my local system, how do I get rid of all my custom libraries and go back to the main ones?

danielcompton09:07:51

Go to ~/.m2/repositories and delete your ones. Maven will download anything it needs so you can delete it all

Pablo Fernandez09:07:58

In Ruby project, using Gemfile, I can point to a path, so I know I’m using the library from that path and when I’m doing developing that library I go back to pointing to a version which is the released library. I’m looking for a way to do that.

danielcompton09:07:39

If that was me I'd change the groupid on the project before lein installing

danielcompton09:07:50

So you can have a clear separation between the two

Pablo Fernandez09:07:22

How do you do that? change the groupid? should it be in project.clj?

Pablo Fernandez10:07:47

What's the function that given a sequence gives you another empty sequence of the same type?

danielcompton10:07:33

@pupeno: yep in the project.clj it's groupid/name

ragge10:07:46

@pupeno: empty, although it's really for collections and works on any collection

ragge10:07:33

@pupeno: any clojure collection that is

Pablo Fernandez11:07:30

Why does (flatten 1) return ‘() instead of ‘(1) or raising an error?

andrea.crotti11:07:27

the implementation is very simple

andrea.crotti11:07:28

[x] (filter (complement sequential?) (rest (tree-seq sequential? seq x))))

andrea.crotti11:07:57

it's because it uses tree-seq which will make leaves into sequences, and then filter only on the actual sequences

andrea.crotti11:07:39

I guess it's not very useful to do (flatten 1) but () I think it's correct, since there is nothing nested, so nothing to flatten

pesterhazy11:07:37

I agree with pupeno that it's surprising

Pablo Fernandez11:07:08

If you remove rest from the implementation, it returns ‘(1) instead of ‘().

Pablo Fernandez11:07:14

So it’s not due to the simplicity of the implementation as an even simpler version would do the other functionality.

Pablo Fernandez11:07:13

If I was implementing it, I’d make (flatten non-seq) return ‘(non-seq), non-seq or throw an error. Silently returning ‘() seems like something that might masquerade a bug.

Pablo Fernandez11:07:20

But maybe I’m missing something.

andrea.crotti11:07:30

I think (1) would be wrong, 1 is not a sequence so it has nothing to flatten

andrea.crotti11:07:53

assuming that flatten always returns a flattened list then () was the right answer for me

andrea.crotti11:07:59

but I didn't write that

pesterhazy11:07:05

yeath, flatten shouldn't turn a non-seq into a seq

pesterhazy11:07:07

but a pre-condition that x is seqable seems sensible

pesterhazy11:07:14

At the very least, the docstring should include that the result is undefined for nonseqable arguments

ordnungswidrig12:07:28

Anyone using timbre to log within wildfly/immutant? I experience that output from timbre is wrapped in another log format resulting in two timestamps etc.

zoldar13:07:32

after bumping clojure version from 1.6.0 to 1.7.0 in one of my projects I'm getting a following error when trying to launch repl session: Caused by: clojure.lang.ArityException: Wrong number of args (2) passed to: StringReader, compiling:(abnf.clj:186:28) - anybody experienced this?

ghadi13:07:34

zoldar: if compojure is in your deps, bump it to 1.3.4

ghadi13:07:28

(It's pulling in instaparse, which did naughty things with the reader in 1.6)

zoldar13:07:23

@ghadi: I explicitly depend on instaparse in my project

ghadi13:07:36

oh, then bump that

ghadi13:07:43

not sure what the version number is

ghadi13:07:59

looks like 1.4.1

zoldar13:07:47

@ghadi: that was it. thanks

Pablo Fernandez15:07:52

What’s the equivalent of (require ‘(foo.bar)) when declaring a namespace (that is, no alias).

escherize15:07:22

(:require [foo.bar :refer :all])

Lambda/Sierra15:07:00

@pupeno: I think you mean (require 'foo.bar)

Pablo Fernandez15:07:29

I meant (:require foo.bar)… it wasn’t working because of a typo somewhere else.

jballanc15:07:44

out of pure curiosity, does anyone know the reasoning behind why (comp …) works in reverse order with transducers relative to normal functions?

tcrayford15:07:46

@jballanc: because that's how math works

dnolen15:07:16

@jballanc: it only seems that way, if you understand how they work it becomes clearer it’s not really “backwards” but a result of how the transducer stack is built.

jballanc15:07:12

@dnolen: sure, under the covers I understand the mechanics, but it’s going to be difficult for beginners I should think...

dnolen15:07:16

@jballanc: people like to say this but I don’t see how

dnolen15:07:27

you could never use comp with the sequence operations before

dnolen15:07:27

like no examples exist of this anywhere at all

jballanc15:07:33

right, but how do you explain that the result of (sequence (comp (map #(+ 2 %)) (map #(* 3 %))) [1 2 3]) not match (map (comp #(+ 2 %) #(* 3 %)) [1 2 3])

nullptr15:07:00

i just remind myself “it’s like middleware” and that helps … ymmv

jballanc15:07:57

hmm…I guess maybe the better analogy is with the threading macros?

jballanc16:07:05

(sequence (comp (map #(+ 2 %)) (map #(* 3 %))) [1 2 3]) is more like (->> [1 2 3] (map #(+ 2 %)) (map #(* 3 %))) 😕

dnolen16:07:28

@jballanc: like I said those two examples do not seem related to me. you’re not composing multiple maps.

dnolen16:07:57

@jballanc: pick a less trivial example mix map and filter and take and it really falls apart

jballanc16:07:01

@dnolen: oh, sure…perhaps it’s my bias having worked with comp. I usually rewrite the forms in my head applying r-to-l

jballanc16:07:33

so the temptation is to mentally convert (sequence (comp (map #(+ 2 %)) (map #(* 3 %))) [1 2 3]) => (map #(+ 2 %) (map #(* 3 %) [1 2 3]))

jballanc16:07:16

wait…now I’m confusing myself 😛

dnolen16:07:45

@jballanc: switch to the example I suggested, map, filter, take, now what?

dnolen16:07:04

for your trivial example I’m not sure why I would ever write the former thing

dnolen16:07:35

(sequence (comp (map (comp #(+ 2 %) #(* 3 %)))) [1 2 3])

dnolen16:07:06

(sequence (map (comp #(+ 2 %) #(* 3 %))) [1 2 3])

jballanc16:07:06

(sequence (comp (filter even?) (map inc)) [1 2 3]) using r-to-l application for comp looks like it should be (filter even? (map inc [1 2 3])) but it’s actually more like (map inc (filter even? [1 2 3]))

dnolen16:07:35

what I wrote above is the sensible thing, doesn’t look different from your later thing now does it?

jballanc16:07:02

oh, I agree that comp’s ordering with transducers “makes more sense” on its own…my problem is that it’s subtly different than what you might expect working with comp on its own

jballanc16:07:16

(I feel like I need a whiteboard…)

dnolen16:07:24

right but I’m just pushing back about the claim about the confusion

dnolen16:07:32

no such confusing examples exist in reality

jballanc16:07:41

hmm…I guess

dnolen16:07:55

non-trivial examples cannot be translated anyway

dnolen16:07:32

so now we’re left only with the complaint - it’s unintuitive at first glance

dnolen16:07:36

but hey … programming!

jballanc16:07:05

honestly, I’m just happy to have transducers

jballanc16:07:29

…I guess if it were me I’d have just picked a different name than comp

jballanc16:07:26

for one thing, normally ((comp f g) x) is equivalent to (g (f x)), but that doesn’t work with transducers since changing the arity changes the behavior

jballanc16:07:43

i.e. you can’t turn (comp (map inc) (filter even?)) into #(filter even? (map inc %)) because now map and filter are no longer transducers

jballanc16:07:18

oh wait! I see now...

jballanc16:07:48

gah…mildly confusing, but it does work if you consider that transducers are nothing without sequence or eduction

jballanc16:07:44

i.e. (sequence (comp (map inc) (filter even?)) [1 2 3]) is actually equivalent to (sequence (filter even?) (sequence (map inc) [1 2 3]))

jballanc16:07:13

so sequence distributes over transducers in comp

jballanc16:07:31

I think I need more coffee...

dnolen16:07:42

I suspect transduce and into are more likely to be used than sequence or eduction.

ghadi16:07:57

into taking a transducer in the middle is the #1 sleeper feature of the release

jrychter16:07:03

Anybody upgraded to cider-0.9.1? I did and nothing works. No REPL, no eval, various interesting error messages.

pesterhazy16:07:55

jrychter: did you also update the corresponding nrepl middleware?

pesterhazy16:07:18

then I don't know simple_smile

jrychter16:07:37

I'm now looking through the cider changelogs, because I didn't expect major breaking changes moving from 0.8.2 to 0.9.1.

andrea.crotti16:07:48

@jrychter: there is a cider room as well

jrychter16:07:07

Oh, I didn't know that. Going there now.

rauh18:07:26

@jballanc: I always find it easiest to look at the definition of a transducer. For instance: map: https://github.com/clojure/clojure/blob/clojure-1.7.0/src/clj/clojure/core.clj#L2596

rauh18:07:49

the comp still does call the right transducer first, but 'calling' here means really "instatiating" the transducer with a reducing function

rauh18:07:37

Thus the left (first argument of comp) really gets the right (sec. argument) instantiated transducer as the rf (reducing function)

rauh18:07:15

then when a step is performed each transducer does it's own work first (look at the code of map) and then calls the reducing function (`rf`)

rauh18:07:13

So comp still does the same thing. It just happens so that the return value of the ((comp xf1 xf2) ...) is the function (transducer) of xf1 which then calls xf2

rauh18:07:25

(I hope I didn't mess up here, somebody correct me if I'm wrong)

Alex Miller (Clojure team)18:07:02

nope, I think you're right on it

ej18:07:09

Anyone used boot-datomic before¿

dergutemoritz21:07:14

@annapawlicka: The config component is's a bit of a cute trick, but I think it has some merits. For example, it's obvious from looking at the system declaration what components actually use it. I think you could consider it to be stateful, too -- after all, it has to be loaded from somewhere before any of the dependent components and it should be done only once. I guess it's a matter of taste whether to do that in an extra step before starting the system or whether to make it part of the system itself. Anyway, thanks for taking a look, let me know if I can clarify anything else simple_smile

noisesmith21:07:00

I totally create a config component

noisesmith21:07:14

this allows changing config cleanly (as part of a restart)

noisesmith21:07:25

otherwise changing config would be more tedious

dergutemoritz21:07:38

Yep, that's another nice side-effect (haha)

danielcompton23:07:48

Is *assert* ever set to false under any normal clojure runtime operation (e.g. running from uberjar, REPL, e.t.c.), or do I need to explicitly set it myself?