#clojure log - Aug 10 2015

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

5:32 WickedShell: I'm trying to chase down a large and ever growing number of java.lang.reflect.Method's that I'm building up till they are GC'd (well up in the millions) but when I turn on *warn-on-reflection* I now get a nullpointer in one of my source files that has been compiling without any problem until now. Anyidea why this might happen?

5:34 TEttinger: WickedShell: clone an earlier version that didn't have the bug from version control, turn on warn-on-reflection, check if bug is present then?

5:34 WickedShell: I... yeah I guess. Gotta go back really far. Will try

5:43 Is there any reason why passing nil into a java library function could cause warn-on-reflection to break? That seems to be the only thing of significane on the line

5:44 The offending line (g2 is already type hinted as java.awt.Graphics2D ): (.drawImage g2 planeIcon 0 0 nil)))

5:55 Apparently it can't resolve the inherited method .drawImage I had to instead cast it to a graphics object and draw with that :/ which is werid but I guess it works

6:12 hm... I've solved all the reflection cases that occur within my code (that is running, theres some that has some left but isn't active) and did a lein clean, and am still seeing about 10k more instances of reflect occur every second...

7:05 CookedGryphon: Is there a reason partition-all doesn't have a transducing version with a step?

7:05 the arities are n, n coll, or n step coll, and I want n step with no coll

7:41 hyPiRion: CookedGryphon: backwards compat. [n coll] is already there

7:41 That's my guess at least

8:43 justin_smith: devn: my preference is to not use lein on production boxes, and not to use aot either. I make a very small shim namespace that loads up the rest of my code in an uberjar.

8:57 cenzhe: Hi all, I got this problem and hope some one can point me in the right direction

8:57 snowell: cenzhe: Just ask it, and somebody should answer :)

8:57 cenzhe: We are currently combining Spring with Clojure

8:58 But the classpath that is received by the clojure part of the code seems wrong

8:58 When I print (seq (.getURLs (java.lang.ClassLoader/getSystemClassLoader)))

8:59 I got only $TOMCAT_HOME/bin/bootstrap.jar and $TOMCAT_HOME/bin/tomcat-juli.jar

9:01 Do I need to add some bootstrap code or anything to make this work?

9:01 The question I asked is obviously incomplete, but I'm not sure what to add here

9:01 please ask if you think anything relevant

9:03 The logic I understand here is: I took AOT on some of the ns, generating some annotated classes for spring MVC component scan.

9:04 When I triggered a URL request, this request was received by spring framework, past the filters and reached the mapping I declared in clojure.

9:07 Anyone can point me to further readings on how clojure was bootstrapped, with all the classloader details explained?

9:12 kasterma: I am trying to load the example data as used in the datomic turorial. This generates a “two datoms in the same transaction conflict”. My code is at https://gist.github.com/kasterma/9e6087f9c0e93239fadc

9:12 I have queried a datomic db enough, but never added data to it. Hoping I am just doing something silly.

9:13 Any obvious mistakes?

9:14 I don’t understand the format in seattle-data0.edn yet, so hard for me to see if there is an issue there. LIkely the issue is between chair and keyboard though.

9:37 bornthird: Hi - does anyone know how I can select all text content from elements - including empty content - with enlive? When I try (html/select some-resource [:table :tr :td html/text]), I'll only get back non-empty content. I'm guessing that is because :content nil for empty nodes, but I still want to get back that nil or ""

9:48 cenzhe: have you tried putting html/text outside?

10:01 bornthird: cenzhe: ahh yah, if i map that to the results that works, duh. Thanks!

10:04 justin_smith: cenzhe: are you making an uberjar?

10:05 cenzhe: what clojure will need is to find either a clj file or the generated aot artifacts on the classpath for every namespace you use

10:05 the part I don't know is how you would tell spring to make those available

10:10 cenzhe: justin_smith: No, i'm not making an uberjar. I'm building it using maven, generating a WAR archive

10:10 justin_smith: cenzhe: OK, then an uberwar, or are you providing the deps in some other manner?

10:11 cenzhe: I'm not sure what you mean here..

10:11 justin_smith: cenzhe: I don't really know the maven options, but "lein ring uberwar" can create a war containing all the deps your clojure code needs at runtime

10:11 as opposed to only containing your own code and relying on some other mechanism to supply your deps at runtime

10:13 cenzhe: em.. I kinda got your point but the framework is not easily changed in production, and I'm trying to minimize the amount of change to push things forward

10:14 justin_smith: cenzhe: all I'm trying to do is figure out how you are providing the deps the clojure code expects. I'm suggesting the methods I have historically used. I am sure there are other alternatives.

10:14 cenzhe: when your code needs clojure.jar, where exactly is that provided from? who supplies it?

10:14 because your code will not run without clojure.jar

10:15 cenzhe: yes, you're absolutely right. I guess the tomcat servlet is able to load the AOT file, as well as other deps that clojure requires.

10:16 I can make invocations to other clj methods in the controller I defined

10:16 justin_smith: OK

10:16 cenzhe: it's just the classpath seems not right

10:16 justin_smith: perhaps your deps are on that new classpath?

10:16 it shouldn't be too hard to look, right?

10:17 cenzhe: yah, I'll try track it further

10:18 justin_smith: cenzhe: my experience with tomcat (but not using spring) is that I wrap up my code and all its deps into a war file (an "uberwar"), and then tomcat adds those deps to the classpath after extracting the war in its custom place

10:18 cenzhe: :D correct, I extracted the WAR file, and all those deps are lying right at the WEB-INF/classes folder

10:19 justin_smith: yes, that's exactly how I remember it

10:19 cenzhe: whoops, WEB-INFO/lib folder

10:19 justin_smith: heh, close to what I remember still...

10:32 cenzhe: wow, problem solved! the classpath I got is correct

10:32 the reason I thought it's wrong, is because I failed to distinguish a context class loader from system class loader

10:32 justin_smith: I guess that would do it

10:33 tbh some stuff about classloaders still baffles me - eg. anything about OSGI

10:33 cenzhe: :D thanks! justin!

10:34 justin_smith: heh, I don't think I did much, but you're welcome anyway

10:34 oddcully: (inc rubberduck)

10:34 lazybot: ⇒ 4

10:35 * justin_smith quacks.

10:37 cenzhe: haha, how to do that? I'm new to IRC

10:38 justin_smith: cenzhe: /me

10:38 * cenzhe laughs

10:39 ericbmerritt: is there a convention around using deftest vs with-test and where tests should be (ie in the same file as the tested thing or in the tests directory)?

10:39 justin_smith: ericbmerritt: most common is deftest and giving tests their own files / directories

10:40 ericbmerritt: Thats the impression I have been getting. I dislike that it separates tests from the thing tested, but it does seem to make things a bit cleaner

10:40 justin_smith: ericbmerritt: the convention is for the test namespaces to follow the same heirarchy as the regular namespaces

10:41 ericbmerritt: editors have commands to automatically jump to the test ns based on that convention

10:41 ericbmerritt: so the namespace is exactly hte same? no '-test' at the end?

10:42 justin_smith: that's the one difference - each ns has -test added, but is otherwise in the same place under a separate test/ root

10:43 I actually like the idea of defining a test with the code it is testing, but have experienced so much friction against it that I have accepted the convention

10:44 ericbmerritt: friction in that you ran into problems with executing, or friction people are idiots and don't like to change?

10:44 justin_smith: hehe now I wouldn't call them idiots...

10:44 no, the execution was no problem at all, it was a culture / convention issue

10:45 ericbmerritt: hmmm, I am not sure how much I care about a convention that is 'bad' for some value of bad

10:52 oddcully: if you need an argument for the separation: you could end up with deps into test libs in regular code

11:09 axsk: ,(/ 39.4 100)

11:09 clojurebot: 0.39399999999999996

11:09 axsk: what can i do against that strange division "error"

11:10 i want it to be 39.4, which is representable in double afaik

11:10 eh 0.394

11:12 akabander: I'm trying to build a CLI utility using lein-bin, but when I run "lein bin", I get a "No implementation of method: :as-file of protocol: #'clojure.java.io/Coercions found for class: clojure.lang.Symbol" error. I'm sure I'm missing something, can anyone point me in the right direction?

11:13 oddcully: ,(/ 39.4M 100.0M)

11:13 clojurebot: 0.394M

11:19 akabander: I'll note that it works when I do "lein run"

11:20 And I can build and execute an uberjar.

11:56 kungi: I am trying to transact a large transaction in datomic and get this error: http://pastebin.com/tVHTkz9s any idea what I can do?

12:01 oddcully: kungi: after it's the same entity, attribute and tx, right?

12:02 s/after/&all/

12:02 kungi: oddcully: Somehow It becomes the same entity yes

12:02 oddcully: some error while reading?

12:04 kungi: I create a vector of maps with [{:db/id #db/id[:db.part/user] :some :data ...}] with about 1200 entries

12:04 When I transact this the entity ids clash

12:05 oddcully: did the business in question move? have you duplicate data?

12:05 kungi: oddcully: The database is initially empty

12:05 oddcully: the error seems legit

12:06 if the entity in question has more than one street, could the schema be wrong?

12:07 (i doubt it, since an address would not only consist of the street0

12:07 kungi: no it only has one street :-)

12:07 I have an idea ...

12:08 oddcully: then my guess is, that your import data have the entity there two times (or at least you detect it as the same)

12:08 kungi: Ok each entity has the same id in my import ...

12:11 \o/

12:33 csd_: does anyone here run spacemacs? if so, i'd love help setting up paredit/similar

12:36 BinaryResult_: Hey everyone, in case you hadn't heard Disco Melee is currently searching for remote full-stack clojure devs https://docs.google.com/document/d/1AZNGw7QaoN7jY8MjwpxcKcTTwqjUM7q--2W3aRM36yI/edit?usp=sharing

12:37 if you have any questions let us know at work@discomelee.com. you can also check us out at http://beta.discomelee.com/#landing

12:48 kungi: Suppose a datomic schema with a cardinality/many attribute of type string (lets say NAMES). I would like to find all the entity where an entry in NAMES starts with "foo". How can I get the individual NAMES entries in a subsequent where clause?

12:50 chouser: Is there any value gained in using an immutable map (over a mutable one) when some of the "values" in the map are themselves mutable (eg. an atom)?

12:56 kungi: (take 20 (d/q '[:find ?zip :where [_ :account/zips ?zip] [(.startsWith (.toString ?zip) 0)]] (d/db CONN)))

12:56 CompilerException java.lang.RuntimeException: Unable to resolve symbol: ?zip in this context

12:57 Why does this yeild an exception when :account/zips is a cardinality many attribute?

12:58 => Because you cannot nest function calls in a where cluse

12:58 clause m(

13:00 justin_smith: chouser: if the map was used as a key in another map, the hash-code would not be changed by updating the contents of the atom

13:00 chouser: and of course you lose the nice guarantees that tend to come with defaults in clojure

13:01 chouser: I guess one example to use to think about the problems is (atom {:foo 1 :bar 2}) vs {:foo 1 :bar (atom 2)}, though I mean my question to be broader than that.

13:02 justin_smith: oh, I thought you meant like a java.util.HashMap or something

13:02 chouser: But in that example, what are the benefits of the latter that outweigh its costs.

13:03 kwladyka: is a better way to write this?

13:03 (-> (partial (fn [boards-pool board] (conj boards-pool (rotate-90-board [cols rows] board))))

13:03 (reduce boards boards))

13:03 this function takes boards and add to this boards 90 degree boards

13:03 justin_smith: kwladyka: I'd use let to name that partial

13:04 instead of passing it forward with ->

13:04 kwladyka: justin_smith, but what with (reduce boards boards)?

13:04 justin_smith: kwladyka: (reduce <name you gave the function> boards boards)

13:05 kwladyka: justin_smith, i know but i am repeating boards twice

13:05 justin_smith: kwladyka: also, how is (partial f) different from (f) in your example?

13:05 kwladyka: if you need to repeat it twice, repeat it twice, what's wrong with that?

13:06 kwladyka: look at full defn, do you think "let" has sense?

13:06 (defn rotate-90-boards [[cols rows] boards]

13:06 (if (= cols rows)

13:06 (-> (partial (fn [boards-pool board] (conj boards-pool (rotate-90-board [cols rows] board))))

13:06 (reduce boards boards))

13:06 boards))

13:06 justin_smith: don't do that

13:06 mistaBIZ: curious why you repeat it twice? (for educational purposes)

13:06 kwladyka: justin_smith, i dont know what's wrong, maybe is better function for that

13:07 mistaBIZ, because i am increasing pool of boards about boards rotated by 90 degree

13:07 justin_smith: kwladyka: don't paste multi line functions, use a gist or refheap or something

13:07 kwladyka: so i am starting with the same pool, but only add something new there

13:07 justin_smith, sorry

13:07 justin_smith: kwladyka: what I am saying is that for any f (partial f) should behave the same as f because you are not providing any args to the partial

13:08 only use partial for (partial f x) if you have some x to provide there

13:09 kwladyka: justin_smith, mmm ?

13:11 amalloy: ,((comp partial partial partial partial) 5)

13:11 clojurebot: 5

13:11 justin_smith: kwladyka: (defn rotate-90-boards [[cols rows] boards] (let [f (fn [boards-pool board] (conj boards-pool (rotate-90-board [cols rows] board)))] (if (= cols rows) (reduce f boards boards) boards)))

13:11 mistaBIZ: where x is the evaluated (f) of f?

13:11 justin_smith: mistaBIZ: where x is some arg partially applied to f

13:11 mistaBIZ: my point is that (partial f) for any f is silly

13:11 it's just noise

13:12 (partial f x) (or more args) is actually useful

13:12 kwladyka: justin_smith, so what do you recommend? loop and recur?

13:13 justin_smith: kwladyka: no, just remove partial, it isn't doing anything

13:13 kwladyka: justin_smith, oh.... so true....

13:13 justin_smith: kwladyka: look at what I suggested above - it uses let instead of -> and gets rid of the pointless partial

13:14 kwladyka: justin_smith, now i understand

13:14 justin_smith: kwladyka: you can probably come up with a better name than f

13:16 mistaBIZ: the thing with reduce and repeating boards is that he wants to take boards as the base state for his accumulator, and for each item in boards, also derive a new item to add to that accumulator

13:17 mistaBIZ: at least that would be the normal reason to do that

13:17 you could do the same thing but interleaved rather than appended via mapcat

13:18 akabander: Okay, this is probably a common noob question... I have some code that works in the REPL, but fails to process the sequence when run on the command line (lein run, or from jar)

13:19 justin_smith: akabander: are you using a lazy operation like map or for?

13:19 akabander: This seems to be the offending function:

13:19 Um, yes, map

13:19 http://gitlab.bandersnatch.org/snippets/1

13:19 justin_smith: akabander: if so the repl can force lazy results by printing

13:19 and that will not happen in your jar

13:19 akabander: Ah, but the compiled version can't?

13:19 justin_smith: so use dorun or doall to force the lazy sequence

13:19 akabander: not that it can't, but if you don't do something that forces it, it won't

13:20 akabander: the printing is a side effect of the repl, you need to use something else (dorun or doall) to simulate what it does

13:20 akabander: Aha... I suspected something like that, too green to know all the ins-and-outs.

13:20 justin_smith: or you could just print, I guess

13:20 yeah, that map of println, you could change to (dorun (map ...)) and it would work

13:21 akabander: I do print eventually, but clearly too far along the call chain.

13:21 justin_smith: akabander: it's inside a lazy operation, and the lazy-operation doesn't get forced, and dorun would fix that

13:21 if you needed to use the list later, you could use doall instead of dorun

13:23 akabander: And there we go... Thanks, I'm off to study The Joy Of Closure. Ironically I just started the first chapter that goes into detail on laziness.

13:23 I really appreciate the quality of help around this joint. :^)

13:24 mistaBIZ: agreed

13:24 kwladyka: yes, justin_smith do good job helping all around :)

13:25 birdspider: hello, I'm looking for an easy way to stop play-clj/lwjglapplication killing my REPL when I close the OpenGL window - what should I be googling for ? :)

13:31 justin_smith: birdspider: maybe something like "on-close"

13:41 dumptruckman: anyone familiar with running lazybot in background mode?

13:42 i've got it running with a log file but when i add --background to launch args it doesn't start up properly and logs nothing

13:42 justin_smith: dumptruckman: I've done it before if you have a specific question, but it was a while ago and don't have my bot install handy right now

13:46 dumptruckman: are you doing this via lein, or via an uberjar?

13:46 dumptruckman: uberjar

13:46 i'm not sure how to run it via lein

13:47 justin_smith: so it just does nothing if you start it with the --background arg, it doesn't exit or start up, just hangs there?

13:47 dumptruckman: well, i can see a java process start and then quickly close

13:47 justin_smith: and it's not printing out any error?

13:49 dumptruckman: correct

13:49 justin_smith: return code?

13:50 dumptruckman: none

13:50 or at least, i'm not at a place where i could see one

13:50 justin_smith: you can use "echo $?" to get the value returned by the last command in the terminal

13:51 dumptruckman: eh?

13:51 it returns $?

13:51 (Windows CLI)

13:51 justin_smith: oh, never mind then!

13:52 I'd hazard a guess that lazybot simply cannot run in background mode on windows, I'm somewhat surprised it runs on windows at all

13:52 dumptruckman: i see

13:52 justin_smith: on a *nix machine, you can get the return value of the last command with $?, I have no idea if there is even a concept of a "return value" from a program in windows

13:57 xemdetia: justin_smith, echo Exit Code is %errorlevel%

13:57 you have to use windows vars

13:58 justin_smith: xemdetia: oh, interesting

13:59 jmbroxs: for Clojure web development, is Chestnut a good start for beginners ?

13:59 dumptruckman: exit code is 0

14:00 DifferentLambda: No, jmbroxs

14:00 wasamasa: jmbroxs: hmm, as a beginner I'd start out with piecing the components manually together

14:01 jmbroxs: so, start with ring and boot up a http server

14:01 jmbroxs: add compojure for routing, hiccup for templates, garden for css, etc.

14:02 jmbroxs: Thanks wasamasa. Besides books, are there some really good online tutorials for learning Compojure+Ring+Hiccup+etc. ?

14:03 wasamasa: jmbroxs: the docs, duh :P

14:03 most of these are so simple that you can read the sources for figuring out what's going wrong

14:03 so far the only exception I've run into is this liberator

14:06 jmbroxs: wasamasa, what I meant by online tutorials are videos of people actually writing code and showing the results on a web page

14:06 wasamasa: jmbroxs: hmm, no idea, I don't use video tutorials

14:06 jmbroxs: Oh ok. Thanks anyway wasamasa

14:11 dumptruckman: well

14:12 i guess i'll just use some windows hackery to backgroundify this batch file

15:00 Olajyd: I want an exponential function (it takes a base and an exponent) raises the base to the exponent and limits the answer to 12 characters?

15:04 sorry the question is I want to be able to restrict the exponent to 12 characters

15:05 and not restrict the answer to 12 characters as earlier stated

15:06 amalloy: characters? like you want to allow 2^999999999999 but not 2^1000000000000?

15:13 Chauncey: amalloy: Looks like Olayd just tried to compute that :D

15:45 hehnope: hey everyone, i'm trying to use slurp to read a file (slurp "/proc/cmdline") and its returning with "IOException Invalid argument java.io.FileInputStream.available (FileInputStream.java:-2)" any idea why?

15:46 awwaiid: hmm

15:47 hehnope: this works though (slurp (java.io.FileReader. "/proc/cmdline"))

15:49 awwaiid: looks like proc is special maybe -- https://bugs.openjdk.java.net/browse/JDK-7132461

15:50 if you want a hack, you could maybe read the results of `cat /proc/cmdline`

15:52 hehnope: (use '[clojure.java.shell :only [sh]]) (:out (sh "cat" "/proc/cmdline"))

15:54 hehnope: ye ait looks like its not going to be fixed either

15:54 "This function is not used in jdk8 or 9, we're not going to backport a fix. Closing as not an issue "

15:55 awwaiid: tell me if the sh hack works :)

15:56 hehnope: awaaiid: yea it works

16:31 awwaiid: suweet

16:31 kwladyka: How to Clojure show data instead clojure.lang.LazySeq@cf55badd https://www.refheap.com/84e2274119b25dab46745dcd6

16:32 gfredericks: so let's say you like multimethods generally but you like how protocols group "methods" together

16:32 is there any reason you wouldn't want to use a library with a couple helper macros, defmultis & defmethods?

16:32 presumably the group would share a dispatch function

16:34 justin_smith: I wouldn't use it if you named it uber

16:37 gfredericks: no worries there

16:37 I wonder if there's any way to implement reify for such a thing

16:38 justin_smith: NDXOXCHWDRGHDXORVI is a good name for something if not that lib http://www.dailymail.co.uk/sciencetech/article-3187667/Can-solve-riddle-NDXOXCHWDRGHDXORVI-British-Library-appeals-help-cracking-code-carved-medieval-double-edged-sword.html

16:39 gfredericks: reify for the dispatch, or for grouping the multimethods?

16:39 gfredericks: I'm not entirely opposed to using that name

16:39 justin_smith: I was thinking for creating an anonymous type that implements the multimethod, but now that I say it outloud that only makes sense for type-based dispatch

16:40 kwladyka: prn?

16:42 kwladyka: gfredericks, thx

16:44 gfredericks: kwladyka: also pr-str if you wanted a string

16:45 kwladyka: gfredericks, "even square board " 4 "x" 4 " pieces: " (:queen :rook :rook :bishop :bishop :king :king :knight) <- how to do that without "?

16:45 (pr-str "even square board " size "x" size " pieces: " pieces)

16:46 justin_smith: kwladyka: (println "even square board " 4 "x" 4 " pieces: " (pr-str coll))

16:46 where coll is the thing with the keywords in it, of course

16:47 kwladyka: justin_smith, no one function for that? (str "even square board " size "x" size " pieces: " (pr-str pieces)) <- is it the best one?

16:47 justin_smith: wait, did you want the string or to print something?

16:47 there's also format I guess

16:47 kwladyka: justin_smith, string

16:48 justin_smith: yeah, then use str / pr-str, or maybe format / pr-str

17:01 kwladyka: i have special functions only for tests and i am using this test only in one test file. Where should i have this functions? In the same file? In another? Where?

17:03 awwaiid: Seems like a helper for a test should be fine to live alongside the test (same file)

17:03 kwladyka: this functions check some heuristic properties of data

17:04 even if functions take more lines then tests ? :)

17:04 just not sure about best practice

17:05 awwaiid: I don't really know about best practice for clojure, but my heuristic probably still applies. If there is a spot where you put lots of these test helpers, esp if more than one test uses them, then it is ok to be separate. otherwise drop that sucker in the test and realize that it IS the test, even if it is split up into helper and assertion

17:05 sdegutis: Can someone make Clojular please.

17:08 Okay has anyone made it yet.

17:17 ,(.parseInt "5")

17:17 clojurebot: #error {\n :cause "No matching field found: parseInt for class java.lang.String"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "No matching field found: parseInt for class java.lang.String"\n :at [clojure.lang.Reflector getInstanceField "Reflector.java" 271]}]\n :trace\n [[clojure.lang.Reflector getInstanceField "Reflector.java" 271]\n [clojure.lang.Reflector invokeNoArgInsta...

17:17 sdegutis: What am I missing?

17:17 Oh.

17:26 ,(Integer/parseInt "5")

17:26 clojurebot: 5

17:27 awwaiid: exactly

17:27 sdegutis: Would make more sense if there was an Interface like ParsableAsInt with .parseInt which String conformed to and then you could just do (.parseInt "5").

17:39 kwladyka: awwaiid, for now i am thinking the same, but file is going to have too many lines i am a little confuse about that

17:54 sdegutis: ,(conj #{} :foo)

17:54 clojurebot: #{:foo}

17:54 sdegutis: ,(assoc #{} :foo nil)

17:54 clojurebot: #error {\n :cause "clojure.lang.PersistentHashSet cannot be cast to clojure.lang.Associative"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.lang.PersistentHashSet cannot be cast to clojure.lang.Associative"\n :at [clojure.lang.RT assoc "RT.java" 785]}]\n :trace\n [[clojure.lang.RT assoc "RT.java" 785]\n [clojure.core$assoc__4130 invokeStatic "core.clj" 191]\n [clojure.cor...

17:58 puredanger: you should really use (Integer/valueOf "5") - that gives you the boxed (cached) value and Clojure is going to box the primitive return from parseInt anyways.

18:01 sdegutis: puredanger: Cool good to know.

18:02 puredanger: top Google result says to use (Integer. s) instead... you might wanna post your answer there

18:03 puredanger: oh, I wrote my piece on this years ago http://tech.puredanger.com/2007/02/01/valueof/

18:03 celwell: Hi, how can I use java interop in a (comp)? (comp .getTime :timestamp) is "unable to resolve symbol"

18:03 puredanger: (comp #(.getTime %) :timestamp)

18:03 Java methods aren't functions, but you can wrap them into one

18:04 celwell: thanks, that's not very pretty, oh well

18:06 sdegutis: puredanger: nobody reads anything except what's on stackoverflow

18:07 puredanger: so that's the place to post it

18:13 amalloy: puredanger: that article doesn't seem relevant to the difference between parseInt and valueOf

18:14 you get the same cached value either way

18:14 if you were arguing against (Integer. "5"), as your article does, i would agree

19:18 sdegutis: O snap, amalloy just outClojure'd puredanger

19:46 simoin1234: Hi there! I want to use the clojure.doc function from inside my program. The thing is, if I give it a Var it does not work, I guess this is because doc is macro. But how can I use doc then?

19:50 devn: Could someone help me out with understanding a docstring:

19:50 ,(doc iterator-seq)

19:50 clojurebot: "([iter]); Returns a seq on a java.util.Iterator. Note that most collections providing iterators implement Iterable and thus support seq directly. Seqs cache values, thus iterator-seq should not be used on any iterator that repeatedly returns the same mutable object."

19:51 devn: That last bit: "*repeatedly* returns the "same" _mutable_ object"

19:53 simoin1234: Ho don't worry for my question I use the private function in clojure.repl passing meta to it. That's working.

19:53 devn: I have a KafkaStream that I am doing: (doseq [message (iterator-seq (.iterator stream))] ...) on

19:55 simoin1234: By the way I have another minor question, is there any way to write a multiline string indented for readability purpose but whose value gets rid of the indent (trimmed)? I guess you have to do this by hand right, there is no special reader macro?

19:55 devn: A) What does 'same' mean, when talking about a mutable object? Like, the identical object?

19:57 B) RE: Caching values. I'm not sure this is what I want. Once I've read a value from the iterator, I'd like to discard it, not cache it.

19:58 but, I am not sure how to go about investigating whether or not KafkaStream fits the criteria of A. Any help would be welcome.

20:02 amalloy: devn: it is talking about some really badly-behaved classes whose iterator just constructs a single entry, and then every time you call .next it mutates that entry and gives it back to you

20:02 devn: Like, if you were to read that docstring above for iterator-seq, would you say (iterator-seq (.iterator (.keySet (System/getProperties)))) fits the bill?

20:02 amalloy: i can't remember off the top of my head an example in the jdk that does that. some kind of map type in its entrySet as i recall

20:03 devn: amalloy: how's your scala? wanna look at a kafka.consumer.KafkaStream? ;)

20:03 amalloy: kafka's stream implementation is reasonably well-behaved

20:04 you shouldn't have any trouble treating it as an iterable

20:04 but iterator-seq of .iterator is bonkers: just seq over the .keySet itself

20:04 devn: That's sort of what I expected. Really appreciate you adding some color on that docstring.

20:04 amalloy: yeah, that's a bad example

20:05 (seq a-kafka-stream) doesn't work

20:05 without that chain

20:05 by which i mean: (iterator-seq (.iterator a-kafka-stream))

20:07 amalloy: one more for you: https://github.com/pingles/clj-kafka/blob/master/src/clj_kafka/consumer/zk.clj#L71

20:07 amalloy: i don't think that's true

20:07 devn: http://stackoverflow.com/a/5455903/625403 is an example of the kind of evil iterator it is warning about

20:08 devn: I've managed to give myself an OOME using that that messages function, and I think there's something about the way that lazy-seq is being constructed that I'm missing

20:09 (loop [msgs (zk/messages consumer "foo-topic")] (do something with (first msgs)) (recur (rest msgs)))

20:11 which is really why i'm here in the first place -- some tests i've been writing are a lot easier if I can treat the messages as a lazy-seq instead of running kafka, zookeeper, constructing a message steam, etc.

20:12 amalloy: oh, wow. puredanger: what is the deal with c47e1bbc? chunking everything that gets seq'd sounds like a serious change that would break any programs that want to work with another language's lazy stuff

20:12 devn: so, after an OOME happened, and i found the culprit to be related to the use of that messages function, i switched over to just calling (.iterator stream), recuring with the iterator after doing what I needed to do on (.next thing)

20:12 amalloy: er, link at https://github.com/clojure/clojure/commit/c47e1bbc

20:13 devn: amalloy: i was wondering the very same thing about that chunkIteratorSeq

20:13 amalloy: devn: it looks like iterator-seq was changed to be automatically chunked as of this march, which means you can't really use it to walk over a collection that isn't yet all realized

20:15 devn: amalloy: hmm, im not sure i follow

20:15 why must it be all realized?

20:15 since it will be chunked, you mean?

20:16 amalloy: devn: so, the .hasNext function on a kafka iterator blocks until it either gets a new item from the server, or gets shut down (so there will be no new items)

20:16 devn: yes, i have this running in a go-loop

20:16 (just FWIW)

20:16 amalloy: which means that the chunked iterator's attempt to bundle the first 32 items into a chunkedcons will return nothing at all until 32 items are available

20:18 devn: !!!

20:19 my god am I glad I came in here and asked

20:19 amalloy: just tested that, and you're absolutely right

20:19 i've been hammering this thing with input, and didn't notice the 32 element threshold

20:21 amalloy: so, you mentioned that you think i'm blowing smoke on (doseq [msg (iterator-seq (.iterator stream))] ...)

20:22 i think i may just be misunderstanding what you're suggesting

20:22 in the case that i dont call iterator-seq, are you expecting me to call .hasNext and .next myself?

20:22 amalloy: no. you just call seq

20:23 or let doseq do it for you: (doseq [msg stream] ...)

20:24 devn: hm, i could swear i tried that, but let me give it a go

20:27 amalloy: now im not sure if it's kafka that's batching

20:27 :D

20:28 it wasn't responding to a message at a time, granted those were tiny messages

20:28 justin_smith: devn: you can set it's buffering size, I cut the default by 1000x and got good latency

20:29 like the config file had a default buffer of 4410000 and I changed it to 44100

20:29 which is obviously the right choice because duh

20:30 devn: 32 is the magic number again

20:30 which makes me a little nervous, since the messages i was sending were like 100k

20:30 scratch that, 72k

20:31 justin_smith: that's still small enough that the default buffering is going to cause weird behaviors if you expect any kind of reasonable response time

20:31 devn: kafka is a strange beast, i must say

20:32 justin_smith: very powerful though

20:32 devn: agreed, just wish there was a training wheels version, because there are /so many/ options

20:33 justin_smith: i suppose this conversation is now bleeding into #apache-kafka

20:33 got a second?

20:33 justin_smith: devn: sure, 'sup?

20:33 devn: check #apache-kafka

21:12 Seylerius: Are there any systems LISPs that can compare favorably with Clojure? Racket seems to try, but doesn't seem to get the data structures nearly as right as Clojure does, from what I'm reading.

21:37 justin_smith: ,(apply str (mapcat (partial map (comp char (partial + 77))) (interpose [11] [[1 -9] [2] [-10 -5 10 -9 5 -6 -5 -9] [2 5 9 -4]])))

21:37 clojurebot: "NDXOXCHWDRGHDXORVI"

21:37 justin_smith: that's today's magic word, btw

21:37 devn: Seylerius: in what sense?

21:38 Seylerius: I mean, compare how? You mentioned data structures, but there's a lot more to it than just that.

21:40 Seylerius: You're right, there are more things. Clojure's just a lot more... fluid to program in. The layout, the standard library, the syntax, it all just feels cleaner to me than other lisps. The nature of the data structures leaves the language feeling more sensible to me. The JVM's a mixed blessing, though, and the language can't really be used for systems programming, since you can't compile all the way down to machine-code.

22:04 namra: greetings, i have a set with keywords, and a keyword looks something like this: :Android/d8:50:e6:7f:52:ae/APAasdfasgd

22:04 but now i want to turn that into a string, thus i use the name procedure

22:04 justin_smith: I don't think that's a valid keyword - not a valid keyword literal at least

22:05 namra: but this returns a string where "Android/" is missing

22:05 justin_smith: ,(namespace :Android/d8:50:e6:7f:52:ae/APAasdfasgd)

22:05 clojurebot: "Android"

22:05 namra: ah i see

22:05 justin_smith: ,(name :Android/d8:50:e6:7f:52:ae/APAasdfasgd)

22:05 clojurebot: "d8:50:e6:7f:52:ae/APAasdfasgd"

22:06 justin_smith: it's a weird keyword, I did not expect the reader to accept it

22:06 namra: was kinda ignorant, didn't ask how those ids will look like

22:06 and to avoid duplicates and to make removing of them easier i went for a set with keywords

22:07 amalloy: justin_smith: little known fact: the reader accepts just about any old junk

22:07 justin_smith: I guess it works

22:07 amalloy: haha

22:07 ,(keyword "this should not be news to me")

22:07 clojurebot: :this should not be news to me

22:07 amalloy: namra: why do you have this keyword at all?

22:08 it clearly is not something you typed into your source code, so i presume you read a string from some external source at runtime. just leave it as a string; it's clearly not good keyword material

22:08 namra: amalloy: because as i said above, prio to implementing it that way i didn't know how the possible ids would look like that go into the set

22:08 amalloy: you don't really need to know that. strings that come from outside your application are bad candidates for keywords

22:09 namra: because (disj (:devices user) (keyword device-id)) is so short ^^

22:09 amalloy: even if it were just a nice easy string like "Android-5" you'd want to leave it as a string

22:09 not as short as (disj (:devices user) device-id)!

22:09 namra: that'll work with string?

22:09 justin_smith: yes

22:09 namra: :/

22:09 amalloy: yes, that is what i am trying to tell you

22:09 justin_smith: strings are equal by value

22:09 namra: thanks alot guys

22:09 amalloy: clojure's data structures contain objects of any sort

22:09 justin_smith: :)

22:15 amalloy: but coming from some other languages you might not expect strings to have value equality

22:19 puredanger: amalloy: re your earlier question - you are already at risk of this when you use potentially it in combination with any lazy sequence transformation (like map, filter, etc). Programs that rely on the number of elements computed "ahead" for any lazy seq operation are inherently fragile. If you want more control, it's easy to do so with your own lazy-seq,

22:19 loop-recur, or any transducing function (which defers processing till the point where it's needed).

22:49 reutermj: How do you type hint a string array?

22:50 justin_smith: ,(type (into-array ["a"]))

22:50 clojurebot: [Ljava.lang.String;

22:50 justin_smith: "[Ljava.lang.String;"

22:51 you can use the string instead of the usual symbol

22:52 of course you can't use it outside a string because the reader would hate it

22:58 Seylerius: Interesting... Anyone seen clojure-scheme (https://github.com/takeoutweight/clojure-scheme)? It seems to be a decent way of making one's way down to bare metal from Clojure, which might be a way around my irritation with existing systems-lisps.

22:58 reutermj: Alright, I'm still a little confused on how to use that in java interop code

22:59 justin_smith: (defn foo [^"[Ljava.lang.String;" bar] ...)

22:59 foo now expects an array of string called bar as its arg

23:00 reutermj: ok thanks

23:07 binjured: when writing a macro that takes a class or function as an argument, how can i ensure the resulting code is ns-qualified?

23:13 gfredericks: um

23:13 binjured: it doesn't normally need to be

23:13 binjured: do you have a specific example where you think that's necessary?

23:15 binjured: gfredericks: yeah, i know. what i'm trying to do specifically is write a macro that takes a class as an argument, then imports something in the same namespace as that class. however, if i call the macro like (some-macro Foo) instead of (some-macro bar.baz.Foo), i haven't figured out how to get the FQNS from within the macro.

23:17 gfredericks: ,(resolve 'Long)

23:17 clojurebot: java.lang.Long

23:17 gfredericks: ,(type (resolve 'Long))

23:17 clojurebot: java.lang.Class

23:17 gfredericks: ,(type (resolve 'first))

23:17 clojurebot: clojure.lang.Var

23:18 justin_smith: ,(nth (iterate resolve resolve) 1000)

23:18 clojurebot: #error {\n :cause "clojure.core$resolve cannot be cast to clojure.lang.Symbol"\n :via\n [{:type java.lang.ClassCastException\n :message "clojure.core$resolve cannot be cast to clojure.lang.Symbol"\n :at [clojure.core$ns_resolve invokeStatic "core.clj" 4218]}]\n :trace\n [[clojure.core$ns_resolve invokeStatic "core.clj" 4218]\n [clojure.core$ns_resolve invokeStatic "core.clj" 4208]\n [clojure...

23:18 gfredericks: ^ I think that'll do what you want

23:18 justin_smith: :(

23:18 binjured: ah, cool. thanks!

23:21 justin_smith: ,(nth (iterate (comp resolve :name meta) #'resolve) 1000000)

23:21 clojurebot: #'clojure.core/resolve

23:23 DeltaLambda: That's one way to implement identity on vars

23:24 justin_smith: DeltaLambda: there's a bunch of amazing ones in clojure

23:24 ,(def id (partial get get get))

23:24 clojurebot: #'sandbox/id

23:24 justin_smith: ,(id 42)

23:24 clojurebot: 42

23:24 justin_smith: ,(id id)

23:24 clojurebot: #object[clojure.core$partial$fn__4517 0x6dcdad6b "clojure.core$partial$fn__4517@6dcdad6b"]

23:24 justin_smith: ,(id 'YOLO)

23:24 clojurebot: YOLO

23:25 DeltaLambda: Interesting

23:25 binjured: is there a less janky way of turning the result of (resolve 'Thing) into a string than (str) and removing the "class" prefix?

23:25 DeltaLambda: . getName

23:26 justin_smith: DeltaLambda: any instance of of the function get can be replaced by (get get get get) without changing the meaning of the program

23:26 binjured: excellent

23:26 justin_smith: the rule can even be applied recursively

23:26 DeltaLambda: I'll begin doing so

23:27 binjured: hahah

23:28 justin_smith: gfredericks: free slide for you if you plan on doing a transducers talk some time https://i.imgur.com/uKoNV3G.jpg

23:28 well I mean anyone could use it

23:28 DeltaLambda: ,(get get get (get get get get))

23:28 clojurebot: #object[clojure.core$get 0x3da99244 "clojure.core$get@3da99244"]

23:30 justin_smith: ,((get get get (get get get get)) {:a 42} :a)

23:30 clojurebot: 42

23:31 DeltaLambda: All the gets

23:42 TEttinger: ,((get get get (get get get get)) {get 42} get)

23:42 clojurebot: 42

23:42 justin_smith: even better

23:44 rhg135: ,((get get get (get get get get)) {get get} get)

23:44 clojurebot: #object[clojure.core$get 0x2f5ba1ff "clojure.core$get@2f5ba1ff"]

23:44 justin_smith: it's like that movie, being john malkovitch

23:44 but with clojure.core/get

23:44 TEttinger: ,((get get get (get get get get)) {"get" get} get "get")

23:44 clojurebot: "get"

23:45 justin_smith: (the phenomenon is called "semantic saturation")

23:45 getjure - new dialect of clojure, where the only function allowed is get?

23:46 rhg135: ,((get get get get) (get get get get) (get get get get) (get get get get))

23:46 clojurebot: #object[clojure.core$get 0x2f5ba1ff "clojure.core$get@2f5ba1ff"]

23:47 rhg135: Good way to break some brains, justin_smith

23:47 That and swearjure

23:50 amalloy: all this ((get get get get) (get get get get) (get get get get) (get get get get)) stuff feels like it ought to be sung, to the tune of https://youtu.be/drVYvZ2cqHQ?t=33

23:53 rhg135: Get get get, get get get, get your get

Logging service provided by n01se.net