#clojure log - Jul 16 2014

The Joy of Clojure
Main Clojure site
Google Group
List of all logged dates

0:31 numberten: is there a good way of lazily reducing?

0:31 trying to read a big file lazily and read values from it and store them in a vector via 'reduce'

0:33 (with-open [rdr (clojure.java.io/reader "file")] (reduce #(conj % %2) [] (line-seq rdr)))

0:33 something like that

0:34 tbaldridge: how would you lazily store something?

0:34 jeremyheiler: numberten: i'm not sure what you mean by lazy reduce.

0:36 numberten: maybe that was the wrong wording

0:37 I think something about that is holding onto the head of the seq?

0:38 because the heap runs out of space

0:38 but I've been able to make vectors of that size before

0:39 jeremyheiler: how big is your file?

0:40 tomjack: try (reduce (constantly nil) ...) to test?

0:40 numberten: 91M

0:42 constantly nil returns nil. what does that test?

0:42 tomjack: I don't think it holds the head

0:42 numberten: hrm

0:44 tomjack: I guess it may be a chunked seq, but surely as long as you can fit every chunk of 32 lines, the reduce with (constantly nil) should work (I'd think)

0:44 jeremyheiler: does slurp cause the same problem?

0:47 numberten: yeah it does

0:47 * tbaldridge cues mythbusters quote

0:47 tbaldridge: "Well there's your problem...."

0:49 technomancy: http://twitterthecomic.tumblr.com/post/40956811679/ah-heres-your-problem-pulls-out-random-part

1:29 danielcompton: What would be the way to turn {:a {:b :makes :c :takes} :b {:c :takes} :c {:a :makes}} into {:a [:b :c] :b [:c] :c [:a]}?

1:30 i.e. get just the keys from a nested map

1:30 jeremyheiler: (update-in m [:a] keys) ?

1:31 so.. (-> m (update-in [:a] keys) (update-in [:b] keys) ...)

1:31 danielcompton: There could be an arbitrary number of keys

1:32 With arbitrary names

1:32 TEttinger: danielcompton, there is almost certainly a way

1:33 jeremyheiler: so, (map #(update-in m [%] keys) (keys m)) ?

1:33 danielcompton: TEttinger: It seems like one of those Clojure things that will be a blindingly obvious one liner

1:34 jeremyheiler: oops.

1:34 danielcompton: jeremyheiler: ?

1:34 jeremyheiler: reduce, not map

1:34 something liek that

1:34 do you see where i'm going tho?

1:35 danielcompton: jeremyheiler: Sort of...

1:36 jeremyheiler: you know the keys because you can inspect the map

1:36 TEttinger: ,(let [nest {:a {:b :makes :c :takes} :b {:c :takes} :c {:a :makes}}] (reduce #(conj %1 [(key %2) (keys (val %2))]) {} nest))

1:37 clojurebot: {:a (:c :b), :b (:c), :c (:a)}

1:37 TEttinger: yep, one-liner

1:37 jeremyheiler: https://gist.github.com/jeremyheiler/899dd9419d5a4ba4671f

1:39 ,(let [m {:a {:b 2 :c 3} :b {:d 4 :e 5} :c {:f 6}}]

1:39 (reduce (fn [m k] (update-in m [k] keys)) m (keys m)))

1:39 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

1:39 jeremyheiler: ugh.

1:40 ,(let [m {:a {:b 2 :c 3} :b {:d 4 :e 5} :c {:f 6}}] (reduce (fn [m k] (update-in m [k] keys)) m (keys m)))

1:40 clojurebot: {:c (:f), :b (:e :d), :a (:c :b)}

1:40 danielcompton: (defn super-keys [m]

1:40 (zipmap (keys m) (map #(vec (keys %)) (vals m))))

1:42 jeremyheiler: thanks!

1:43 jeremyheiler: np

1:58 amalloy: i like (into {} (for [[k v] m] [k (keys v)])), because i always like for-comprehension solutions

2:20 * isaac``

3:20 magopian: is there a functional database (like datomic) that is opensource and nice to use?

3:20 (that I can use with clojure ;)

3:28 whodidthis: no ;_;

3:57 hhenkel: Good morning all!

3:58 In the past I used cheshire to parse and generate json data. Now I'm working with a third party client who gives me json data.

3:58 magopian: whodidthis: ah, too bad :'( i'm not comfortable using something that isn't opensource

3:58 hhenkel: I fail to cast it into some clojure datatype with this error: java.lang.ClassCastException: org.json.simple.JSONObject cannot be cast to java.lang.String

3:59 What is the way to go? Is it possible to use cheshire here or do I need to use org.json.simple ?

4:01 ivan: if you wanted to read some xattrs, would you prefer listxattr + llistxattr (does not follow symlinks) matching the POSIX APIs, or an opts map {:follow-symlinks true}, or a (into-array [LinkOption/NOFOLLOW_LINKS]) to match NIO?

4:03 hhenkel: Okay, nevermind I looked at the javadoc of simplejson and found "toJSONString"

4:13 nobodyzzz: magopian, there are a lot of db you can use with clojure, but none of them seems to be "functional" :)

4:18 vijaykiran: magopian: the free/starter version works fine - if *free* is the requirement

4:30 magopian: nobodyzzz: haha ;)

4:31 vijaykiran: nope, free is not the only requirement ;)

4:31 well, it's not a requirement, just... not comfortable

4:36 ivan: are there any Java APIs for opening/writing/listing filenames that are not valid UTF-8? (while staying in the UTF-8 locale)

4:44 wagjo: ivan: most flexible is to use filechannel with java.nio.charset

4:47 ivan: wagjo: does that help with invalid filenames, though?

4:47 skimming the APIs it looks like it's for file contents?

4:48 wagjo: ivan: yeah, its just for fole contents, for file names, look in java.nio.file.Paths

4:59 ivan: see http://stackoverflow.com/questions/22775758/java-io-file-accessing-files-with-invalid-filename-encodings

5:00 ivan: wagjo: do any of those solve the problem, though?

5:00 I probably don't want to take the Java process out of the UTF-8 locale to read some weird files

5:02 * kerneis remembers Linus' rant about filename as opaque identifiers

5:06 vyorkin: hi everyone! i've just started to learn clojure & now i'm trying to solve some simple problems to practice & become comfortable with it, for example http://pastebin.com/Q53Ctf91 could you give me some code review?

5:07 to merge the resulting hashes i've used deep-merge-with from deprecated clojure.contrib.map-utils, i think that it could be done better=simplier

5:08 wagjo: ivan: if you set file.encoding to some non-0unicode one-byte charset, it will read any filename. However you will get garbled filenames if they were utf8.

5:09 ivan: wagjo: yeah, I think I either have to do that, or live with the limitations, or rewrite this in Rust ;)

5:09 thanks

5:09 wagjo: ivan: another thing is to not use old java.io when encoding is changes, as e.g. FileReader uses this property. Use java.nio where you can set any charset you like for file contents

5:10 ivan: thing is that you cannot get filename as a byte array, only as a string, so this is the only workaroud I'm aware of

5:13 ivan: wagjo: yeah the -Dfile.encoding=iso-8859-1 workaround is no fun because it screws up a lot of things

5:13 e.g. "hello \uCCCC" -> "hello ?" in my REPL

5:39 kerneis: vyorkin: it could be much simpler

5:41 also, are you sure your identifiers are restricted to a single letter?

5:47 vyorkin: kerneis: good to see you!

5:48 AeroNotix: is there something like filter / remove but returns the collection of items that are truthy as per predicate function?

5:48 vyorkin: kerneis: can you point me in the right direction? maybe some reading

5:48 hyPiRion: AeroNotix: keep?

5:48 AeroNotix: hyPiRion: /me looks

5:48 That does it!

5:48 :)

5:48 hyPiRion: ,(keep {:a 1 :b 2} [:b :c :a])

5:48 AeroNotix: cheers

5:48 clojurebot: (2 1)

5:48 hyPiRion: sweet

5:49 vyorkin: kernies: i've just started to read The joy of clojure

5:51 kerneis: vyorkin: have you looked at update-in and tried to re-write transform to use it as I suggested yesterday?

5:51 you could really get rid of deep-merge-with and do all the work in reduce transform {}, provided you use update-in in transform

5:52 vyorkin: kerneis: yep, i understand how update-in, but i really couldn't come up with anything

5:52 kerneis: i've tried to think about smth like (reduce (update-in ..)) as you've suggested yesterday

5:52 kerneis: but had no luck with it(

5:53 kerneis: don't know what to do with things like { :a { :b [1] } } { :a { :b [2] } }

5:53 kerneis: to get { :a { :b [1 2] } }

5:54 Glenjamin: have you tried starting with a direct port of the rails logic?

5:55 nobodyzzz: vyorkin, maybe try to take a look at ring.util.codec/form-decode

5:56 vyorkin: Glemjamin: i think thats not fair (: i wanted to do it by myself, this solution works but code looks really ugly imho

5:56 i mean my solution is ugly & too verbose

5:59 ivan: wagjo: -Dfile.encoding= was for file contents, -Dsun.jnu.encoding=iso-8859-1 lets me read invalid UTF-8

6:01 nobodyzzz: ,(merge-with (partial merge-with concat) { :a { :b [1] } } { :a { :b [2] }})

6:01 clojurebot: {:a {:b (1 2)}}

6:06 vyorkin: nobodyzz: looks great, trying to understand it

6:06 kerneis: vyorkin: the key insight is that you need to treat your chain differently when the last element is "[]"

6:06 so, in (nesting-chain), remove the "reverse"

6:06 (it is more confusing than anything else)

6:07 also remove that last (apply deep-merge-with)

6:08 and now, rewrite transform from scratch

6:08 so it will still be (defn- transform [acc [chain value]]

6:08 but now, you have two cases:

6:08 first case: (= (last chain) "[]")

6:08 second case: everything else

6:09 in the first case, the "real" chain is everything execpt this "[]" (ie. drop-last chain)

6:10 and you need to use update-in with some concat magic, as nobodyzzz suggested above

6:10 in the second case, you use update-in again, this time with the whole chain

6:10 or maybe just assoc-in in fact

6:10 use an if to glue both cases together, done!

6:12 vyorkin: kerneis: thank you!

6:13 kerneis: now i need some time to think (:

6:18 kerneis: vyorkin: I'll be away but if you still cannot solve it with those hints, the solution I just outlined is here http://pastebin.com/2enmLUSb (but try to look at it only when you have one by yourself!)

6:19 razi: vyorkin: I found Programming Clojure far more enjoyable than Joy of Clojure, if it helps. :)

6:20 http://www.braveclojure.com/ is awesome as well, and http://aphyr.com/

6:23 kerneis: what, 106 views in 5 minutes? My little snippet does not deserve so much attention :-$

6:41 ivan: kerneis: I think there are a lot of bots spidering pastebin to steal credentials

6:41 vyorkin: kerneis: looks awesome

6:42 * vyorkin now needs a next problem to solve

6:45 vyorkin: maybe someone can also suggest some set of problems to practice? something close to real life cases

6:53 nobodyzzz: http://www.4clojure.com/ but problems there not really close to real life cases =)

6:53 nbeloglazov: vyorkin: how real life? I always wanted to have some kind of web service which runs kibit (https://github.com/jonase/kibit) checks on arbitrary github clojure repo and presents a summary. Is it real life enough?

7:11 vyorkin: nbeloglazov: thats interesting!

7:15 nbeloglazov: ok, maybe i'll try to buld such a tool, that'll be a really good practice (:

7:16 nbeloglazov: vyorkin: yeah, it would require working with GitHub API and probably clojure AST, so should be quite fun

7:19 nobodyzzz: https://github.com/Raynes/tentacles hehe, funny name

7:59 gfredericks: how do you debug a situation where defn returns #'user/foo and you can call that var just fine but (resolve 'user/foo) returns nil?

8:00 answer: it was a typo of course

8:00 i.e., defn returned #'user/ofo and (resolve 'user/foo) returned nil to nobody's surprise

8:52 hhenkel: Hi I'm stuck currently. Can someone please explain to me why "(doseq [server server-config] (pprint server))" executes the pprint and why the same thing with for is doing nothing?

8:52 CookedGr1phon: hhenkel: because for is lazily evaluated to produce a list

8:53 whereas doseq doesn't produce a value, it simply goes through performing side effects

8:54 hhenkel: CookedGr1phon: okay, so if I execute something within a for the execution happens when I try to get data from it, right?

8:54 CookedGr1phon: right

8:55 hhenkel: So as long as I don't do anything with the returned data I won't see any trace output for example?

8:55 CookedGr1phon: exactly

8:55 hhenkel: CookedGr1phon: Okay, then it makes somehow sense... ;)

8:55 CookedGr1phon: Thanks! I guess I was to long siting in front of the code....

9:47 nbeloglazov: hhenkel: be aware though, that 'for' is not completely lazy, it will "calculate" elements in batches by 32 elements. So when you try to access first element you'll see 32 (pprint server) in repl.

9:48 gfredericks: that's not for doing that

9:48 for is just as lazy as anything else

9:49 that's how chunked seqs behave

9:50 ,(second (for [x (take 10 (iterate inc 0))] (print x)))

9:50 clojurebot: 01

9:50 gfredericks: ,(second (for [x (range 10)] (print x)))

9:50 clojurebot: 0123456789

9:50 ucb: I get a warning about clojure-test-mode being deprecated and having to switch to cider-0.7+

9:51 how does cider replace clojure-test-mode?

9:51 or at least, where can I read about this replacement?

9:55 ssideris: ucb: the functionality has been integrated into cider

9:55 ucb: same default key bindings

9:55 ucb: yeah, now reading https://github.com/clojure-emacs/clojure-mode/issues/214

9:55 thanks!

9:56 ssutch_: what does #{:blah} construct, the repl just prints it back out at me and it's a tough one to google

9:57 boxed: #{} is a set, {} is a map

9:57 Glenjamin: it's a set

9:57 ssutch_: aye, thank you

9:57 boxed: ,(type #{:blah})

9:57 clojurebot: clojure.lang.PersistentHashSet

9:57 boxed: <3 clojurebot

9:59 TimMc: ssutch_: You'll want to look through this: http://clojure.org/reader

9:59 ssutch_: ah i did not know the "type" function

10:00 thanks TimMc ill give it a refresher (coming back to clojure after ~2yr)

10:00 Glenjamin: so, when discussing simple made easy with someone just now he gave a very good counterexample

10:01 his claim was that esperanto is simple, but it's foreign so therefore not easy.

10:01 so should we all learn esperanto?

10:02 i didn't really have a good answer, i guess practicality is the third axis?

10:07 ssideris: Glenjamin: I think the whole argument about simplicity is that it's more desirable than ease

10:07 simple!=easy

10:07 but it's worth the extra effort

10:07 Glenjamin: which would imply we should learn esperanto :)

10:08 ssideris: that's my understanding

10:08 :-)

10:10 Glenjamin: Ok, ebligas fari tion

10:11 gfredericks: you're outside the domain of engineering at that point though

10:11 so there's different dynamics and different scales of concern

10:16 latk: I'm trying to enable sourcemaps in cljs, but when I change the project.clj I get an error I cannot decipher. Can anyone help? http://bpaste.net/show/RmYBXEuf8N3AE3XKHvbe/

10:17 bob2: == typo in your project.clj

10:17 latk: bob2: Ah, how can I work out where ?

10:17 bob2: by looking at the change you just made

10:20 latk: bob2: Sorry, my connection just died.

10:20 bob2: look at your diff

10:22 gfredericks: latk: my guess is you somewhere have a map when cljsbuild is expecting a collection of maps

10:24 latk: Right. I just copy/pasted from the wiki and edited.. we shall see

10:32 So I've changed some stuff, and now I don't get an error - but it seems that the compiler is hanging.

10:32 As in, it's been "Compiling ClojureScript." for 5 minutes

10:34 tbaldridge: what's your JVM heap size? And what are you using to compile?

10:35 latk: tbaldridge: I'm using lein. How can I check my JVM heap size?

10:37 tbaldridge: What lein command are you using?

10:38 latk: lein cljsbuild auto test-test-om

10:38 test-test-om is the name of the project

10:48 tbaldridge: latk: sometimes cljsbuild auto doesn't start compiling until a file is changed

10:48 try adding a space to a file and saving it, that should kick off the compilation

11:12 cbp: it says Compiling "foo.js" when it's actually compiling

11:13 if it just says compiling clojurescript then it has already compiled and it's waiting for changes

11:17 mikerod: When using tools.analyzer.jvm is there any good way to make it *not* throw exceptions when symbols cannot be resolved?

11:17 I'm trying to parse out the clj AST from a form, however, I know there are some symbols that will not make sense in the form.

11:17 Well, they won't make sense at the time of analysis.

11:18 However, I do want to qualify all vars that *do* exists during analysis.

11:18 kerneis: mikerod: naive idea, if you know them in advance, can't you wrap your form in (let [x nil y nil] ...)?

11:19 mikerod: The goal is to emit a form that has all symbols fully-qualified, when they can be - however, I want to leave all binding symbols alone, and allow for shadowing to occur. This is why tools.analyzer approach looks like it could almost fit my needs.

11:19 arrdem: kerneis: then they'll be locals rather than vars and it won't work.

11:19 mikerod: what are you really trying to do? what you're asking for doesn't make sense.

11:20 mikerod: arrdem: Making a DSL. I want to parse out some of the forms in it with everythign qualified, so that if I eval the forms later on, they will make sense regardless of the ns they are in.

11:20 regardless of *ns* that is

11:21 I have some "special" scoped symbols available during this. I don't want those to throw exceptions. They will be present later.

11:22 So essentially I wanted to do the :qualified-vars option and emit the form. I just wanted to not fail on the symbols that didn't make sense in the form. I may be able to "pretend" they are in scope though by passing some dummy-env or something like kerneis said about introducing them as locals at the top-level... hmm

11:22 arrdem: that doesn't make sense from a Clojure semantics point of view. Either a def exists and a var can be resolved/qualified or no def exists and you have a forward declaration which is illegal. The only way you're going to be able to do this is as you say with a dummy env that provides such forward defs because otherwise this is meaningless.

11:23 mikerod: arrdem: That's fair and that's sort of what I thought given the perspective of this being an analyzer

11:23 To go along with this goal, does tools.analyzer.jvm have any way of fully-qualifying imported Java classes? I'm not seeing this option.

11:24 So I have a form with something like, List in it - that is really imported from java.util.List.

11:24 arrdem: that stuff will already be fully qualified if a fully qualified class can be statically resolved.

11:25 there's no such thing as an "aliased" class in the JVM or TANAL

11:25 AFAIK

11:25 the class "renaming" that Clojure and Java provide is a compile time lie that goes away quickly.

11:25 mikerod: arrdem: Oh, so I guess that means as long as the env has the `import`s in it

11:25 arrdem: yep.

11:25 mikerod: arrdem: cool, I'll keep that in mind for this then.

11:25 arrdem: I mean... Bronsa is the expert on this not me, but this is what I recall.

11:25 mikerod: Thanks for the feedback.

11:25 arrdem: np.

11:45 gfredericks: clojure and java provide class renaming??

11:45 lazybot: gfredericks: Definitely not.

11:46 gfredericks: or do we just mean using the unqualified class names?

11:46 in neither case can I decide I want to spell java.util.List as "FooBar" amirite?

11:46 arrdem: the ability to use unqualified class names due to implicit as.

11:46 right.

11:47 gfredericks: okay phew

11:49 * arrdem plots a Java frontend allowing for silly class renaming

11:55 Digenis: are there any other #clojure channels in freenode?

11:55 arrdem: there's #clojure-offtopic, #leiningen, #clojurescript, #typed-clojure, #clojure-social (dead), #clojure-gsoc and some more

11:56 mikerod: gfredericks: One time I hacked the symbol table for a Namespace to map an arbitrary symbol to a Java class

11:56 gfredericks: I don't think that really counts for what you're saying, but it can be done with the Namespace API

11:57 technomancy: oh, there's a gsoc channel now?

11:57 does that mean #clojure-offtopic is actually offtopic?

11:57 arrdem: I made one a while back, hasn't been used for anything so #clojure-offtopic is still gsoc :P

11:57 technomancy: oh

11:58 mikerod: gfredericks: What I was referring to was calling Namespace#importClass(Sym, Class) with a symbol of your choice

11:58 Digenis: I see, thank you

11:58 gfredericks: ,*ns*

11:58 clojurebot: #<Namespace sandbox>

11:59 gfredericks: ,(.importClass *ns* 'HooHa java.util.HashMap)

11:59 clojurebot: java.util.HashMap

11:59 gfredericks: ,(HooHa.)

11:59 clojurebot: {}

11:59 gfredericks: (inc mikerod)

11:59 lazybot: ⇒ 2

11:59 mikerod: exactly

11:59 I don't know that is a good thing/reliable thing to do.

11:59 arrdem: (inc mikerod) ;; well that's my wat for the day

11:59 lazybot: ⇒ 3

11:59 gfredericks: ,(type HooHa)

11:59 clojurebot: java.lang.Class

11:59 mikerod: :)

12:00 technomancy: nice

12:00 mikerod: Some (probably bad) isolated clj runtime classloader stuff I was messing with one day led me to wanting to do that

12:00 technomancy: that'd be cool for the RidiculouslyLongAndVerboseClassNamesWithLongNames you see in java land

12:01 mikerod: but then I never followed through with it

12:01 technomancy: I mean, assuming you had egalitarian-ns =\

12:01 mikerod: technomancy: that's a good use case

12:01 I hate long names

12:01 LongNamesMakeMeAngryThatIs

12:01 technomancy: 80 columns is where it's at

12:01 mikerod: I can't even read them. Just a wall of texts filling my eyes.

12:02 Yes, I don't mind the 80 cols

12:05 Shayanjm: morning all

12:05 verma: what would you guys recommend for async code testing? can clojure.test do this?

12:24 nbeloglazov: verma: what kind of async code?

12:25 verma: nbeloglazov, clojure.async channels

12:27 nbeloglazov: I think you can do it in clojure.test. Java supports multithreading, so you can create some kind of latch which will block current thread until async operations are done. May be there is some specific libraries for testing core.async, don't know.

12:31 johnwalker: i've been getting clojure-test-mode is deprecated messages every time i visit a clj file

12:31 i'm on the latest versions of cider/clojure-mode

12:32 is this normal?

12:36 munderwood: Hi all. Is there an inbuilt json serializer/deserializer? or failing that which one do most people use?

12:36 arrdem: clojure.data.json is a contrib library...

12:37 munderwood: so thats packaged with clojure?

12:37 arrdem: no, that means it's separately available but still "official"ish

12:37 Glenjamin: hrm, what does having something in contrib tell you?

12:37 puredanger: No, see here: https://github.com/clojure/data.json

12:38 Glenjamin: apart from it's harder to send PRs to :D

12:38 technomancy: Glenjamin: that's about it

12:38 Glenjamin: i jest

12:38 puredanger: Glenjamin: it tells you that is is managed with the same license and contribution model as Clojure itself

12:38 Glenjamin: somewhat

12:38 puredanger: and parts of it could be included or depended on from within Clojure

12:38 technomancy: munderwood: most people use cheshire

12:38 puredanger: for example, Clojure uses data.generators and test.generative for testing itself

12:38 Glenjamin: right, i see

12:39 puredanger: (and hopefully will start using test.check in the near future)

12:39 Glenjamin: i guess there's some sort of implicit fuzzy quality bar as well?

12:40 puredanger: not necessarily - contrib libs are at many stages of development and maturity, just like any other libs

12:40 there are some ideas around bars for a 1.0 release but I'm not sure how much that's actually important

12:41 munderwood: technomancy: thanks! thats kind of what I was looking for. Although the info about contrib was useful. The distiction between contrib and the std lib is confusing for me (a clojure n00b). Coming from python where you have a lot of stuff built in and then everything else. Having a third group seems confusing.

12:41 puredanger: and contributors might be anyone that signed the CA

12:42 munderwood: at times there has been a contemplation of having an "in the box" version of Clojure that would bundle certain libs

12:42 gfredericks: count me -1 for that idea

12:42 Glenjamin: me also, dependencies are great!

12:42 munderwood: why gfredericks ?

12:42 puredanger: it's mostly historical why certain things (like clojure.test, clojure.xml, etc) are in the std lib instead of in external libs

12:43 gfredericks: munderwood: makes the ecosystem more complicated, and doesn't seem obviously useful; what sort of person has serious need for contrib libs but nothing else?

12:43 puredanger: gfredericks: that seems to be largely the consensus

12:44 it solves the "easy" at the expense of the "simple" :)

12:44 johnwalker: it might make sense to create bundles of things though

12:44 puredanger: in some ways old contrib was this, right?

12:44 johnwalker: like a web bundle that would include reviewed versions of compojure, friend etc

12:44 munderwood: how does (and I admit this is a simple example) having a built in json serializer make the ecosystem more complicated vs three different libs that all do json serilazing?

12:44 puredanger: johnwalker: you could do that now by creating a lib that merely had dependencies but no source and would pull things in transitively

12:45 johnwalker: agreed

12:45 puredanger: munderwood: json is a good example - data.json is more official looking but cheshire is more used

12:45 (I think mostly b/c it has an option to make maps with keywords?)

12:45 munderwood: Ahh I think we are talking about something different. Im talking about a stdlib rather than multiple bundles

12:45 gfredericks: puredanger: it is rumored to be faster

12:45 I've never seen data on that

12:46 technomancy: jackson has been around since forever

12:46 hiredman: puredanger: https://github.com/dakrone/cheshire#speed

12:46 er

12:46 gfredericks: https://github.com/dakrone/cheshire#speed

12:46 munderwood: Im arguing that there is justification to have basic things built into the clojure std lib.

12:46 hiredman: puredanger: dakrone is super resposive for all the libraries he maintains

12:46 gfredericks: hiredman: thanks

12:47 munderwood: I agree that having a bunch of seperate bundles would be more confusing.

12:47 puredanger: hiredman: agreed and I use cheshire more than data.json myself

12:47 gfredericks: munderwood: that forces those things to have the same slow update cycle as clojure

12:47 technomancy: munderwood: it might make sense, but the core team has an attitude towards copyright assignment that makes that very impractical

12:47 hiredman: munderwood: clojure using maven repos has a much better dependency management story than python

12:48 tbaldrid_: munderwood: yeah, some may think that, but the nice thing with small libs is the response time

12:48 hiredman: given a better dependency management system, it makes more sense to break things up

12:48 tbaldrid_: better to have 100 mutexes instead of a GIL ;-)

12:49 munderwood: I can see the logic. From a new user perspective its just hard to know which libs to use over others. Thats the downside. which makes adoption hard.

12:50 puredanger: I think most separable pieces in the std lib (test, xml, etc) would be better served outside the std lib

12:50 technomancy: munderwood: it's not that hard, you just ask on IRC and use that. =)

12:50 tbaldrid_: munderwood: because it requires a bit of research? And you still get that problem in other languages as well. I may not always want python's builtin json reader. So I should still do my research

12:50 munderwood: technomancy: ha, I guess thats what I did :)

12:51 Glenjamin: basically: the discovery problem is a better problem to have than slow moving core libs

12:51 tbaldrid_: (dotimes [x 100] (inc Glenjamin))

12:51 hiredman: well, it doesn't matter

12:52 which json library you use, unless it does

12:52 Glenjamin: heh

12:52 philandstuff: did anyone mention clojure toolbox yet?

12:52 hiredman: if it does matter, you'll have some hard requirements that drive you to a particular solution

12:52 if you don't have those requirements, it doesn't matter

12:52 munderwood: tbaldrid_: Look I get doing reseach. And thats essentially what I did. reseach is a lot easier when your experienced at clojure, you know who/what to look for in the ecosystem. I think your underestimating the knowledge gap.

12:53 philandstuff: http://www.clojure-toolbox.com/

12:53 ^ makes doing research much easier

12:53 munderwood: I know about clojure toolbox. I found its list, there are three json libs. which one do I choose?

12:53 technomancy: munderwood: I would use http://www.clojuresphere.com/ instead

12:53 it has some issues, but you can see which are the most widely-used

12:54 philandstuff: technomancy: ooh ta, that looks useful too

12:54 hiredman: the best must be what is most widely used

12:54 technomancy: hiredman: well, assuming you can't ask on IRC for whatever reason

12:54 hiredman: right? I mean, this is a meritocracy is it not?

12:54 technomancy: someone really needs to add decay to that though. just ignore the swank-clojure entry =\

12:54 tbaldridge: munderwood: that's the problem with any tech/library. You should almost always do one of two things: a) just grab one and run with it until it gives your problems. 2) read the README.md of every option weighing the pros/cons of each. If a given library does list it's design decisions move to another lib

12:54 technomancy: and the midje one

12:55 tbaldridge: *doesn't list

12:55 every tech has a tradeoff, find that tradeoff and think about if you're comfortable with it, or if you really don't care, then just grab something

12:56 hiredman: the reality is, there are three json libraries, and you basically may as well pick one at random, you will in 85% of cases be just fine

12:56 tbaldridge: If cheshire is faster than data.json does it matter if you're parsing 400bytes of data?

12:56 munderwood: Im really only bringing this up as I think this is probably something that the clojure community needs to have a think about. Getting up to speed on clojure can have some gaps IMHO. All these suggestions are welcome and I really love clojure.

12:56 AeroNotix: munderwood: there are 10 JSON ruby libraries, I don't know ruby. Which do I use?

12:57 technomancy: there are like seventeen brands of cereal

12:57 AeroNotix: Clojure doesn't *specifically* have this problem. Open sores isn't a bastion of pristine codebases or anything like that, it's a toilet filled with people throwing shit at the wall until a library falls out

12:57 hiredman: I don't think the clojure community needs more people wringing their hands about the experience for people new to the language

12:57 puredanger: munderwood: if you want to drop me a line about gaps, I'm happy to hear stuff like that alex.miller@cognitect.com and hopefully improve things

12:57 tbaldridge: "Open sores" I am sooooo using that in the future

12:58 AeroNotix: asking the community to curate a list of packages so you don't have to do research is, frankly, quite a bit selfish and needy

12:58 tbaldridge: /me bows

12:58 technomancy: this is why pagerank exists, innit?

12:58 AeroNotix: technomancy: (inc technomancy)

12:58 dammit

12:58 ,(inc technomancy)

12:58 TimMc: technomancy: Pagerank needs a decay boost when it comes to software.

12:58 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: technomancy in this context, compiling:(NO_SOURCE_PATH:0:0)>

12:58 AeroNotix: WHATEVER

12:58 TimMc: (inc inc)

12:58 lazybot: ⇒ 9

12:58 technomancy: TimMc: yeah, but it's a starting point at least

12:59 TimMc: (inc ()

12:59 lazybot: ⇒ 1

12:59 munderwood: puredanger: sure no problems. I didnt want this to come across like this. I was just hoping to highlight some of the issues I have come up against. I'll have a think about some ways I can help out with this.

12:59 TimMc: $karma (

12:59 lazybot: ( has karma 1.

12:59 hiredman: given that the people who wring their hands about the experience for new people are either new people that don't know clojure (well of course learning new things isn't as easy as just using stuff you already know) or people pushing their own pet theory of what a language should be in a backwards way

13:00 AeroNotix: hiredman: I wholeheartedly agree with that

13:00 it's why we now have millions of idiots writing JavaScript and Node applications and shoving them in our faces

13:00 TimMc: hiredman: ...and people who hang out in the IRC channel and see noobs beating their heads against the same problems over and over again.

13:01 puredanger: hiredman: I disagree. I'm interested in it and just want more people to be more successful with Clojure.

13:01 TimMc: (Some of which are basically inevitable, others of which should get fixed!)

13:01 hiredman: TimMc: sure, that is why math teachers keep trying to change how math works, right?

13:01 TimMc: I don't know much about the history of math education.

13:01 puredanger: TimMc: not enough monads I hear

13:01 tbaldridge: and I think there is much room for improvement in Clojure on the newbie front. Making design choices for users is not one of those

13:01 TimMc: I do know that it currently sucks.

13:02 hiredman: I am not saying nothing needs changing, I am saying doing it for the newbs is poor justification, since we all are here and newbs are only passing through

13:02 (either they stop being newbs at some point or they leave)

13:02 technomancy: that's a bit self-fulfilling

13:02 maybe the newbs are only passing through because things suck so much

13:03 hiredman: technomancy: passing through meaning they cease to be newbs, not that they leave

13:03 TimMc: Maybe we only end up with people who really like editing their init.el file and similar experiences.

13:03 allensb: I'm a newb with Clojure. Shouldn't the Devs that have spent months more than me researching all this stuff give the newbs advice? If I need a library I don't necessarily want to spend 3 days of research to pick the right one. Don't always have time.

13:03 TimMc: allensb: I hear that, but there are more newbs than experts, and burnout sucks.

13:04 allensb: Yeah, I can see that.

13:04 TimMc: It doesn't help that some are Help Vampires. http://www.skidmore.edu/~pdwyer/e/eoc/help_vampire.htm

13:04 technomancy: TimMc: that seems a lot less common in here than some communities

13:04 tbaldridge: allensb: pay me some money and I'll be more than glad to make all your research for you ;-)

13:05 TimMc: Yeah, definitely not as bad here as in Java land.

13:05 hiredman: tbaldridge: haha, I was just debating hitting enter on that

13:06 newbiness is a state you pass through, it is not some fundamental defining use case to optimize for

13:06 allensb: tbaldridge: haha. As a newb I've found the best way to learn Clojure is to watch the million videos on it out there. We didn't have anything like that when I started my career 10 years ago.

13:06 tbaldridge: hiredman: I'll look like the jerk today, you can have a turn tomorrow

13:07 hiredman: I was a newbie once, I like to think I have not been a newb for much longer than I was now

13:07 technomancy: just gonna leave this here https://twitter.com/seriouspony/status/476453906554159104

13:07 allensb: So basic rule, at least do some dang research first before asking a question.

13:08 philandstuff: hiredman: clojure is competing for people willing to learn it. if the dropout rate of newbs is too high, the community will not grow.

13:08 puredanger: the community is clearly growing

13:08 there are (and likely always will be) more things we can do

13:08 hiredman: it is just like a company who optimizes for getting new customers without taking care of existing customers

13:08 technomancy: philandstuff: or worse, we'll self-select for people who like pain

13:08 like erlang has

13:09 allensb: It's growing. I'm a C# Dev and have been obsessed with Clojure the last 2 months.

13:09 philandstuff: puredanger: agreed

13:09 munderwood: Im fine with trying to learn an ecosystem. And actually I was trying to phrase my questions in a non-confrontational way (which I find is hard on IRC). My original questions were trying to understand the logic behind how things are packaged.

13:09 technomancy: munderwood: I don't think they were unreasonable questions. the contrib model is weird and political.

13:10 hiredman: philandstuff: if clojure needed a lot of work for newbies, I submit to you, that #clojure would not be constantly full of newbies learning clojure (who all put in their two cents about what it should be)

13:10 puredanger: technomancy: that's a matter of opinion. although maybe that makes it political somehow. :)

13:10 mdrogalis: Yeah, I always found contrib really odd. It elevates libs that sometimes don't merit that level of attention.

13:11 ToxicFrog: If we're talking about "ways to make clojure more newbie-friendly",things like getting the compiler to not crash on syntax errors is higher priority than library organization, IMO.

13:11 hiredman: obviously clojure already has appeal and manages to pull in lots of new "customers"

13:11 munderwood: putting things inside a std lib to be available is a tradeoff. Putting things outside a stdlib is also a tradeoff. Obviously at the moment clojure has chosen one over the other. I mean that in the most neutral way possible

13:12 puredanger: mdrogalis: i think perhaps the misunderstanding is that contrib == elevation whereas it really means "same license/contrib model"

13:12 tbaldridge: Well I guess there's nothing stopping anyone from creating a project called [kitchen-sink "0.1.0"] that simply pulls in every single contrib library that would be about on par with Python.

13:12 gfredericks: I've heard contrib advertised as "guaranteed support"

13:12 hiredman: puredanger: which is amusing since the contrib model is what every hates about contrib :)

13:12 technomancy: puredanger: it doesn't though; it means "some subset of projects with the same license/contrib model"

13:12 mdrogalis: puredanger: Correct. Obvious to people who have been around for a while, completely blurry to someone new.

13:13 hiredman: puredanger: and by everyone I mean the vocal complainers in #clojure about jira and prs and etc

13:13 puredanger: gfredericks: who/where?

13:13 gfredericks: puredanger: abedra, talking to me

13:13 philandstuff: hiredman: I'm just saying that throwing newbs under a bus is a strategy that would have consequences. I don't think we are throwing them under a bus, I just don't want us to start.

13:14 mikerod: ToxicFrog: I do not think that "clj doesn't design to please newbs" argument is a valid reason to have bad exception handling and messages. Good design should attempt to give good feedback for illegal conditions. e.g. I don't think class cast or null pointer exceptions are necessarily the way to go most of the time.

13:14 mdrogalis: mikerod: So, to be fair, when Rich was building Clojure and had no attention on him, I'm sure he had many dark nights where errors messages weren't a priority.

13:15 ToxicFrog: mikerod: I entirely agree, and I don't think that this is just a "for the newbies" issue. But if we are talking about ways to make things more newbie-friendly, it's still a big issue.

13:15 mikerod: Compiler exceptions aside, the rest of the arguments about clj don't usually hold up in my opinion. There has to be a strong willingness to learn when trying to approach a new language that you intend to use professionally. I think your goal with a new language should be to become an expert.

13:15 munderwood: Thanks for all your help. When I have some more constructive things to add, i'll get in touch.

13:15 time for lunch in Miami :)

13:15 mdrogalis: munderwood: Niiice.

13:16 gfredericks: wait crap am I supposed to be in Miami right now?

13:16 mikerod: mdrogalis: yes, I'm sure that the exceptions were put on the "back-burner" when trying to get the language up and running.

13:16 Which makes sense.

13:16 gfredericks: clojure-with-bad-error-reporting has the competitive advantage over clojure-with-good-error-reporting that it exists

13:17 mikerod: I cringe a bit nowadays when I read about some new language that starts of advertising how it "uses a similar syntax from the C-family that you're familiar with" - as if this is a good thing.

13:17 technomancy: gfredericks: I think the ontological argument only works with deities last I checked.

13:17 mikerod: Or "you assign to a variable, just like you typically would in Java!" - yuck.

13:20 arrdem: is there an architecture note/history somewhere on why KeywordLookupSite exists?

13:20 gfredericks: (inc technomancy)

13:20 lazybot: ⇒ 119

13:20 gfredericks: arrdem: that's defrecord related amirite?

13:21 arrdem: gfredericks: if I knew I wouldn't be asking

13:21 gfredericks: I have the hazy notion in my head that keyword lookup on defrecords is special-cased more than vanilla maps

13:21 arrdem: yeah it is. hum...

13:22 gfredericks: it's counterintuitive to me that you can somehow do better than a case statement inside the record's #get method

13:22 tbaldridge: arrdem: it's basically callsite caching

13:23 Glenjamin: there's two types of people learning clojure, people who wanted to, and people who were told by the people who wanted to how good it was

13:23 i reckon the second group (which i just made up), could be better served

13:24 technomancy: some day we'll have people learning clojure because their bosses made them

13:24 arrdem: glod willing

13:25 Glenjamin: i reckon clojure is pretty smooth after an initial bump

13:25 hiredman: isn't KeywordCallSite dead code these days?

13:25 Glenjamin: learning-curve-wise

13:25 mikerod: technomancy: I can't wait for such an exciting day

13:26 hiredman: ah, nope, just missed it

13:26 Glenjamin: my boss suggested to me that we try should maybe try some clojurescript

13:26 arrdem: tbaldridge: hum... is this doing anything more than dynamically creating a .get specialization? it doesn't seem to be and that's only saving one cast and check.

13:26 gfredericks: technomancy: that already happens, just not sooper common

13:26 bob2: we have some people like that already at work

13:26 Glenjamin: but i have no idea if you can cleanly mix clojurescript into an existing JS project without a horrible toolchain

13:26 bob2: since we vetoed scala

13:26 gfredericks: I learned clojure in 2010 or something because my boss told me to

13:27 technomancy: mikerod: I dunno, it's kinda scary

13:28 mikerod: oh interesting

13:29 Glenjamin: where (geographically) are you based gfredericks ?

13:29 mikerod: Well, I guess I came into a job position where the project I am working on is in clj. So I was told to learn it I guess too... I just never thought of it that way. woops

13:29 gfredericks: Glenjamin: Chicago

13:29 mikerod: I just watched a bunch (all) of the Rich Hickey videos out there first.

13:30 At that point, I was onboard with being willing to learn things.

13:30 gfredericks: mikerod: yeah I guess some people look at "learn this thing" as an opportunity/excuse rather than a requirement

13:30 bridgethillyer: I’m confused about something. I don’t understand why anyone would not want to improve the beginner experience for Clojure.

13:30 Is it that there are scarce resources to apply, so if we choose to do that, we choose to not do something more important?

13:31 mdrogalis: bridgethillyer: It's mostly disagreement about how to accomplish that, I guess.

13:31 mikerod: gfredericks: Yes. I was excited to get to try something new.

13:32 bridgethillyer: mdrogalis: ah, ok. That definitely makes sense. I’ve spent a lot of time thinking about it, and I still feel kinda clueless.

13:32 mikerod: bridgethillyer: I think documentation and better exceptions are very valid concerns. I think a lot of other arguments are just around the fact that the language embraces some concepts that are unfamiliar to the mainstream. Those concepts are by design and need to be understood, not worked around.

13:33 puredanger: technomancy: (et al) sorry I dropped out of the conv above; was on a call

13:33 mdrogalis: bridgethillyer: There's also the "Well, I had to learn it this way, so you have to, too." mentality. But I don't see a lot of that around these parts.

13:33 hiredman: bridgethillyer: well yes, time devoted to something is not devoted to something else, but also I object to it being the main motivating factor, newbiness is a temporary state that people pass through, so orienting the language around it means sure the langauge will grow a lot, but what good is it to the people who aren't newbies anymore

13:34 Glenjamin: i think the focus needs to be on streamlining that journey

13:35 but even for non-newbies, the errors you get from a malformed (ns) are appalling

13:35 hiredman: basically, I think, my objection is "newbie" is not specific enough to be a real useful use case

13:35 bridgethillyer: hiredman: I think there is value to more senior people to have newbs around

13:35 hiredman: bridgethillyer: sure

13:35 mikerod: With Clojure, I've tended to always "try to get to the bottom" of whatever issue I'm having that I don't understand. This has often came down to reading the source code, digging through the Compiler etc. I think all of this investigation and reading has made me a lot more proficient at the language nowadays.

13:36 So maybe this is clj's secret way of teaching newbies. The lesson is in the digging.

13:36 Glenjamin: mikerod: i think that's a great way to learn, but that most people dont/wont want to do that

13:36 hiredman: bridgethillyer: but to drive change in the language by worrying about the use experience of a poorly defined newbie group, that is a temporary phase people pass through

13:36 allensb: I would call the bump: Rich Hickey's Youtube Talks.

13:37 hiredman: bridgethillyer: part of the value for senior people is it is rewarding watching newbs stop being newbs

13:37 mdrogalis: lol

13:37 mikerod: Glenjamin: Yes, I think if all you do is a read a bunch of documentation and come away with the idea that "I'm not going to worry about how this works - its magic to me", you probably aren't going to get the most out of your tool.

13:37 bridgethillyer: hiredman: I think you’re exactly right that we need to define who we’re addressing.

13:37 mikerod: by tool I mean language*

13:38 Rich Hickeys' talks are great. And there are many others beyond that.

13:38 technomancy: mikerod: except it is literally impossible to get anything done without doing that on some level

13:38 Glenjamin: i think selling the philosophy isn't too hard, but i think there's a large set of people who aren't as conscious that they experience the problems that rich talks about

13:38 mikerod: technomancy: true, for some things. I'm not sure I feel that way at the level of the language you use though. Not the fundamental parts of the language at least.

13:38 technomancy: it's literally no longer humanly impossible to be a "full stack" expert

13:38 even if you cut it off at the hardware level

13:39 allensb: mikerod: Those talks are just the base. If someone started to look at Clojure that is the first thing I would tell them to do.

13:39 hiredman: bridgethillyer: I don't think the language / community should be hostile to newbies, but we should get them to stop being newbies as soon as possible in a language that rewards expertise

13:39 mikerod: technomancy: yeah, there certainly has to be some lines of abstraction you draw as magic

13:39 some places

13:39 bridgethillyer: I’m totally comfortable with some people being turned off by Clojure (or whatever aspects of the ecosystem). I’m not a big fan of anything “for everybody”

13:39 mikerod: allensb: I agree

13:39 Glenjamin: if i never had to go read the clojure.lang java classes, that'd be nice

13:40 technomancy: mikerod: maybe "I wish I could spend the time to understand this, but I am a human with a limited lifespan" is a good compromise. =)

13:40 bridgethillyer: My concern is with people who would get a lot out of the language/ecosystem who are turned away for reasons that can be fixed

13:40 mikerod: technomancy: haha, maybe the real problem to solve then is the "limited lifespan" part

13:41 Glenjamin: life is too short to really grok the details of the JVM's GC?

13:41 technomancy: mikerod: on the other hand, there's something to be said for "isn't it great that there are these abstractions we can just rely on to work reliably without having to tear them apart and rebuild them in our heads from the ground up?"

13:42 bridgethillyer: hiredman: good point. Removing impediments to that would make sense then.

13:42 mikerod: technomancy: Yeah, I know what you're saying. I guess its just important to weigh the tradeoff when deciding whether or not the abstraction is worth understanding. I feel that I can use clj without having in depth understanding of how persistent data structures are implemented though.

13:42 However, I think the compiler "lifecycle" should be understood pretty well.

13:42 technomancy: mikerod: IMO the value of understanding how the abstraction works is proportional to the likelihood of it breaking down =)

13:43 just like with machines, the more likely it is to break, the more valuable the repair skill is.

13:43 mikerod: technomancy: sounds reasonable

13:43 gfredericks: I don't lose sleep at night worrying about the filesystem not working

13:43 technomancy: well, break or benefit from improvement in some way

13:44 like... you pretty much have to understand way more about how browsers work, because the abstractions they use are crap

13:44 {blake}: Why are records NOT functions that accept their field names as parameters? i.e., why can you say "my-map :some-field" but not "my-record :some-field"?

13:44 hiredman: bridgethillyer: hows clojurebridge going? (I heard the cognicast episode a while back)

13:44 gfredericks: {blake}: I don't know why, but I don't think it's bad

13:44 bridgethillyer: hiredman: There have been a number of workshops

13:45 mdrogalis: technomancy: We should start ClojureBridge Seattle.

13:45 gfredericks: {blake}: I think clojure maps are roughly used in two different ways, and that records address one of those, while IFn addresses the other

13:45 bridgethillyer: hiredman: We have some issues with the curriculum. Mainly, it’s a two-day curriculum, but it’s only a one-day workshop.

13:45 technomancy: mdrogalis: but then we'd have to find new meeting space for seajure =\

13:45 bridgethillyer: hiredman: so we’re working on that. More workshops coming together for the fall

13:45 hiredman: thanks for asking :)

13:45 mikerod: {blake}: wow, I didn't know that records weren't functions

13:45 hiredman: sure, I can imagine it is a lot to take in for one day

13:46 mdrogalis: technomancy: We are the plebes of PNW :(

13:46 hiredman: bridgethillyer: is the curriculum based on anything in particular?

13:46 gfredericks: ,(defrecord Blake [a b] clojure.lang.IFn (invoke [this k] (get this k)))

13:46 clojurebot: sandbox.Blake

13:46 gfredericks: ,((Blake. 1 2) :b)

13:46 clojurebot: 2

13:46 mikerod: gfredericks: I'd have just expected that behavior hah, wonder why it was left off

13:46 gfredericks: mikerod: I speculated above

13:46 mikerod: oh

13:46 bridgethillyer: hiredman: the teaching/training experience of people who have taught Clojure before

13:47 {blake}: mikerod, Maybe flexibility? You wouldn't always want it?

13:47 gfredericks, Thanks, I didn't know you could dothat.

13:47 mikerod: gfredericks: I see what you're saying. However, I thought when records were designed they were meant to be able to be a "drop in replacement" for the places you were using maps before.

13:47 When you decided later a record was more appropriate that is.

13:47 arrdem: being able to define a custom set of invoke implementations without defrecord checking for conflict/replacement

13:47 gfredericks: yeah there's a few other ways they're not

13:47 jasoncof: I just added ring.middleware.defaults to my app and now I'm getting this strange 'java.lang.IllegalAccessError: in-seconds does not exist, compiling:(ring/middleware/cookies.clj:1:1)' error. Any ideas?

13:48 bridgethillyer: hiredman: rather, the people who are teaching the workshops who have developed the curriculum

13:48 mikerod: I've never ran across this, meaning I've never tried to use a record as a fn. I've used a good amount of records before too. So this must not be a common usage for me anyways. :P

13:48 gfredericks: mikerod: yeah I think IFn makes more sense for homogeneous maps

13:50 Glenjamin: presumably you can extend IFn to your own maps?

13:50 hiredman: make sense, I am not even sure where I would start, I've only really once written something expository at length about part of clojure and it is difficult to figure out where to draw lines and delineate concepts

13:50 Glenjamin: erm, own records

13:50 gfredericks: Glenjamin: I just did that above

13:50 Glenjamin: so you did

13:50 missed that one :)

13:56 MC-Escherichia: I have a stupid question about records...how do I make something like a record in Java to trick my coworkers

13:56 gfredericks: O_O

13:56 MC-Escherichia: I think that is not quite specific enough

13:57 MC-Escherichia: I want to say new Record("Name","field1","field2") and then be able to say new Name(1,"test")

13:59 and then be able to access the fields as fields, or keywords

13:59 and trhat'

13:59 s all the functionality I need

13:59 hiredman: MC-Escherichia: I would look at https://github.com/boundary/fasttuple

14:00 Bronsa: mikerod: I'm reading the backlog, do you still need help with t.a.j?

14:01 MC-Escherichia: hiredman: even better than what I was thinking

14:01 thanks

14:05 noprompt_: is `prim-seq` intended to be public in clojurescript?

14:07 hiredman: dnolen_: why announce that something will be announced? wouldn't it make more sense to save the announcing until there is something to announce?

14:10 cbp: but the hype train

14:11 Frozenlock: Tsk tsk tsk. The real way to do it it to announce something will be announced, and THEN announce that something will really be announced. Announception

14:13 gfredericks: the rhickey keynote description is interesting

14:13 hiredman: to be fair, at least it isn't hyping a talk by rich where the subject is TBD, or "something big we've been working on at cognitect" there is actually an abstract with some detail, but does it need a pre-announcement?

14:14 gfredericks: mainly because it sounds exactly like how edn is advertised

14:15 puredanger: the talk will be the announcement

14:15 PigDude: i find myslef making APIs where there is a multimethod that dispatches on *identity* of first argument

14:16 i end up writing this function a lot: (defn identity-mm [o & _] o)

14:16 is this common?

14:16 amalloy: PigDude: that seems a little weird, but not outrageous

14:16 PigDude: it's all over my code. the pattern is some-method :sym -> ProtocolImpl

14:16 gfredericks: (def identity-mm (comp first list))

14:16 PigDude: and then the rest of the API is from the protocol or built on it

14:16 puredanger: PigDude: why not use "case" instead?

14:17 PigDude: puredanger: multimethods are extensible? i don't understand what you are asking

14:17 puredanger: PigDude: that's a good answer (also would have accepted: custom hierarchies) :)

14:17 amalloy: PigDude: i don't understand your "pattern" some-method :sym -> ProtocolImpl

14:17 it just looks like three symbols and a keyword, not related in any obvious way

14:18 hiredman: PigDude: people will understand it better if you say it is an lisp interpreter dispatching on the first of a list

14:18 PigDude: amalloy: (my-lib/make-thing :fluffy) => FluffyThing, (-> (my-lib/make-thing :fluffy) my-lib/proto-meth ...)

14:18 * gfredericks speculates about how hiredman pronounces "lisp"

14:18 PigDude: so user doesn't have to do (FluffyTHing.) directly

14:19 hiredman: PigDude: defrecord creates factory functions

14:19 amalloy: yeah, just use a function

14:19 mikerod: Bronsa: I think my questions were mostly cleared up. The first thing I requested was for a way to have t.a.j. "ignore" symbols that weren't in scope. - This seems to be a messy use-case and I probably just need to create/generate the appropriate environment first.

14:19 PigDude: hiredman: maybe is ruby experience but (f :thing) is easier to read than (->Thing) and end user doesn't have to know the name of Thing

14:20 hiredman: PigDude: :thing is a name

14:20 amalloy: there's no reason to have one multimethod with N bodies instead of N functions

14:20 mikerod: Bronsa: My second question was around if imported Java class symbols would be fully-qualified when emitted.

14:20 hiredman: so you either need to know the name of a function or some random keyword

14:20 mikerod: Bronsa: I think I was seeing that they weren't. However, I didn't have the :import decls in the env at that time. So I'm thinking I just need to ensure I have the appropriate env passed to analyze.

14:20 PigDude: also w/ (f :thing) i can change implementation of f later and user never knows

14:20 can't do that w/ ->Thing

14:20 mikerod: Then I'm hoping that the Java class sym's will be analyzed in their fully-qualified representation.

14:20 hiredman: PigDude: you can

14:21 (defn ->Thing [& _] (launch-the-bombs))

14:21 amalloy: PigDude: or just (defn make-thing [] (Thing.)). the name of the function doesn't have to be ->Thing

14:21 PigDude: ok, i see what you're saying

14:21 amalloy: but it should be a function, not this weird multimethod with special keywords. at least your IDE can help you track down function implementations

14:21 PigDude: but my library has a config api, and i like users to be able to say :serializer :json, not :serializer MyLibJsonSerializer

14:22 so :json is mapping to the multimethod

14:22 what's the cleaner way to accom;ish this?

14:22 sounds like there is one

14:22 hiredman: any way, a common case for dispatching on identity is some kind of interpreter, which is what your factory thing is

14:22 PigDude: what users?

14:22 PigDude: hiredman: right now internal but there's a good chance this will be open sourced

14:22 Bronsa: mikerod: re: 1, if you're interested in how to construct a "fake" environment, core.async does it you might want to look it up

14:22 PigDude: hiredman: generic log store

14:23 puredanger: why not mechanically convert the keyword to a constructor name and invoke it?

14:23 PigDude: i could, here's why i originally used mms

14:23 mikerod: Bronsa: oh, awesome. I will definitely look at that.

14:23 PigDude: clojure seems to encourage (defmethod foo :json ...) for this sort of extension, not adding :json => JsonSerialzier to some global map?

14:23 puredanger: PigDude: I mean in a way that does not require you to add a new case every time

14:23 PigDude: i don't know, what other means do i have?

14:24 i want end users to be able to provide their own serialziers, etc

14:24 hiredman: PigDude: I would either stick to namespaces, or move to something like component

14:24 amalloy: PigDude: you can also eval your config file, instead of just reading it. that makes things a lot more extensible for the user: they have the whole language available. and then they can just use a function there

14:24 PigDude: so a case :a 1 :b 2 ... doesnt' cut it

14:24 Bronsa: mikerod: re: you're right, emit-form doesn't actually qualify classes, I must have missed that

14:24 hiredman: https://github.com/stuartsierra/component

14:24 PigDude: it sounds like there's no firm way to do this

14:24 so mine is as good as any other

14:24 or am i wrong?

14:25 Bronsa: mikerod: I'll change that in the next release, in the meantime if you need it you can just monkey-patch the emit-form multimethod

14:25 PigDude: component looks like a framework framework

14:25 no thanks

14:25 mikerod: Bronsa: ah, that's helpful. I was about to check it out in a bit. Yes, I was thinking if it didn't, I was going to try to alter one of the multimethods that were responsible

14:25 hiredman: PigDude: well, what you are building is a DI system

14:25 PigDude: that's fair

14:25 hiredman: PigDude: but your multimethod lacks a way to specify dependencies

14:26 PigDude: every software that injects dependencies is a DI system?

14:26 hiredman: PigDude: or let your users pass in an environment map

14:26 PigDude: i don't think i need turtles all the way down ..

14:27 hiredman: {:json-encode ... :json-decode ...}

14:27 PigDude: i just need a clean basic implementation, and right now the one alternative i have is an obscure library

14:27 dogonthehorizon: Hey folks, I'm trying to be clever and format a sequence of strings into another string using the format form but I keep getting errors from the formatter. Here's the relevant snippet: https://gist.github.com/dogonthehorizon/c205387c4c5ade8147be . Is it because sequences are lazy and it's not being realized at the point that format is being called?

14:27 hiredman: the multimethod approach is gross because each multimethod lives in a single globally def'ed var

14:27 so you can only have one definition in a clojure runtime

14:27 PigDude: what does that mean to the library user?

14:27 one definition of what?

14:28 amalloy: dogonthehorizon: you only gave it one thing to format, a sequence

14:28 dogonthehorizon: amalloy: So (seq args) will not expand the sequence?

14:28 amalloy: you want (apply format ... args), to give it six things to format

14:28 hiredman: PigDude: if I am building system A out of systems B and C, both of which use your library and provide their own (defmethod … :json …) I may be screwed

14:28 PigDude: i see what you're saying hiredman but i think you're focusing on corner cases

14:29 dogonthehorizon: amalloy: Oh, that makes a surprising amount of sense. Thanks!

14:29 amalloy: dogonthehorizon: no function in clojure can return an "expand" view of its stuff, because a function can only return one thing

14:29 PigDude: hiredman: is there a standard clojure way to overcome this? or just using complex stuff like this component library?

14:29 amalloy: for example, seq just returns a sequential view of its argument, or nil if it's empty

14:29 PigDude: hiredman: (this global mm definition limitation)

14:30 gfredericks: protocols have the same problem

14:30 PigDude: oh ok

14:30 so, a problem, but not really a problem

14:30 a perceived problem

14:30 hiredman: PigDude: the component library is a possible approach, and it is really not very complex, it is less than 200 lines of code

14:30 amalloy: gfredericks: what? protocols don't have any such problem, because there's no dispatch values that can be overlapping

14:30 hiredman: PigDude: is a real problem

14:30 amalloy: they share one var, but you can pass in arbitrary instances

14:30 PigDude: hiredman: maybe good to measure library complexity in terms of number of lines in README :)

14:30 gfredericks: amalloy: the different libraries extending a third library the same way problem

14:31 PigDude: gfredericks: i think node has a clean solution for this?

14:31 puredanger: amalloy: isn't that false due to Java hierarchies?

14:31 hiredman: PigDude: another possible approach is making the environment an explicit parameter, so the user can choose what to pass in

14:31 Bronsa: mikerod: https://github.com/clojure/tools.analyzer.jvm/commit/df55bf039f0eb9aa6c161c363bee3e53629477e6#diff-c5f5c869e9024d37ac35f3f9344df50fR43

14:31 MrJones98: anyone here have som experience with clara-rules?

14:31 amalloy: puredanger: huh?

14:31 PigDude: hiredman: yea, you mentioned that ... what is the environment? this was vague to me

14:31 amalloy: ~anyone

14:31 clojurebot: Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."

14:32 gfredericks: PigDude: I'd be interested in what that is

14:32 hiredman: PigDude: an environment in the cs sense, a map of names to things

14:32 puredanger: amalloy: I have a protocol extension for HashMap and one for Map - they overlap?

14:32 amalloy: puredanger: sure, and HashMap wins

14:32 puredanger: amalloy: there are cases where there is no winner though and then it's arbitrary

14:32 PigDude: hiredman: that would be the super-cusotmizable approach :)

14:32 hiredman: PigDude: {:json SomeJsonCodecObject :transport SomeHttpThing}

14:32 dogonthehorizon: amalloy: Yeah, this also makes sense. Still getting used to "thinking in Clojure", so thanks for the explanation!

14:32 amalloy: but the problem i perceived hiredman to be talking about is two different consumers define something called :json, and they overlap just because they picked the same name

14:33 hiredman: the env map is nice and very direct, but you end up having to pass the map everywhere

14:33 mikerod: MrJones98: I may a little

14:33 PigDude: hiredman: i'll keep that in mind, i try to strike a balance between tweakbility and simplicity in config API

14:33 amalloy: and that doesn't happen with protocols, because there's no names to worry about, just the classes you define, which are namespaced and separate

14:33 puredanger: amalloy: yes, I digressed from original discussion

14:33 gfredericks: amalloy: he first mentioned globality, which I think is the heart of my gripe

14:33 PigDude: hiredman: maybe is good to bury this deep in the API for specific cases

14:33 hiredman: PigDude: I would suggest the balance is to leave it out

14:33 PigDude: yea

14:33 hiredman: PigDude: just call functions like amalloy and I suggested instead of putting those multimethods everywhere

14:33 PigDude: ok, thanks for the advice everyone :)_

14:34 * amalloy <3 functions

14:34 PigDude: hiredman: ok, so this is the kernel, what does that look like in code?

14:34 hiredman: multimethods are functions after al

14:34 hiredman: either solve a problem or don't, don't include a half considered solution that doesn't solve anything

14:34 radix: are clojure records implemented as maps? (i.e. with a hamt and structure-sharing updates)

14:34 hiredman: PigDude: have you needed this multimethod thing?

14:35 MrJones98: mikerod: i am trying to avoid using :fact-type-fn, and instead just wrapping my map with a field-less record

14:35 PigDude: hiredman: w/ current implemtnation, somebody extends the factory MM and the protocol if they wan tto provide a serializer implemtnation, etc.

14:35 hiredman: radix: no, they are jvm classes with fields, you can add arbitrary fields to them which end up in a hamt, but the definied fields are fields

14:35 PigDude: sorry for the typos i'm over ssh and the internethere is awful, i'm going to go work from hiome now

14:35 MrJones98: mikerod: i.e. i’m doing (merge (->Rec) {:a :b}) and inserting that as a fact

14:36 mikerod: where Rec is (defrecord Rec [])

14:37 hiredman: PigDude: do you have at least two distinct uses of the multimethod extension thing? not places where you are using it, but places where consumers have used it to extend things differently?

14:41 arrdem: &(/ 330.0 400)

14:41 lazybot: ⇒ 0.825

14:42 gfredericks: haha yay math

14:42 * arrdem apologizes for using #clojure as a calculator

14:42 gfredericks: love seeing those numbers do things

14:46 mikerod: MrJones98: ok, and you are having an issue with that?

14:46 amalloy: can we shame arrdem for not even simplifying it to (/ 33.0 40)? those wasted keystrokes are precious

14:46 mikerod: MrJones98: I guess your issue is that the field names are not "visible" to the rules engine

14:46 Bronsa: amalloy: but that's just (/ 3.3 4)

14:47 arrdem: heh

14:47 amalloy: whoa, Bronsa, let's not get crazy

14:47 MrJones98: mikerod: sorry…. i didn’t finish - i actually think that might be working and that the problem is my definition of rules in one namespace and records in another

14:47 mikerod: MrJones98: [Rec [(= ?a a)]] fails for you or something?

14:47 amalloy: you can only cancel out the visible zeros - those invisible ones are too tricky

14:47 MrJones98: mikerod: have you tried defining rules/records in different namespaces and passing that to mk-session?

14:47 mikerod: MrJones98: That should be fine. As long as you have the appropriate require's and refer's if you are not qualifying things

14:48 Yes, I've tried it too. The test cases set up for clara-rules even does it that way.

14:48 gfredericks: Bronsa: but that's just 0.825

14:48 mikerod: MrJones98: Perhaps if you are stuck on something with it, you could send a little example on a gist or something similar.

14:48 gfredericks: 4 fewer characters

14:48 Bronsa: gfredericks: I was waiting for someone to say that

14:48 radix: hiredman: ok, so if you assoc one of the declared members onto a record, it just copies the java instance and mutates that one value in the result?

14:49 gfredericks: ,(rationalize 0.825)

14:49 clojurebot: 33/40

14:49 gfredericks: ^ I can never figure out how that works

14:49 Bronsa: wuut

14:50 whoadude: I just had to come post this

14:50 mikerod: Bronsa: thanks for the commit link!

14:50 Bronsa: thanks for the quick feedback+commit on that too.

14:50 whoadude: user=> (defn reduces [coll & fns] (mapv #(reduce % coll) fns))

14:50 user=> (reduces coll max min) [99 1]

14:50 amalloy: gfredericks: it just multiplies everything by 10 until they're both integers, right? and then reduces?

14:51 whoadude: (the vector was the result)

14:51 my mind was blown... i feel like i've turned a corner

14:51 amalloy: like, ##(rationalize Math/PI) is going to be garbage

14:51 lazybot: ⇒ 3141592653589793/1000000000000000

14:51 gfredericks: amalloy: there's only one number not two

14:51 cbp: 825/1000

14:51 amalloy: gfredericks: well. okay, yes. just one

14:51 gfredericks: the denominator there is interesting though

14:53 ,(defn amalloy ([num] (amalloy num 1)) ([num den] (if (= num (Math/floor num)) (/ num den) (recur (* num 10) (* den 10)))))

14:53 clojurebot: #'sandbox/amalloy

14:53 gfredericks: ,(amalloy 0.825)

14:53 clojurebot: 0.825

14:53 gfredericks: whoops

14:53 ,(defn amalloy ([num] (amalloy num 1)) ([num den] (if (= num (Math/floor num)) (/ (int num) den) (recur (* num 10) (* den 10)))))

14:53 clojurebot: #'sandbox/amalloy

14:53 gfredericks: whoops

14:53 whoops I didn't meant to repeat the whoops

14:53 ,(amalloy 0.825)

14:53 clojurebot: 33/40

14:53 gfredericks: ,(amalloy Math/PI)

14:53 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Value out of range for int: 3141592653589794>

14:53 gfredericks: okay whatever

14:54 amalloy: that is an interesting theory.

14:54 amalloy: it's mainly the interplay between binary and base-10 that confuddles me

14:54 since converting 33/40 to a float must lose information

14:54 MrJones98: mikerod: i think i might’ve figured it out…. i needed to import the record in the namespace with defrules as well as the one that calls mk-session

14:55 amalloy: gfredericks: well it's not just a theory, it's actually how rationalize works

14:55 _alejandro: amalloy: gfredericks: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Numbers.java#L303

14:55 was looking at it while you were talking about it

14:56 gfredericks: HUH.

14:57 I swear I've seen that before and didn't think it was scrutable

14:58 amalloy: gfredericks: also, i don't think 33/40 loses any information when converting to a float, does it?

14:59 gfredericks: it should

14:59 40 is not a power of 2

14:59 so it should be an infinite binary representation

14:59 amalloy: oh, i guess it does lose some

15:01 gfredericks: ,(defn all-positive-ratios [] (iterate #(/ (- (* 2 (- % (rem % 1))) % -1)) 1))

15:01 clojurebot: #'sandbox/all-positive-ratios

15:02 hyPiRion: huh, I thought it computed the continued fraction expansion

15:02 gfredericks: ,(->> (all-positive-ratios) (remove #(-> % double rationalize (= %))) (first))

15:02 clojurebot: 1/3

15:02 gfredericks: ,(-> 1/3 double rationalize)

15:02 clojurebot: 3333333333333333/10000000000000000

15:03 gfredericks: ,(->> (all-positive-ratios) (remove #(-> % double rationalize (= %))))

15:03 clojurebot: (1/3 2/3 4/3 5/3 4/7 ...)

15:12 mikerod: MrJones98: yes, I'd imagine that mk-session needs to be aware of the environment you are bringing rules in from

15:12 MrJones98: However, I'd be curious to know what sorts of failures you are seeing.

15:12 MrJones98: And I'd be curious to see what wasn't working for you before this.

15:13 MrJones98: mikerod: i was getting a few classloader issues… but my issue before this was the rules just weren’t matching at all

15:13 mikerod: (defrule some-rule [Rec] => (println “found a rec”)) wasn’t giving me the expected output

15:14 mikerod: i’m basically just trying to adapt the main example in the readme

15:14 i’m starting to think there’s been a confluence of issues - classloader, re-def’ing records, namespaces not being loaded in the repl jvm

15:14 mikerod: MrJones98: so in one ns you made this defrule for some-rule with Rec being created via defrecord in the same ns?

15:15 MrJones98: you definitely have to be careful for redef'ing any of your defrecords

15:16 e.g. if you are inserting instances of your class Rec, and a rule matching on Rec is not firing at all - there is a chance you're dealing with 2 versions of the class named Rec

15:24 PigDude: hiredman: you asked about people using MMs to extend two things differently, but i'm not sure what you mean

15:24 hiredman: now i have internet :)

15:27 arrdem: Bronsa: looking at -emit :keyword-invoke, this will neither arity exception nor fail to emit (:foo {} :bar :baz :quxx) it seems.

15:27 &(:foo {} :bar :baz)

15:27 lazybot: java.lang.IllegalArgumentException: Wrong number of args passed to keyword: :foo

15:27 Bronsa: arrdem: It should be implemented in t.a.j IIRC

15:27 arrdem: one sec

15:28 arrdem: https://github.com/clojure/tools.analyzer.jvm/blob/master/src/main/clojure/clojure/tools/analyzer/passes/jvm/classify_invoke.clj#L44

15:29 arrdem: Bronsa: ok cool.

15:29 andyf: gfredericks: The comer

15:30 gfredericks: The conversion of double to BigDecimal in rationalize probably approximates based on current settings in BigDecimal package

15:31 teslanick: Looking for a function that takes a list of keys and a map and returns a list containing the values the keys associate to. I have to think some function for that already exists but I'm not sure what it would be called.

15:31 cbp: select-keys

15:32 mikerod: MrJones98: https://github.com/rbrush/clara-rules/issues/44#issuecomment-36637022 maybe relevant to something you were experiencing. Not sure though.

15:32 teslanick: Oh. Duh. (vals (select-keys ...))

15:32 gfredericks: andyf: right

15:32 andyf: so I guess that's the real work

15:33 mikerod: (I'm mrrodriguez as well...)

15:33 I'm still trying to figure out how to install more packages when I'm using emacs-live

15:34 https://github.com/ardumont/emacs-live-packs is the best looking option I see

15:34 technomancy: mikerod: the most annoying thing about emacs-live is how they reinvented emacs packaging for no reason =\

15:35 andyf: gfredericks: In particular see java docs for BigDecimal.valueOf(double) and BigDecimal(double) constructor

15:35 technomancy: apart from just, you know, being a starter kit in the first place

15:36 gfredericks: andyf: oh snap they're different

15:36 ,(def andy (double 1/3))

15:36 clojurebot: #'sandbox/andy

15:36 gfredericks: ,(rationalize (java.math.BigDecimal. andy))

15:36 clojurebot: 6004799503160661/18014398509481984

15:36 gfredericks: ,(rationalize (java.math.BigDecimal/valueOf andy))

15:36 clojurebot: 3333333333333333/10000000000000000

15:37 gfredericks: (inc andyf)

15:37 lazybot: ⇒ 4

15:37 gfredericks: so I guess rationalize uses the latter

15:37 wherein the work is now being done by Double#toString

15:38 andyf: No guessing required :-)

15:38 arrdem: but what's the epsilon?

15:39 hum...

15:39 clearly we need an arbitrary length float package

15:39 gfredericks: ,(Double/toHexString (double 1/3))

15:39 clojurebot: "0x1.5555555555555p-2"

15:39 gfredericks: ^ wat

15:40 ,(Double/toHexString (double 3/7))

15:40 clojurebot: "0x1.b6db6db6db6dcp-2"

15:42 puredanger_: why can't everyone just use integers

15:44 aviau: Hello! My internet skills are bad today =(. I am looking for an example web server that just echoes posts it receives. Where can I learn doing this?

15:44 arrdem: puredanger: we have yet to invent a way to actually effect the world in exact integer quantities. works great for virtual worlds tho...

15:44 nobodyzzz: is there a tool to add dependency to project.clj? something like adddep clj-http 0.9.2 and puf required string is added to project.clj?

15:44 andyf: puredanger: We do. We just don't always print them that way :-)

15:44 technomancy: aviau: (defn app [req] {:status 200 :headers {"content-type" "text/plain"} :body (slurp (:body req))})

15:45 arrdem: (inc technomancy)

15:45 lazybot: ⇒ 120

15:45 andyf: arrdem: The difference between two consecutive double values, according to java docs for Double.toString(double)

15:45 technomancy: hm... maybe :body (pr-str (update-in body [:body] slurp)) instead if you want headers

15:46 and a bunch of other stuff

15:46 arrdem: technomancy: with-out-str pprint

15:46 technomancy: oh yeah nice

15:47 aviau: technomancy, Sorry. I don't want to echo it but print it.

15:47 Anh huh, That is a web server?

15:47 and*

15:47 technomancy: aviau: it's a ring-compliant hnadler

15:47 handler

15:47 aviau: oh. So it will work with aleph?

15:48 technomancy: you'd pass it to ring.adapter.jetty/run-jetty

15:48 or that, yeah

15:48 ztellman: haha

15:49 arrdem: technomancy: oh good you still have ops.

15:49 * technomancy blows smoke from his fingerguns

15:53 arrdem: andyf: sure, I was just curious if there was a non-0.0 epsilon between the two rationalize values.

15:59 boxed: parsing the clojure cheatsheet structure into a structure that looks like clojure and not some markup: 144 lines of core.match horror :P

16:00 arrdem: boxed: ... you realize that andyf generates that thing from clojure data right?

16:00 andyf: It is the clojure data that horrifies him :-)

16:00 boxed: yea, what andyf said

16:00 andyf: I did some expedient things

16:01 boxed: it’s complected to hell with markup and page structure

16:01 a million expedient things :P

16:01 arrdem: fair

16:01 boxed: but anyway, this has been a very useful little detour into core.match which is pretty rad I must say

16:02 and all this because I wanted to write a reagent search frontend to the cheatsheet :P

16:02 andyf: I didn't have time to do that many expedient things, or it wouldn't have been expedient :-)

16:02 boxed: heh

16:04 I have a few nuts and bolts left, like figuring out the namespaces to be able to get the proper links but I think that’s pretty easy

16:05 mi6x3m: hello, is there a way besides the reader to get a data structure out of source-fn ?

16:05 gfredericks: mi6x3m: I don't think so

16:06 mi6x3m: gfredericks: oh well :)

16:06 technomancy: clojurebot: serializable-fn?

16:06 clojurebot: serializable-fn is a hack for preserving source of a compiled function: https://github.com/technomancy/serializable-fn

16:06 technomancy: mi6x3m: doesn't work with regular functions, but you could try that

16:07 boxed: is it just me that has the annoying problem that light table freezes up for a few seconds every once in a while?

16:07 mi6x3m: technomancy: it will not help me much for i need the source of dependent symbols, a list of which I get with flatten :/ my use case is simple: i show the source code to small examples of a seesaw component

16:08 guess source-fn and the reader will have to do :)

16:08 technomancy: sounds like it

16:11 nobodyzzz: I'm trying to parse a string which contains HTML with enlive, but calling (html-resource my_string) gives me NullPointerException net.cgrand.tagsoup/parser/fn--1254 (tagsoup.clj:31), 31 line in tagsoup is (with-open [^java.io.Closeable stream stream]. Any ideas why this is happening?

16:12 mi6x3m: any more efficient way to group the elements of a sequence with their index than:

16:12 aviau: technomancy, I Had a TCP server working. But I couldn't use your handler with an http server. Any ideas? This is what I have: http://pastebin.com/yLivSLMA

16:12 technomancy: aviau: I've never used aleph

16:12 mi6x3m: nobodyzzz: can you try to provide a minimal example

16:13 aviau: technomancy, Okay, thanks anyways =)

16:15 nobodyzzz: http://pastebin.com/Yg9ZpMGx (just poking around in repl)

16:15 it seems enlive treat my string as path to a file...

16:16 boxed: not-any? existing but not any?… wtf

16:16 amalloy: aviau: you want to read through https://github.com/ztellman/aleph/wiki/HTTP, and there's an example that's very similar to technomancy's

16:17 &(doc some) boxed

16:17 lazybot: ⇒ "([pred coll]); Returns the first logical true value of (pred x) for any x in coll, else nil. One common idiom is to use a set as pred, for example this will return :fred if :fred is in the sequence, otherwise nil: (some #{:fred} coll)"

16:18 mi6x3m: nobodyzzz: what is the doc saying about html-resource?

16:18 boxed: amalloy: ah.. blech, but ok

16:19 nobodyzzz: mi6x3m, not much :)

16:19 net.cgrand.enlive-html/html-resource

16:19 ([resource] [resource options])

16:19 Loads an HTML resource, returns a seq of nodes.

16:20 mi6x3m: nobodyzzz: i am looking

16:23 nobodyzzz: wrapping test to (java.io.StringReader. test) help \o/

16:33 aviau: technomancy, amalloy, I played with the example a little bit and I got it working. Thank you guys!

16:34 mi6x3m: nobodyzzz: it seems html-resource is using get-resource

16:34 https://github.com/cgrand/enlive/blob/master/src/net/cgrand/enlive_html.clj

16:36 andyf: Creating a completed data structure that suits the purposes it was created for: ~ 2 weeks. Updating it occasionally over 3 years: another 2 weeks. Getting boxed to learn that core.match is rad and earning 7 weeks in Clojure purgatory: priceless

16:36 boxed: heh

16:40 augustl: at what point does it become more efficient to create a set and union it with the original, rather than adding step-by-step in an iteration to a set?

16:41 absolute and definitive answer expected! :)

16:42 gfredericks: augustl: why not use transients?

16:42 technomancy: definitive answer: http://images.cryhavok.org/d/11335-1/Dresden+Codak+-+I+Will+Do+Science.jpg

16:42 hiredman: clojure.set is not very efficient

16:43 into is most likely faster than set/union

16:43 amalloy: the only way i can think of it mattering, augustl, would be if you were adding the same value to a large set many times. like, (into (set (range 1e5)) (repeat 1e4 0))

16:43 in that case, creating a set of (repeat 1e4 0) first would probably be faster; in any other case i can think of, you just want to dump stuff into the existing set one at a time

16:43 augustl: gfredericks: PersistentTreeSet doesn't seem to support transients

16:43 gfredericks: oooh the sorted set

16:44 augustl: PersistentHashSet can have transients?

16:44 gfredericks: ,(transient #{})

16:44 clojurebot: #<TransientHashSet clojure.lang.PersistentHashSet$TransientHashSet@164c6c9>

16:45 augustl: I need a sorted set though, boo

16:45 gfredericks: clojure 1.7 will include transient Longs and Doubles

16:45 augustl: makes sense that it doesn't support transients now that I think about it..

16:45 gfredericks: it does?

16:45 Glenjamin: augustl: data.avl has transient sorted maps

16:45 gfredericks: I thought we were just being lazy with the fringe data types

16:46 puredanger: gfredericks: and transient nil

16:46 Glenjamin: https://github.com/clojure/data.avl/

16:46 gfredericks: (inc puredanger)

16:46 lazybot: ⇒ 5

16:46 latk: I've been trying to understand why my project.clj doesn't work when I attempt to enable source-maps for cljs (om). The file looks like this: http://bpaste.net/show/g6fayuRFcRhSMAFut6Q4/ and the error is http://bpaste.net/show/rdOW7blOiy5RHGW5rM4p/

16:47 I don't really understand the error, which makes it pretty hard to debug :s

16:47 mikerod: technomancy: Sorry, I was away. I agree the packaging part of emacs-live is not making me too happy.

16:47 I don't understand the motivation behind it.

16:51 amalloy: that error message doesn't look like it came from that project.clj, latk. the line that's failing is https://github.com/emezeske/lein-cljsbuild/blob/master/plugin/src/leiningen/cljsbuild/config.clj#L73, and it's failing because :builds is a single map instead of a list of maps

16:52 hiredman: amalloy: it looks like it is a list of maps in the linked project.clj?

16:52 amalloy: hiredman: that's why i said the error message doesn't seem to match the project.clj

16:53 like, looking at the stacktrace and the line of code i linked, how can it be anything other than :builds being a single map

16:54 hiredman: makes sense

16:54 latk: I'm pretty new to clojure - how can I go about fixing this ?

16:54 I just copied the syntax from an example I found on the cljs wiki

16:56 whodidthis: https://github.com/aamedina/cljs/blob/master/src/leiningen/new/om_cljs/project.clj

16:56 gfredericks: latk: wrap that map in a vector?

16:56 technomancy: latk: from what I gather, learning cljs without a background in clojure is really difficult given the immaturity of the tooling.

16:56 amalloy: gfredericks: but it's already wrapped in a vector! that's the weird thing. his error message does not match his code

16:56 latk: technomancy: This is becoming apparant :P

16:57 amalloy: this morning i was thinking about learning cljs. you guys have now reminded me that i'd have to learn cljsbuild, and it sounds less fun now

16:57 Frozenlock: technomancy: I'd say learning cljs without JS background is also quite hard.

16:58 latk: Yeah, I have some background in JS, but almost nothing in clojure. I was hoping to use cljs as a js replacement :s

16:59 technomancy: amalloy: yeah, I'm gonna just wait for this whole browser thing to blow over and get in early on the next fad: http://www.smbc-comics.com/index.php?db=comics&id=760#comic

17:00 amalloy: hah. i've read most smbc, but only by hitting Random - i've never gone systematically through the archive - and that is a new one to me

17:00 latk: No ideas for what I might do then? :s

17:00 other than give up and learn clojure first

17:00 whodidthis: latk: https://github.com/aamedina/cljs try this to get started at least

17:01 Frozenlock: technomancy: Any ETA on the end-of-browsers? It can't come quickly enough...

17:01 whodidthis: To create a new project type "lein new om-cljs project-name", then it will hook you up with a cool new (hopefully) working project

17:01 augustl: hmm, seems PersistentTreeSet.create(myComp, null) doesn't work when using Clojure's data structures from a Java project

17:01 I get "java.lang.IllegalArgumentException: contains? not supported on type: clojure.lang.PersistentList"

17:01 gfredericks: technomancy: chewin on skunks *in clojure*!

17:02 technomancy: gfredericks: well now you have a name for your new browser-killer paradigm

17:02 all that's left is to build it

17:02 gfredericks: and a logo

17:02 and a twitter account

17:02 technomancy: the rest is little more than an exercise for the reader

17:03 gfredericks: and a website in the .io TLD

17:03 technomancy: or possibly one of the other jovian moons

17:03 gfredericks: thanks icann!

17:04 Frozenlock: What you need to know to use cljs: JS, HTML, CSS, browser-compatibility, google compiler (munging, externs...), cljsbuild tweaks and Clojure... but not exactly because they don't allow the same thing.

17:04 It's like a tower of abstractions without abstractions.

17:05 amalloy: a tower of agglomerations

17:06 Frozenlock: Oh and if you want to use the new hot toys, learn React.js as well.

17:06 amalloy: Blob?

17:06 hiredman: all these tlds are yours(for a price) except .europa, attempt no whois lookups there

17:06 gfredericks: I'm pretty sure you can't do any serious front end web dev without a similarly sized toolbox

17:06 latk: the question is though, is it worse than plain js ?

17:07 I would be surprised if it were...

17:07 technomancy: hiredman: hehe

17:07 Frozenlock: gfredericks: Bring back the .html webpage!

17:08 technomancy: latk: probably difficult to get a balanced answer on that, and it undoubtedly depends on context

17:08 gfredericks: Frozenlock: that's not a webapp that's a document

17:08 Frozenlock: You still have forms.

17:09 What more do you want?

17:09 gfredericks: no more web browsers

17:10 Frozenlock: By that you mean no more websites... or do you have an alternative?

17:10 latk: technomancy: Well, in the near future I'm going to have to write a semi complex front end for some software I'm building.. I don't really want to do it in angular.js or similar

17:11 Frozenlock: latk: do you intend to learn clojure for the backend?

17:11 gfredericks: Frozenlock: I'm just a curmudgeon so I don't mean anything in particular

17:12 amalloy: gfredericks: do you mean to imply that all curmudgeons are pointless ramblers?

17:12 latk: Frozenlock: The backend is mostly written, in Haskell

17:12 technomancy: what we need is an elaborate calculus of program maintainability to tooling overhead ratio, factoring in the expected rate of change of the program and the likelihood of needing to bring new programmers up to speed with the setup

17:12 boxed: latk: http://yogthos.net/blog/54-Building+Single+Page+Apps+with+Reagent may be helpful

17:12 Frozenlock: /random-rants I want people to stop sending .doc forms and just use webforms instead.

17:12 gfredericks: amalloy: I didn't mean to imply anything in particular

17:13 (expressly because I'm a curmudgeon)

17:13 technomancy: latk: purescript? =)

17:13 latk: purescript looks cool, but I wanted to learn a lisp :p

17:14 Also I was lead to belive cljs was more mature than purescript.. though that has not been my experince thus far

17:15 radix: latk: I don't know much about purescript (though it does look very cool), but cljs is indeed pretty awesome. there's a #clojurescript channel specifically about it fwiw

17:16 latk: radix: I'm actually already in there, but it seems somewhat dead :s

17:16 radix: ah :)

17:16 gfredericks: latk: I used it a lot a couple years ago; my guess is that there's a pretty big initial hump to get over, but then it ensmoothens a lot and is nice for anything sufficiently complex

17:16 latk: gfredericks: Did you already know clojure at this time ?

17:16 gfredericks: oh right I forgot about that difference

17:16 abandon all hope

17:17 latk: Hah :p

17:17 gfredericks: or rewrite your haskell in clojure first ;-)

17:17 latk: but muh type saftey!

17:17 technomancy: from what I've seen about the browser, it seems like a place where the guarantees of the type system are *more* important than the server

17:17 gfredericks: lol

17:17 dnolen_: latk: cljs definitely more mature than purescript on pretty much every possible metric. But yes you need to know Clojure to be productive.

17:18 technomancy: because the jvm will at least usually crash when you reach nonsense, and the browser will just keep going

17:18 dnolen_: technomancy: lol but likely for not the reasons you intended.

17:18 latk: dnolen_: Could you suggest a subset of clojure that would be sufficient ?

17:18 dnolen_: latk: no, we replicate the entire standard library outside of concurrency primitives.

17:19 gfredericks: an interesting use of defrecord with a custom IFn is as a serializable representation of a job

17:19 dnolen_: and that may change in the future if game companies have their way

17:19 latk: Hmm, are there any "roadmaps to clojurescript" or the like ?

17:19 Or do I just need to spend a week writing clojure first?

17:19 radix: dnolen_: what may change?

17:19 gfredericks: oh concurrency primitives I bet is what he meant

17:20 dnolen_: radix: Google is exploring shared memory parallelism in V8, locks and everything

17:20 radix: ooohh. cool :)

17:20 dnolen_: and Brendan Eich has not written off the idea for ES7

17:20 radix: I mean...

17:20 Frozenlock: latk: Spend a week writing clojure in a repl first.

17:20 Getting a repl with clojurescript is yet another complication

17:21 dnolen_: https://www.youtube.com/watch?v=-xNZYr40QOk

17:21 latk: Frozenlock: I have been meaning to have a look at SICP - would this be the right sort of thing to be doing ?

17:21 radix: dnolen_: so, I'm no fan of threads+locks, but won't having shared memory parallelism actually be useful as a runtime for a functional language? since you'll be able to share memory without fear since your data structures are immutable

17:21 dnolen_: Nick Bray talk from JSConf 2014 talk on this ^

17:21 radix: yep

17:21 bring it on

17:21 radix: just leave out the locks

17:21 ok, then that sounds great :)

17:22 Frozenlock: latk: I'm not the right person to ask.. I only read half of it :-p

17:22 * locks feels left out

17:22 Frozenlock: (But I watched the lectures)

17:22 latk: Frozenlock: Hah, fair enough. Seemed easier than thinking of some toy projects, is all

17:22 gfredericks: (inc locks)

17:22 lazybot: ⇒ 2

17:24 amalloy: latk: sicp is pretty great

17:24 verma: I am having a hard time understanding this, I am writing cljs program sort of and need to use macros, I created a macros.clj right alongside my cljs but I cannot use it, what is needed to get some macros working for cljs? I seem to be able to import macros fine from external sources like clojure.match

17:25 dnolen_: verma: gist would help thanks

17:27 verma: dnolen_, sure

17:32 dnolen_, https://gist.github.com/verma/3fb02dcad9a6bc3e972a

17:33 kenrestivo: hi, i remember reading about a hack in lein to inject the version number of the project into the source somehow so it can be accessed from inside the project. but i forgot

17:33 technomancy: kenrestivo: no more hacks needed; just read pom.properties

17:33 it used to be only available at jar time, but no more

17:34 Frozenlock: I usually use this https://github.com/trptcolin/versioneer

17:34 Not sure if it's still the right thing to do.

17:34 kenrestivo: technomancy: thanx

17:34 technomancy: versioneer is the thing to use if you need compatibility with pre-2.4 lein

17:35 gfredericks: read pom.properties from where?

17:35 it's not on my classpath

17:35 not at the root anyhow

17:35 technomancy: yeah it's nested or something

17:36 gfredericks: is it deep down under META-INF/classloader/JAVA/classes/com/gfredericks/POM-INFO/...

17:36 technomancy: why do you have to ask such hard questions

17:37 kenrestivo: technomancy: you mean META-INF/projectname/pom.properties ? what path would i use to slurp that from inside the project?

17:37 technomancy: kenrestivo: should be the same path whether you're running from lein or an uberjar

17:37 aperiodic: verma: I don't see any reason why that macro needs to be a macro

17:38 kenrestivo: (slurp "pom.properties") comes up FileNotFoundException

17:38 technomancy: oh hey, I was thinking "that should be in the faq" and like magic I went to add it, and it was already there

17:38 kenrestivo: ,(slurp "pom.properties")

17:38 clojurebot: #<SecurityException java.lang.SecurityException: denied>

17:38 verma: aperiodic, the fn on line 11 is called every frame, I don't want it to change the random offsets every frame

17:38 dnolen_: verma: hmm, still not enough information for me to see the issue

17:38 technomancy: (doto (java.util.Properties.) (.load (io/reader (io/resource "META-INF/maven/group/artifact/pom.properties"))))

17:38 aperiodic: verma: but your error is not anything to do with cljs, it's because your macro is written incorrectly

17:38 kenrestivo: technomancy: awesome, thanks

17:39 verma: aperiodic, oh is it?

17:39 technomancy: np

17:39 dnolen_: verma: oh i see it

17:39 verma: the symbol by is not being unquoted

17:39 ~by

17:39 clojurebot: It's greek to me.

17:39 aperiodic: verma: is there no place you could generate the offsets once at the beginning and them pass them through to that fn?

17:40 verma: aperiodic, but that won't be awesome :(

17:41 technomancy: I can't remember if I announced it or not, but I posted the lein survey results a while back https://lein-survey-2014.herokuapp.com/results

17:41 hmm... maybe like ... a couple months ago.

17:41 kenrestivo: oooh nifty, even shows the git commit? sweet.

17:41 verma: dnolen_, nice, that worked, I don't need the by unquoted though, I wanted the whole thing ~(- by (rand-int (* 2 by))) :) thanks

17:41 mi6x3m: i remember myself using ant

17:42 when I recall the past

17:42 Frozenlock: technomancy: wow, so many Mac OS X

17:42 mi6x3m: lein and maven seem like... I don't know

17:43 why are custom profiles so intensively used o_o

17:43 yeah startup times are a bit annoying

17:43 dnolen_: verma: that's symbol capture but ok, ~'by is what you want

17:44 Frozenlock: "Did you know if you have a single patch accepted you can ask for commit rights and a sticker?" I must have spent 20 seconds trying to understand what sticker meant.

17:44 Then I realized it wasn't a technical term.

17:44 mi6x3m: Frozenlock: LOL

17:44 :D

17:44 I thought so too

17:45 technomancy: Frozenlock: we send someone to your house to poke you with a stick

17:45 mi6x3m: technomancy: can you show a template of the stickers?

17:45 or they are different every time

17:45 verma: dnolen_, hmmm, ok, playing with it

17:45 technomancy: mi6x3m: it's just the logo, but I got a big batch printed on transparent backgrounds by accident

17:45 Frozenlock: "Oddly enough, the number of 3+ answers this year was almost exactly the same as last year. However, all the other numbers have fallen, especially the 1 year bracket." Clojure losing steam?

17:46 technomancy: so I tend to include five or six stickers in there to make up for it because I feel bad

17:46 mi6x3m: technomancy: round or square?

17:46 suitable for notebooks?

17:46 technomancy: square

17:46 sure

17:46 I mean, as long as you place them on a lighter surface

17:46 mi6x3m: I gotta say this is quite motivating

17:48 aperiodic: dnolen_, verma : i don't think expanding to something with 'by is desired; verma just wants to generate an offset at macro-expand time so that it's consistent every time fn is invoked (each frame). quoting the whole subtraction expression is sufficient for that.

17:48 amalloy: i wonder if i answered that lein survey

17:50 verma: aperiodic, you're right, but the outcome of it was not really what I wanted, I think I was just confused, but at least the macros are working now so I can move forward :)

17:50 thanks aperiodic, dnolen_

17:50 aperiodic: verma: also, small note: it's easier & more idiomatic to use (dec n) instead of (- n 1)

17:51 verma: aperiodic, sure, learning new things everday :)

17:51 (inc aperiodic)

17:51 lazybot: ⇒ 7

17:51 verma: (inc dnolen_)

17:51 lazybot: ⇒ 3

17:52 amalloy: technomancy: from my sample size of 1, i conclude that the reason "how long have you been using lein" got fewer answers than previously is because fewer people knew about the survey

17:55 kenrestivo: stuffed away where i won't have to remember how to do that anymore: https://github.com/kenrestivo/utilza/blob/master/src/utilza/java.clj#L101

17:56 technomancy: amalloy: seems likely

17:57 gfredericks: I don't know about a survey and I've been using lein for a long time.

17:57 I can't remember if I was using it right away.

17:57 technomancy: mi6x3m: https://twitter.com/technomancy/status/162281090336305152

17:58 mi6x3m: technomancy: let the patch hunt begin, this is quite worthy :)

17:58 great idea

17:59 is this a heron on your twitter ?

17:59 technomancy: mi6x3m: yeah, I like to work from parks

17:59 sometimes parks by lakes

17:59 mi6x3m: technomancy: great birds, herons

17:59 technomancy: oh?

18:00 mi6x3m: well yes, quite beautiful

18:00 technomancy: oh yeah, and graceful

18:00 amalloy: technomancy: i hadn't realized this, but apparently my only commits in lein are to markdown files

18:01 plus that one joke pull request

18:01 Frozenlock: pfff, no birds come close to the Shoebill http://masspictures.net/shoebill-bird/

18:01 technomancy: amalloy: it was a good one

18:03 amalloy: Frozenlock: http://www.usnews.com/news/articles/2014/07/07/largest-ever-flying-bird-a-prehistoric-dragon-found-in-south-carolina

18:04 elben: I want to convert HTML string, strip out tags and just get the raw text between tags. Something similar to beautifulsoup’s get_text (http://www.crummy.com/software/BeautifulSoup/bs4/doc/#get-text). Any ideas? Doesn’t seem to difficult to implement w/ enlive, clj-tagsoup, etc.

18:05 mr-foobar: can clojure have the problem of memory leaks ?

18:05 amalloy: &(vec (repeatedly 1e6 #(object-array 1e4)))

18:06 really, no OOME, lazybot?

18:08 i guess the wrong thread ate that OOME. poor guy

18:26 gfredericks: ,(extend-protocol clojure.core.protocols/CollReduce Long (coll-reduce [n f] (reduce f (repeat n 1))))

18:26 clojurebot: nil

18:26 gfredericks: ,(reduce str 42)

18:26 clojurebot: "111111111111111111111111111111111111111111"

18:26 gfredericks: ^ protip

18:30 cbp`: =(

18:31 amalloy: ,(reduce + 100) ;; proof that reduce==0

18:31 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>

18:32 cbp`: :-D

18:32 Frozenlock: ,(str (take 42 (repeat "1")))

18:32 clojurebot: "clojure.lang.LazySeq@643d5f61"

18:32 * Frozenlock facepalms

18:32 Frozenlock: ,(apply str (take 42 (repeat "1")))

18:32 clojurebot: "111111111111111111111111111111111111111111"

18:39 AeroNotix: ,(reduce str 42)

18:39 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long>

18:40 gfredericks: what should LazySeq#toString be changed to do?

18:42 amalloy: gfredericks: (throw (Exception. "This never does what you want anyway, so why bother?"))

18:43 gfredericks: haha oh geez

18:43 people would hate that pretty quick

18:43 technomancy: "It looks like you're trying to stringify a lazy seq. Did you mean ..."

18:46 gfredericks: returning "#<LazySeq>" would be better than nothing

18:46 or similar

18:47 I don't see a big reason not to just do pr-str though

18:47 technomancy: maybe invoke whichever honors *print-length*?

18:47 gfredericks: hmm

18:48 I don't think the current behavior reliably saves anybody from anything

18:48 since most repls don't even use it

18:48 technomancy: surely it's being called by accident on an infinite seq deep in some codebases somewhere

18:49 amalloy: technomancy: that doesn't ever return

18:49 gfredericks: that's true it would be backwards-dangerous

18:49 amalloy: so the current behavior is not much good anyway

18:49 gfredericks: oh right of course

18:49 technomancy: oh, really?

18:49 I thought the whole point was to avoid realizing it

18:49 gfredericks: amalloy: okay so surely it's being called by accident on a large seq deep in a memory-strapped codebase somewhere

18:49 technomancy: that's the problem is it doesn't even do that

18:49 technomancy: ok, yeah pretty lame

18:50 amalloy: technomancy: i thought that too, but every so often i am reminded that this is not the case

18:50 ,(str (iterate inc 0))

18:50 clojurebot: "(0 1 2 3 4 ...)"

18:50 gfredericks: haha wat

18:50 ,(str (range))

18:50 clojurebot: #<OutOfMemoryError java.lang.OutOfMemoryError: Java heap space>

18:50 amalloy: whaaaaaat

18:50 gfredericks: hiredman you weirdo did you special-case (str (iterate ...))

18:51 hiredman: definitely not

18:51 technomancy: geez, rude to ask

18:51 amalloy: &(str (iterate inc 0))

18:52 lazybot: java.lang.OutOfMemoryError: Java heap space

18:52 hiredman: ,(type (iterate inc 0))

18:52 clojurebot: clojure.lang.Cons

18:52 hiredman: ,(type (range))

18:52 clojurebot: clojure.lang.LazySeq

18:52 amalloy: oh jeez. friggin iterate

18:52 gfredericks: ,(type (rest (iterate inc 0)))

18:52 clojurebot: clojure.lang.LazySeq

18:53 gfredericks: still confused

18:53 hiredman: haha

18:53 the toString on ASeq calls RT.printString

18:53 Cons extends ASeq

18:53 amalloy: yeah. i guess ASeq assumes that it will only be for finite, realized sequences?

18:53 gfredericks: and RT.printString somehow goes throw a clojurebot codepath?

18:53 hiredman: no

18:53 amalloy: gfredericks: no, not at all

18:54 it prints it like the repl would

18:54 gfredericks: with a *print-length*?

18:54 hiredman: LazySeq doesn't implement ASeq

18:54 gfredericks: yeah, printString must just call the pr var

18:54 amalloy: gfredericks: clojurebot has *print-length* set all the time, probably

18:54 hiredman: yep

18:54 amalloy: not just when attempting to print a result

18:54 hiredman: oh clojure, you are the living end

18:55 Frozenlock: Clojure is like a box of chocolates

18:55 amalloy: ,(str (cons 'infinity (range)))

18:55 clojurebot: "(infinity 0 1 2 3 ...)"

18:55 gfredericks: I pretty much didn't know about print-length

18:56 devn: gfredericks: award for best readme goes to you for qubits

18:56 gfredericks: devn: w0000hthx

18:57 devn: speaking of great readme/content in the same vein

18:57 http://hoplon.discoursehosting.net/t/get-rich-with-hoplon-part-1/115

18:59 gfredericks: so not only does (str a-lazy-seq) not save the seq from getting realized, but infinite not-instances-of-LazySeq get treated differently

18:59 devn: "The idea is, while listening to the song, the user can tap their phone's screen and determine the tempo1 of the song. They can then blog or tumbleblog or retweet or whatever with this number because quantified self and social networking fitbits Ashton Kutcher South-by."

19:00 technomancy: imma get the high score on taptobmp.com and you can't stop me

19:01 Frozenlock: I don't like that everything is in the fragment in Hoplon :-(

19:01 http://hoplon.io

19:02 (Instead of a real URL that hits the server)

19:02 But maybe I'm just old fashioned.

19:29 mthvedt: anyone with any experience writing friend workflows?

19:37 fifosine: How do I turn a lazy sequence of ints into a lazy sequence of keys?

19:38 dnolen_: fifosine: do you mean keywords?

19:38 amalloy: you mean keywords like :1? why would you do that?

19:38 fifosine: Yea, so that I can use zipmap

19:38 hiredman: you can use numbers as keys

19:38 ,{1 1}

19:38 clojurebot: {1 1}

19:39 fifosine: ,(get 1 {1 1})

19:39 clojurebot: nil

19:39 aperiodic: that's not how you use get

19:39 amalloy: ,(get {1 1} 1)

19:39 clojurebot: 1

19:39 dnolen_: ,(zipmap (range 5) (repeat "foo"))

19:39 clojurebot: {4 "foo", 3 "foo", 2 "foo", 1 "foo", 0 "foo"}

19:39 hiredman: ,(doc get)

19:39 clojurebot: "([map key] [map key not-found]); Returns the value mapped to key, not-found or nil if key not present."

19:41 fifosine: ty

19:44 gfredericks: ,(get get get get)

19:44 clojurebot: #<core$get clojure.core$get@7f6155>

19:44 aperiodic: (inc gfredericks)

19:44 lazybot: ⇒ 76

19:45 aperiodic: the Buffalo buffalo of clojure

19:45 technomancy: related: https://twitter.com/technomancy/status/327234371813781505

19:46 gfredericks: RT https://twitter.com/technomancy/status/327234371813781505

19:51 verma: arrdem, the grimoire syntax theme was inspired by an existing colorscheme or is it your own?

19:52 gfredericks: ,((juxt (juxt :a :b) (juxt :c :d)) {:a :a, :b :b, :c :c, :d :d})

19:52 clojurebot: [[:a :b] [:c :d]]

19:52 gfredericks: ,(partial partial partial)

19:52 clojurebot: #<core$partial$fn__4228 clojure.core$partial$fn__4228@1e0799a>

19:52 fifosine: I'm trying to mask a function in my tests so that I can provide input like this: (with-redefs [read-line #("1")] (read-line))

19:53 Is this a right way to go about it?

19:53 gfredericks: ,((constantly constantly))

19:53 clojurebot: #<core$constantly clojure.core$constantly@b2f2d6>

19:53 AWizzArd: clojure.async: (dotimes [i 5] (put! chan i)) Is there a `foo` which will do (foo chan) => (0 1 2 3 4) ?

19:54 gfredericks: fifosine: ##(with-redefs [read-line (constantly "1")] (read-line))

19:54 lazybot: java.lang.SecurityException: You tripped the alarm! with-redefs-fn is bad!

19:54 gfredericks: clojurebot: You |tripped| the alarm! with-redefs-fn is bad!

19:54 clojurebot: 'Sea, mhuise.

19:55 technomancy: ,((constantly constantly) constantly constantly constantly constantly constantly constantly constantly constantly) though

19:55 clojurebot: #<core$constantly clojure.core$constantly@b2f2d6>

19:55 alandipert: (reduce partial (repeat partial)) ; world's most partial function

19:55 fifosine: gfredericks: Are you not supposed to use with-redefs in tests?

19:55 technomancy: ,(apply (constantly constantly) (repeat constantly))

19:56 clojurebot: #<core$constantly clojure.core$constantly@b2f2d6>

19:56 verma: AWizzArd, you mean like <! ?

19:56 technomancy: huh, that worked

19:56 * technomancy makes a K-combinator gang sign

19:56 gfredericks: fifosine: nope it's fine

19:57 AWizzArd: verma: yes, I want a <! which will read all elements from the channel and return them in a list

19:58 verma: AWizzArd, may be (repeatedly #(<! chan)) ? but that's a lazy seq

19:59 gfredericks: ,(-> + (partial 7) (partial 4) ())

19:59 clojurebot: #<CompilerException java.lang.IllegalArgumentException: Can't call nil, compiling:(NO_SOURCE_PATH:0:0)>

19:59 gfredericks: ,(-> + (partial 7) (partial 4) (deliver 9))

19:59 clojurebot: 20

19:59 fifosine: Anyone know how to view stdout in lighttable?

19:59 technomancy: funcall!

20:00 * technomancy funcalls the guards

20:00 hiredman: I think deliver is too powerful, it needs to be banned to keep things fun

20:01 Frozenlock: deliver?

20:02 TEttinger: (doc deliver)

20:02 clojurebot: "([promise val]); Delivers the supplied value to the promise, releasing any pending derefs. A subsequent call to deliver on a promise will have no effect."

20:02 gfredericks: ,(defn deliver? [x] (= x deliver))

20:02 clojurebot: #'sandbox/deliver?

20:02 gfredericks: ,(deliver? 'hey)

20:02 clojurebot: false

20:02 gfredericks: ,(deliver? deliver)

20:02 clojurebot: true

20:02 amalloy: clojurebot: deliver is a version of funcall snuck into clojure by a lisp-1 fanatic

20:02 clojurebot: c'est bon!

20:02 amalloy: er, lisp-2. dangit

20:03 gfredericks: haha you can't take it back now

20:03 hiredman: the implementation of deliver happens to be (fn [x y] (x y)) because of laziness in implementation of promises

20:03 gfredericks: clojurebot NEVER forgets

20:03 amalloy: clojurebot: forget deliver |is| a version of funcall snuck into clojure by a lisp-1 fanatic

20:03 clojurebot: I forgot that deliver is a version of funcall snuck into clojure by a lisp-1 fanatic

20:03 amalloy: clojurebot: deliver is a version of funcall snuck into clojure by a lisp-2 fanatic

20:03 clojurebot: Roger.

20:03 amalloy: hiredman: s/laziness/sloppiness, just because laziness is so overloaded in clojure

20:03 TEttinger: hello?

20:03 clojurebot: BUENOS DING DONG DIDDLY DIOS, fRaUline TEttinger

20:03 Frozenlock: clojurebot: Datomic is still not FOSS.

20:03 clojurebot: Ok.

20:03 Frozenlock: :-D

20:04 fifosine: ,datomic

20:04 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: datomic in this context, compiling:(NO_SOURCE_PATH:0:0)>

20:04 TEttinger: ...good ding dong diddly god, miss TEttinger?

20:04 fifosine: how do you ask it facts

20:04 TEttinger: datomic?

20:05 Frozenlock: Is it case sensitive?

20:05 fifosine: clojurebot: Is Datomic FOSS?

20:05 technomancy: ,tias

20:05 clojurebot: No entiendo

20:05 #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: tias in this context, compiling:(NO_SOURCE_PATH:0:0)>

20:05 amalloy: clojurebot: is it case sensitive?

20:05 clojurebot: excusez-moi

20:05 TEttinger: clojurebot: datomic |is| a money-making scheme

20:05 clojurebot: You don't have to tell me twice.

20:05 TEttinger: datomic?

20:05 clojurebot: datomic is a money-making scheme

20:06 fifosine: ah-ha

20:06 TEttinger: Datomic?

20:06 Frozenlock: Datomic?

20:06 clojurebot: Datomic is still not FOSS.

20:06 Datomic is still not FOSS.

20:06 Frozenlock: Yeah, case sensitive

20:06 fifosine: scheme?

20:06 clojurebot: scheme is Scheme is like a ball of snow. You can add any amount of snow to it and it still looks like snow. Moreover, snow is cleaner than mud.

20:07 fifosine: anyways, does anyone know how to view stdout in lighttable, e.g. see "5" when you exec (println "5")?

20:07 TEttinger: fifosine, run it in the repl?

20:07 fifosine: TEttinger: I'd have to copy-paste all my code

20:07 TEttinger: light table I believe only shows you return values

20:07 Frozenlock: fifosine: Been a while since I used lighttable, but isn't it Shift+Ctrl+C to show the console?

20:08 TEttinger: huh why?

20:08 just import it

20:08 require, sorry

20:08 fifosine: frozenlock: yes, thanks!

20:08 * Frozenlock knows something!

20:20 gfredericks: hey if you want to have a good time do a (shuffle 1000) and try to find the 0

20:20 best way to spend your evening

20:20 (shuffle (range 1000)) I mean

20:20 if you figure that one out, then try to find the 1

20:21 Frozenlock: ,(some #{0} (shuffle (range 1000)))

20:21 clojurebot: 0

20:21 Frozenlock: It's there!

20:21 gfredericks: if you get bored of that, mix things up -- bump it to 2000 and look for your birth year

20:21 get creative!

20:22 if you really want to challengeg yourself try (repeatedly 2500 #(rand-int 2)) and look for patterns

20:22 amalloy: gfredericks: c'mon man, it's 2014 already. clojure surely has some programmers born after 2000

20:23 gfredericks: raynes would have told us about it

20:23 amalloy: maybe he did and you ignored him because you don't take youth seriously

20:27 gfredericks: yeah well maybe I took youth seriously and you ignored it because you don't take me seriously

20:28 Frozenlock: lol

20:29 Is Clojure hip with the kids?

20:30 platz: no

20:30 amalloy: ,hip

20:30 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: hip in this context, compiling:(NO_SOURCE_PATH:0:0)>

20:33 technomancy: Frozenlock: https://a248.e.akamai.net/media.pinterest.com.s3.amazonaws.com/736x/8a/76/60/8a7660926fd0668dfc5ae9aa39feff00.jpg

20:34 Frozenlock: Wise man

20:34 technomancy: Are you showing Clojure to your little ones yet?

20:35 * gfredericks gets out racket shield

20:45 gfredericks: ,(defmethod print-method :print-fn [x pw] (.write pw ((-> x meta :print-fn) x)))

20:45 clojurebot: #<MultiFn clojure.lang.MultiFn@724356>

20:46 gfredericks: ,(with-meta '(1 2 3) {:type :print-fn :print-fn #(str "#<I am a list with a " (first %) " >")})

20:46 clojurebot: #<I am a list with a 1 >

20:47 gfredericks: I think I've written that sort of thing a few times

20:49 fifosine: ,(let [input "1"]

20:49 (condp = input

20:49 "0" "1"

20:49 "1" "0"))

20:49 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

20:49 fifosine: ,(let [input "1"] (condp = input "0" "1" "1" "0"))

20:49 clojurebot: "0"

20:49 fifosine: Is there a better way to write the above?

20:50 Since there are only two possibilities, and they "switch"

20:50 amalloy: i mean, if this binary switching is a common pattern for you, you can make it into a function

20:50 gfredericks: fifosine: I always write that {"0" "1", "1" "0"}

20:51 fifosine: gfredericks: Just make a map, you mean?

20:51 gfredericks: ,(def singleton-bitstring-flip {"0" "1", "1" "0"})

20:51 clojurebot: #'sandbox/singleton-bitstring-flip

20:51 gfredericks: ,(let [input "1"] (singleton-bitstring-flip input))

20:51 clojurebot: "0"

20:53 gfredericks: ,(def ? (fn [_] (rand-nth [true false])))

20:53 clojurebot: #'sandbox/?

20:55 gfredericks: apparently this is what I do when there's tedious code I need to write

20:55 technomancy: Frozenlock: no, sticking with racket and scratch so far

20:55 clojure has too much incidental BS

20:55 arrdem: verma: nope that's existing. the last color scheme I built to look like emacs... "got replaced" with what is now used for my blog and Grimoire

20:56 fifosine: ,(map {"0" "1" "1" "0"} "01")

20:56 clojurebot: (nil nil)

20:56 fifosine: mmm

20:57 gfredericks: chars

20:57 fifosine: ,(map {\0 \1 \1 \0} "01")

20:57 clojurebot: (\1 \0)

20:58 fifosine: gredericks: So I string is really a list of chars?

20:58 gfredericks: no

20:59 a string gets turned into a list of chars if you pass it to a function that expects a seq

20:59 hiredman: gfredericks: I tend to start writing abstract machines to execute code in other languages that already do the tedious stuff before remembering I need to get this stuff through code review at some point

20:59 Frozenlock: technomancy: any chance of seeing racket used for 'real' stuff?

21:00 technomancy: gfredericks: proof: https://twitter.com/hiredman_/status/423167878326530048

21:00 gfredericks: ,(->> "01110101001" (map {\0 \1 \1 \0}) (apply str))

21:00 clojurebot: "10001010110"

21:00 hiredman: I started writing a secd machine to execute ruby today using jruby's parser, which was a terrible idea since I don't really know ruby

21:00 technomancy: Frozenlock: by me specifically?

21:00 Frozenlock: No, just in general.

21:01 I tried it once and remember it was interesting, but nothing more...

21:01 technomancy: Frozenlock: sure, it's definitely the most practical of any scheme

21:01 hiredman: and this gem is really just a wrapper around shelling out to a binary, which I should just do

21:01 Frozenlock: Hmmm

21:01 Should take another look.

21:01 technomancy: Frozenlock: the main downside is that all their web stuff goes on and on about how continuations are such a great model for web sessions

21:01 which is pretty annoying

21:01 but apart from that it's really nice

21:02 libs are weak compared to clojure, but getting better

21:03 gfredericks: hiredman: TIL SECD

21:03 you wrote this in clojure?

21:03 hiredman: I started to

21:04 to be honest it started as a CESK machine

21:05 gfredericks: this is so hipster it doesn't even have its own wikipedia article

21:07 I wrote a lazy BF interpreter the other day

21:08 just because somebody was in here talking about it

21:17 hiredman: actually http://matt.might.net/articles/oo-cesk/ could run a lot of ruby off the bat I think

21:24 fifosine: ,(map (partial take-nth 2) '("1122" "1122"))

21:24 clojurebot: ((\1 \2) (\1 \2))

21:24 fifosine: Is a partial necessary here, or is there another way to write this without using a partial?

21:29 amalloy: naturally, fifosine, there are arbitrarily many ways to write it. for example, you could use #(), or a for-comprehension

21:29 Frozenlock: http://racket-lang.org/download/docs/6.0.1/html ---> > ((uncaught-exception-handler)

21:29 Wow, worse than Clojure docs! :-p

21:29 amalloy: on the less practical things, you could write a prolog interpreter and then write a prolog program that does what you want

21:29 fifosine: amalloy: Is what's written above idiomatic?

21:30 amalloy: perfectly reasonable. i probably would write instead (for [s ["1122" "1122"]] (take-nth 2 s)), but there's nothing wrong with yours

21:32 dbasch: I would write [[\1 \2] [\1 \2]] :)

21:33 amalloy: ,(map list "11" "22")

21:33 clojurebot: ((\1 \2) (\1 \2))

21:44 gfredericks: ,(repeat 2 '(\1 \2))

21:44 clojurebot: ((\1 \2) (\1 \2))

21:45 gfredericks: ,(->> (repeat (range)) (map #(map str %)) (map #(map first)) (map rest) (map #(take 2 %)) (take 2))

21:45 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: sandbox/eval51/fn--54>

21:45 gfredericks: ,(->> (repeat (range)) (map #(map str %)) (map #(map first %)) (map rest) (map #(take 2 %)) (take 2))

21:45 clojurebot: ((\1 \2) (\1 \2))

21:46 gfredericks: ^ if you're not starting with an infinite seq of infinite seqs you're doing it wrong

21:54 fifosine: Is there a way to stop println from trimming strings?

21:57 nvm

22:00 If nobody minds code-reviewing this small code snippet for idiomatic clojure, efficiency, style, that'd be awesome. http://www.reddit.com/r/dailyprogrammer/comments/2avd5i/7162014_challenge_171_intermediate_zoom_rotate/cizl682

22:02 dbasch: ~flatten

22:02 clojurebot: flatten is rarely the right answer. Suppose you need to use a list as your "base type", for example. Usually you only want to flatten a single level, and in that case you're better off with concat. Or, better still, use mapcat to produce a sequence that's shaped right to begin with.

22:03 fifosine: dbasch: ok, I'll remember that, thanks!

23:39 Subapical: Hello, transitioning from Scheme to Clojure

23:39 So far, so good

Logging service provided by n01se.net