#clojure logs

2014-10-27

01:14sm0kehello in java.jdbc there is a db/query method to fetch whole result set is there a better way to do this?
01:14sm0kesoemthing like a query-seq?
01:15sm0kewhich could be operated upon lazily
01:16sm0keoops there is a result-set-seq!
01:31justin_smithsm0ke: the lazy stuff breaks if you try to realize it outside the transaction context
01:32justin_smithbut it does work
01:33sm0kejustin_smith: i dont understand
01:34sm0kei just want a seq over result as maps, how do i do that?
01:34sm0kelazy seq
01:35sm0kei see that internally query uses result-set-seq so i am more confused now
01:35justin_smithsm0ke: just make sure you realize as much of it as you are going to use before exiting the scope where you acquire the results
01:35justin_smithsm0ke: if you just pass the lazy-seq out and then try to access elements later, you get an error because you aren't in the scope where the connection to the db exists any more
01:36sm0keyes that is true, but i dont think it is still lazy
01:36justin_smithsm0ke: the advantage is that means you can determine lazily when you have enough data and stop without needing to wait for the rest to transfer - but it can lead to unintuitive errors if you use it wrong
01:36sm0keby default :result-set-fn is doall
01:36justin_smithsm0ke: ahh yeah, but you can change that to actually be lazy
01:37justin_smithif you actually wanted the lazy part
01:37sm0keso setting it to identity should be enough?
01:38justin_smithI think so
01:42oskarkvStyle sheets are cached in JavaFX, and are not reloaded if I don't restart the repl. Does anyone know of a way to fix this?
01:48m00nlightDoes struct save memory than ordinary map structure ?
02:14dysfunm00nlight: don't look at it in those terms. do you want polymorphism? use a record. else use a map
02:14dysfununless you have funky requirements
02:14dysfunthere's a really good diagram of which abstraction to pick, let me find it
02:15dysfunhttps://github.com/cemerick/clojure-type-selection-flowchart
03:14m00nlightdysfun: thanks very much
03:20dysfunyw
03:24dysfunoskarkv: which bindings are you using?
03:26dysfunif it's just raw JavaFX you can do something like (-> my-pane .getStylesheets (.add "styles.css"))
03:26dysfuner with a .clear in there as well
04:00oskarkvdysfun does not work. And it would be strange if it did: It's a new Pane instance each run.
04:00oskarkvdysfun I'm using plain JavaFx
04:01dysfunhrm, i'm afraid i don't know then
04:01dysfuni stopped using javafx once i realised it couldn't actually do what i wanted it for
04:01oskarkvhehe
04:01oskarkvWhat was that?
04:01dysfuni wanted to manipulate the dom of a webkit control from clojure code without involving javascript or clojurescript
04:02dysfunwell, that was one of the things (and doesn't work because the DOM is made read-only, presumably to simplify implementation)
04:02oskarkvhehe ok
04:03dysfunthe other one, i wanted to buiild a web browser. but you can't swap out engines so you'd have to create lots of WebViews, and you can see how quickly that's going to get tedious
04:11oskarkvdysfun :p i'm just making a game. It's pretty handy to just draw javafx to a texture and then use that inside the game, because otherwise i'd have to make my own gui from scratch :p
04:12oskarkvbtw i can probably just rename the css file to something random, and then load that, tricking the cache P
04:22sm0keok so if i set result-set-fn to something other than doall it causes ResultSetClosed exception
04:22sm0keis there a way to have lazy seq without realizing it immediately?
04:34dysfunoskarkv: yeah, you can just increment a number in a filename i suppose
06:30SagiCZ1sm0ke: isnt that the point of lazy-seqs?
06:55dysfunlaziness and i/o resources don't play terribly lovely together
06:57dysfunyou'll be wanting doseq *somewhere* at least to make sure it doesn't get closed before you've read it all. but at that point, why use laziness at all?
07:02borkdudedysfun I'm not clear on this, but someone mentioned transducers could help here? I would like to hear something about this if it's true
07:03dysfuni haven't gotten around to playing with them yet, so i can't help, sorry
07:03dysfunbut if you have a read, i can probably help you through some of it if you're struggling to understand
07:08borkdudedysfun I understand what transducers do, but not how they help working with resources
07:08borkdudedysfun in the lazy case
07:10SagiCZ1(doc read)
07:10clojurebot"([] [stream] [stream eof-error? eof-value] [stream eof-error? eof-value recursive?]); Reads the next object from stream, which must be an instance of java.io.PushbackReader or some derivee. stream defaults to the current value of *in*. Note that read can execute code (controlled by *read-eval*), and as such should be used only with trusted sources. For data structure interop use clojure.edn/read"
07:11SagiCZ1if read should be used only with trusted sources, what should i use with untrusted source?
07:13SagiCZ1io/reader i guess
07:14dysfunborkdude: i'm reading. gosh, they sound like lazy monads
07:15clgvborkdude: when you'd do file processing via transducer you eliminate the need for a lazy-seq
07:15jonathanjanyone familiar with instaparse?
07:15jonathanji have a tree sgement like [:command "F" "O" "O"]
07:16dysfundamn. i've just realised how this could make some of my code cleaner. so i suppose i'll have to go play
07:16jonathanjif i use (insta/transform {:command str}) then i end up with "FOO" whereas what i'm looking for is [:command "FOO"]
07:17borkdudeclgv the data source for a (sequence xform source), what would that be instead of a lazy seq?
07:19clgvborkdude: well a transducer is a stepwise description, so the step could be "read the next thing from file"
07:19borkdudeclgv the problem with lazy sequences and file resources is that you can't use them within a with-open-file macro for example right?
07:20borkdudeclgv because if use consume elements from outside the macro, the file is closed
07:20clgvborkdude: yes, you have to consume as much of the lazy-seq as you need within the with-open
07:20borkdudeclgv ok, so it doesn't really add any benefit in that area
07:21clgvborkdude: a transducer would also have to work in the context where the file is open. though as far as I read, the opening and closening could be done in steps supported by the transducer
07:22borkdudeclgv what are you reading.
07:23SagiCZ1how do i convert string to number?
07:23SagiCZ1,(Double/parseDouble "1.64")
07:23clojurebot1.64
07:23SagiCZ1more clojury way?
07:23clgvno
07:23clgv,(double "1.64")
07:23clojurebot#<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number>
07:23clgv;)
07:24SagiCZ1okay :)
07:24borkdude(read-string "1.64")
07:25borkdude,(read-string "1.64")
07:25clojurebot1.64
07:25clgvborkdude: I am not sure where I read the finalizing part either the official blog post or on the mailing list
07:25clgvha! right :P
07:26dysfunborkdude: potentially dangerous
07:26clgvthen read-edn ;)
07:27borkdudedysfun clojure.edn/read-string
07:27dysfunalso (binding [*read-eval* false]) if you're going to use read-str
07:27dysfunstill gotta check what you get back afterwards
07:27borkdudedysfun I'm assuming everybody knows I mean that one ;)
07:27dysfuni suspect there are lots of people in this channel who don't
07:28borkdudedysfun they'll learn
07:29dysfunyes, but we prefer them not to learn in production :)
07:29borkdudedysfun production is the best teacher ;)
07:29dysfunthat's definitely true, but it can go quite badly
07:29clojurebotI don't understand.
07:31dysfunnow i think about it, , is presumably reminiscent on 'unquote' in other lisps, but clojure uses ~, so it seems an odd choice, especially considering how often people use commas compared to tildes
07:31borkdudedysfun of course I agree.
07:37SagiCZ1(doc read-string)
07:37clojurebot"([s]); Reads one object from the string s. Note that read-string can execute code (controlled by *read-eval*), and as such should be used only with trusted sources. For data structure interop use clojure.edn/read-string"
07:38SagiCZ1,(read-string "(+ 3 3)")
07:38clojurebot(+ 3 3)
07:43clgv,(-> "(+ 3 3)" read-string eval print)
07:43clojurebot6
07:43clgvrepl yay! ;)
07:44jonathanjis there a shorter way to write: (fn [& args] [:foo (apply str args)]) ?
07:44borkdudejonathanj you could use a minifier
07:44clgvjonathanj: probably not
07:45clgvor do you want something like that: #(vector :foo (apply str %&))
07:45jonathanjhrm
07:46borkdudejonathanj I was kidding btw
07:46clgv,(#(vector :foo (apply str %&)) [:a 1 :b 2])
07:46clojurebot[:foo "[:a 1 :b 2]"]
07:46jonathanj(defn apply-and-tag [tag f] (fn [& args] [tag (apply f args)]))
07:46jonathanjmight work, i guess
07:47jonathanji want an instaparse transformer that retains tags instead of consuming them
07:47clgvthough that result looks strange
07:47clgv,(apply str [:a 1 :b 2])
07:47clojurebot":a1:b2"
07:47clgvah lol ;)
07:47clgv,(#(vector :foo (apply str %&)) :a 1 :b 2)
07:47clojurebot[:foo ":a1:b2"]
07:47jonathanjthanks
07:53jonathanjso instaparse produces trees like [:tag [:another-tag [:foo "FOO"]]]
07:54jonathanjwhat's the easiest way to get the value of the :foo tag?
07:57mbacjonathanj, ((apply hash-map (second (second x))) :foo)
07:57mbacwhere x = [:tag [:another-tag [:foo "FOO"]]]
07:58mbacyou could also just say (second (second (second x)))
07:58mbacbut that's probably not what you had in mind
08:00mbac(reduce (fn [x k] ((apply hash-map x) k)) x [:tag :another-tag :foo])
08:00jonathanjhrm
08:00mbac:P
08:01jonathanjhrm, this is kind of inconvenient to work with
08:02jonathanji wonder if i'm missing something
08:03hyPiRionjonathanj: you can hide instaparse nodes with the <>-syntax I think
08:03jonathanjhyPiRion: yeah, but in this case i don't want to hide them because having them tagged seems like a useful way to pick out something specific, not so?
08:04hyPiRionjonathanj: well, it sort of depends on what you're doing I guess. (for me it was useful)
08:05jonathanjhyPiRion: parsing IRC messages
08:05hyPiRionI used it in conjunction with core.match for pattern matching
08:05jonathanjhyPiRion: do you have an example?
08:05jonathanji'd be interested to see that
08:14clgvcriterium question: are the mean durations in the result map always in seconds?
08:16hyPiRionjonathanj: not here unfortunately. but it'd be something like x = [:tag [:another-tag [:foo "FOO"]]], then (match [x] [[:tag [:another-tag [:foo foo]]]] foo :else :not-found)
08:17hyPiRionnow, if you know all the different permutations à priori (like you'd do for instaparse), using core.match is very succinct
08:37ChazeHi. Does Clojure have "arrows" (http://www.haskell.org/arrows/) in the core namespace somewhere?
08:37dysfunnot in core
08:38Chazesomewhere that ships with clojure?
08:38Chaze(guess that's what i meant)
08:38dysfuncheck the 'functional programming' section here http://www.clojure-toolbox.com/
08:38dysfunno, not in the base distribution. use a third party library
08:38dysfununless there's one in contrib somewhere
08:38dysfunbut those still require installing
08:39ChazeAlright, thanks. Great site
08:40dysfunyeah, it is :)
08:48clgvChaze: btw. it is not automatically a problem if it is a third party library since leiningen makes it pretty easy for you to use those
09:34jonathanjis there a shorter way to write (apply hash-map (apply concat xs))?
09:34zoldarjonathanj: mapcat ?
09:35jonathanjmmm
09:35zoldarumm no
09:35jonathanjxs is like [[:a 1] [:b 2]]
09:36mgaare_(into {} xs) should do it
09:36jonathanjoh, awesome
09:44jonathanjmgaare: thanks
09:44mgaarejonathanj: you're welcome
09:46jonathanjwhat's the convention for naming private variables in a namespace?
09:46jonathanjwell, private values, rather
09:47mgaareuse the ^:private metadata tag, and name it however you want
09:54mavbozojonathanj: follow bbatsov's clojure style guide
09:54mavbozojonathanj: https://github.com/bbatsov/clojure-style-guide#private
09:57stompyjprivate variables?!
09:57stompyjwhats next? interfaces to classes? I thought this was #clojure, not #kingdomofnouns
09:57stompyjjk
10:00mavbozostompyj: chill down. there will always be someone who doesn't know the proper usage of various terminologies
10:00stompyjmavbozo: haha, no, i was legit just messing around. this IRC channel is devoid of the typical pedantic rage that other chans have
10:11mavbozostompyj: haha, it seems that I am in a very tense-serious mood
10:12stompyjhaha, my bad
10:23SagiCZ1btw why dont we have def- ?
10:24BronsaSagiCZ1: because we'd need to have a defmulti-, a defonce-, a defprotocol- etc
10:24BronsaSagiCZ1: just use ^:private, defn- was a bad idea
10:25SagiCZ1Bronsa: seriously?
10:25Bronsayes
10:25SagiCZ1so should i avoid defn- ?
10:25Bronsause it if you want
10:25SagiCZ1,(def x ^:private 6)
10:25clojurebot#<IllegalArgumentException java.lang.IllegalArgumentException: Metadata can only be applied to IMetas>
10:25Bronsa,(def ^:private x 6)
10:25clojurebot#'sandbox/x
10:25SagiCZ1Bronsa: thank you
10:25BronsaSagiCZ1: np
10:28jonathanjhow do i do something like Python's repr() in Clojure?
10:28jonathanji want to examine a string that may include characters line \r or \n
10:28perplexayo, i have (map (partial a) x) and i want to exec first 'a' and then 'b' on each x, would i do (map (comp b a) x) ?
10:29Bronsaperplexa: (partial a) is just a
10:29justin_smithperplexa: do you want to run b on the result of a, or do each in parallel?
10:29perplexaalso (partial) with a 1 param fn is probably pointless ;P
10:29perplexaBronsa: yeah just realised :D
10:29perplexajustin_smith: yeah b on a
10:29Bronsaperplexa: then comp is ok
10:29Bronsa(map (comp - inc) [1 2 3])
10:29Bronsa,(map (comp - inc) [1 2 3])
10:29clojurebot(-2 -3 -4)
10:30Bronsaotoh if you want to run them in parallel you'd want to use juxt
10:30Bronsa,(map (juxt - inc) [1 2 3])
10:30mmeixin the other case (a, and par. b) there would be juxt, as
10:30clojurebot([-1 2] [-2 3] [-3 4])
10:30perplexayeah i have one of those examples myself and tried but
10:30perplexai don't know which order it is
10:30perplexa,map (comp inc (partial + 3)) [1 2 3])
10:30clojurebot#<core$map clojure.core$map@1cf3511>
10:30perplexa,(map (comp inc (partial + 3)) [1 2 3]))
10:30clojurebot(5 6 7)
10:30perplexafirst inc then +?
10:30Bronsaperplexa: no
10:30Bronsaperplexa: right to left
10:30perplexaok ty
10:31Bronsathat's why I used a non commutative example
10:31perplexaoh the - inc was obv.. ;P
10:33mgaarejonathanj: what does repr() do exactly?
10:33perplexa(inc Bronsa)
10:33perplexa,inc Bronsa
10:33clojurebot#<core$inc clojure.core$inc@178fdc3>
10:33perplexanarf
10:33perplexai'll never remember this
10:33hyPiRion(inc Bronsa)
10:34hyPiRionlazybot is dead, long live lazybot
10:34Bronsaperplexa: it was correct the first time, but lazybot is dead
10:34perplexaoh!
10:34perplexaliving up to its name i guess
10:35hyPiRionhard at work
10:35BronsaRaynes: you owe me an inc
10:36daniel__(inc Bronsa)
10:36daniel__,(inc Bronsa)
10:36clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: Bronsa in this context, compiling:(NO_SOURCE_PATH:0:0)>
10:37BronsaI'm undefined
10:38mgaareBronsa: according to Joseph Heller, we all have to start ignoring you now
10:39stompyj(inc mgaare)
10:40jonathanjmgaare: for a string it produces an escaped string
10:41jonathanjrepr("\r") -> "\\r"
10:43mavbozo`jonathanj: that's wrong. should be
10:43mavbozo`repr("\r") -> "'\\r'"
10:44jonathanjerr, yes sorry
10:46mgaarejonathanj: not aware of a core clojure function that does that. pprint ignores newlines. you could also do something using clojure.string/replace
10:47SagiCZ1is there a way to have clojure.pprint required no matter what namespace is currently set in the repl?
10:47mgaarewith :inject in lein, perhaps
10:48mgaareer, :injections
10:49mgaarein fact that's the default usage example for it - https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L242
10:50SagiCZ1it says "Forms to prepend to every form that is evaluated inside your project."
10:50SagiCZ1isnt that unecessary?
10:51mgaareit's not something you'd want to do in your production profile, to be sure
10:51SagiCZ1mgaare: makes sense
10:51andyf_jonathanj: Maybe clojure.string/re-quote-replacement is something like what you?re looking for? I should go read what Python?s repr() does first, though.
10:52mavbozo`jonathanj: do you want to use the escaped string in a regex expression?
10:52perplexabtw, is aot broken in lein 2.5?
10:53andyf_jonathanj: Python?s repr() has many options for limiting the length and/or nesting depth of large Python objects. This is similar to (binding [*print-level* 7 *print-length* 10] (clojure.pprint/pprint value)) in Clojure
10:54perplexacoworker said sth like that and reverted to a previous lein version, just curious if anybody has experienced any issues
10:55mmeixplaying with music structures in clojure... having the strong feeling, that this: https://www.refheap.com/92362 could be done shorter, but not sure how - anybody have a look?
10:57jonathanjmavbozo`: no, i just want to inspect a string
10:59SagiCZ1can i simplify (or (= x 5) (= x 10)) so that i wouldnt have to repeat x?
10:59andyf_jonathanj: I don?t know of any built-in Clojure function that limits the size of printed strings like Python?s repr() does, though.
11:01gfredericksSagiCZ1: in this case (#{5 10} x) would work
11:03hyPiRionSagiCZ1: (not (distinct? 5 10 x))
11:11SagiCZ1gfredericks, hyPiRion thanks
11:14bostonaholicmmeix: be careful with that implementation. (map notes (series 15)) will cause infinite recursion
11:16mmeixah ...
11:17mmeixin the mean time I found (some #{x} coll) to test for repetitions, just a bit shorter than my first try
11:18mmeixbostonaholic thanks
11:19bostonaholicmmeix: but that's a cool idea. you could then do similar randomness of quarter, eighth, etc. to create some pretty interesting improv solos
11:20mmeixof course
11:20bostonaholicjust play that through my speakers all day, on a blues scale
11:20mmeixthis is just getting to grips with clojure
11:20jeffterrelljonathanj: Try (pr-str)
11:20jeffterrell,(pr-str "\r")
11:20clojurebot"\"\\r\""
11:20jonathanjthanks, that's probably sufficient
11:21justin_smith,(shuffle ["c" "c#" "d" "d#" "e" "f" "f#" "g" "g#" "a" "a#" "b"]) mmeix
11:21clojurebot["g#" "a#" "e" "d" "d#" ...]
11:21justin_smithmmeix: your intention is a random permutation of a fixed set, right?
11:22mmeixnot quite
11:22patrkrishi everybody. is there some way to have clojure.java.jdbc always replace undercores with hyphens in the field names of result sets?
11:22mmeixthis is just a beginning
11:22justin_smithmmeix: (take n (shuffle ["c" "c#" "d" "d#" "e" "f" "f#" "g" "g#" "a" "a#" "b"]))
11:22justin_smithto answer your "can this be done shorter" question
11:23SagiCZ1im using io/reader to read a huge text file and i would like to skip the first half of lines for example, is that possible?
11:23mmeixthere will be many methods to build more structurally anchored things, a random dodecaphonic series is just the most primitive example ...
11:23justin_smithmmeix: sure, just addressing the question in that comment, you are doing shuffle
11:23mmeixof course! I had forgotten about shuffle - thank
11:24mmeixthis makes it much shorter :-)
11:25mmeixI'm thinking about a more functional version of something like http://web.mit.edu/music21/
11:26mmeixwhich is great somehow, but overflows with classes and supers and subs ...
11:26mmeixthis has to be done much more simple, functional
11:26mmeixI think
11:27mmeix[thus learning Clojure like crazy ;)]
11:28SagiCZ1what is the goto benchmarking tool for clojure? or something that looks for hotspots? like which function is called the most
11:28mmeixjustin-smith apologies & thanks!
11:29patrkrisSagiCZ1: YourKit and JVisualVM seems to be popular choices
11:29patrkris*seem
11:29SagiCZ1patrkris: JVisualVM is not clojure related though? its general jvm?
11:29patrkrisSagiCZ1: I think you are right, yes
11:30patrkrisI don't think there is anything specifically suited for Clojure
11:30SagiCZ1patrkris: ok i will try to use that
11:30stuartsierraYou need a JVM-level tool to get worthwhile performance metrics.
11:30mavbozopatrkris: put your converter function in :identifiers arguments in clojure.java.jdbc/query function, default lower-case
11:30stuartsierraEven then it's like voodoo.
11:30mavbozopatrkris: http://clojure.github.io/java.jdbc/#clojure.java.jdbc/query
11:30mavbozo
11:30patrkrismavbozo: yeah, but I have to do that everywhere I call query, right?
11:31mavbozopatrkris: yeah, but we have macros
11:31patrkriswe do :)
11:34mavbozopatrkris: and robert-hooke :p https://github.com/technomancy/robert-hooke/
11:35SagiCZ1thats interesting, according to jvisualvm the most called function is clojure.lang.RT.next()
11:39justin_smithSagiCZ1: well, what's more important than most called is which one it spends the most time calling
11:43SagiCZ1justin_smith: its time as well, but maybe im doing something wrong
11:43mavbozoI often get java.lang.OutOfMemoryError: PermGen space when doing too many (refresh) using org.clojure/tools.namespace
11:44mavbozois it just me? or is anyone else having this kind problem?
11:44stuartsierramavbozo: Which JVM?
11:44mavbozojava version "1.7.0_67"
11:44mavbozoJava(TM) SE Runtime Environment (build 1.7.0_67-b01)
11:44mavbozoJava HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode)
11:45SagiCZ1mavbozo: i've had this problem in a completely different circumstance (jetty hot deploy) but you could try turning permgen garbage collection on
11:45justin_smithmavbozo: 1.8 doesn't even have segregated permgen any more iirc, if upgrading is an option. Or you can just bump up the alloted space for permgen
11:46stuartsierraSagiCZ1, mavbozo: PermGen is GC'd by default.
11:46SagiCZ1stuartsierra, mavbozo: see https://stackoverflow.com/questions/7383658/permgen-space-exception?lq=1
11:46stuartsierraBut you can fill up the space if you're recompiling a large project.
11:46mavbozoSagiCZ1: I just increase increase the -XX:MaxPermSize
11:47stuartsierraI've had to increase the PermGen size for large projects (hundreds of Clojure source files)
11:48mavbozothanks everyone
11:48justin_smithstuartsierra: the top SO answer at that link claims permgen GC is off by default
11:48stuartsierrajustin_smith: I take no responsibility for what StackOverflow says.
11:49justin_smithstuartsierra: OK - I wasn't saying you were wrong, just pointing out the discrepency
11:49mavbozostuartsierra: please add that in Warnings section in https://github.com/clojure/tools.namespace README
11:49stuartsierraOlder JDKs had PermGen GC disabled by default, but not 1.7.
11:49stuartsierramavbozo: I will consider that.
11:49justin_smithstuartsierra: thanks for the clarification. Too bad 1.6 is still such a common deployment target.
11:50stuartsierraI'm not certain if 1.6 has it enabled by default, but I think it does.
11:50stuartsierraMay depend on the vendor.
11:50justin_smithstuartsierra: I had production issues with permgen running out that I never saw locally, and had a 1.7 / 1.6 split, but I never proved that was the cause...
12:34SagiCZ1is both first and next always in constant time?
12:38justin_smithSagiCZ1: they call seq - if seq is always constant time then they are too, but I am not sure if seq is always constant time
12:40dopamean_justin_smith: the other day you mentioned hat i could install a library locally
12:40dopamean_and you said something really simple that i have now forgotten
12:40justin_smithoh, and seq can wrap a java iterable, and that iterable could hypothetically in a pathological case have a non-linear Iterator?
12:40dopamean_originally i wanted to use a library i had written that is not on clojars
12:40justin_smithdopamean_: lein install
12:40dopamean_doh
12:41dopamean_thanks
13:00SagiCZ1,(time (dotimes [_ 10000000] (first (range 5))))
13:00clojureboteval service is offline
13:00SagiCZ1,(+ 5 3)
13:00clojurebot8
13:01SagiCZ1anyways first is dependent on the size of the size of the sequence even though its lazy..... what a bummer why wouldnt first be always constant .. this breaks my performance terribly
13:02hyPiRionSagiCZ1: no, it isn't. It's dependent on the 1-32 first elements, but only if the lazy seq is chunked.
13:02justin_smithwat - how would first be dependent on the size of the sequence?
13:03hyPiRionIt's a bit weird and strange at first, but things are usually chunked unless you do something like (iterate ...) or lazy-seq yourself
13:03SagiCZ1i ran two tests..
13:03SagiCZ1(time (dotimes [_ 10000000] (first (range 50000000000000)))) took 12 seconds
13:03SagiCZ1(time (dotimes [_ 10000000] (first (range 5)))) took 4 seconds
13:04SagiCZ1and it is very consistent on my pc
13:04justin_smithSagiCZ1: (range 50) takes as long as (range 50000000000000)
13:05justin_smithSagiCZ1: it's because of chunking, like hyPiRion said
13:05justin_smithfirst of range realizes the first 32 or so elements
13:06SagiCZ1oh.. i see, sorry
13:06SagiCZ1i didnt get hyPiRion's message at first
13:21rooster_rusis there something like perl's "state" variables in clojure? state variables are basicly kept between function calls. I'm trying to make something like (take-while increases!? coll) where increases!? keeps value of previous call.
13:22rooster_rusalso state variables are lexically scoped within function body
13:23tropicalmugHi all. Does anyone have a library of choice for handling RSS feeds? Handling would mean reading entries, caching state, finding new entries. I've found the Java library ROME, but I'm a little unsure of how that works.
13:28SagiCZ1rooster_rus: i dont think there are state variables but there is always a way of working around that in clojure, maybe iterate or reduce would help you
13:29justin_smithtropicalmug: I have had good luck with https://github.com/yogthos/clj-rss
13:30mmeixI owe justin_smith some incs
13:30justin_smithrooster_rus: you could close over an atom with your function definition, but there is likely a way to realize whatever algorithm you are doing without a state variable
13:30mmeix(inc justin_smith)
13:31justin_smithmmeix: lazybot is out
13:31justin_smiththanks though :)
13:31mmeixI' keep your (repeatedly 5 (inc justin_smith)) for later :-)
13:32justin_smithSagiCZ1: since he is tracking the last argument to the function, that means he is dealing with state and concurrency in a way that reduce or iterate won't really help with - he needs something that manages concurrent access
13:32tropicalmugjustin_smith That looks good for creating feeds, though that isn't my use case
13:32justin_smithrooster_rus: agents are values that manage unsyncronized sequential update, that may help you
13:33justin_smithtropicalmug: oh, you want to consume feeds
13:34justin_smithtropicalmug: I don't know of anything, but given your description I would imagine using clojure.xml to make edn data out of the xml, and an atom to cache and update state
13:34tropicalmugjustin_smith I was hopeful there would just be the go-to Clojure wrapper for Rome, but rolling my own library isn't the end of the world.
13:34tropicalmugThanks!
13:35justin_smithhttps://github.com/scsibug/feedparser-clj this is a ROME wrapper
13:37tropicalmugjustin_smith :-b
13:42justin_smithtropicalmug: it's a pretty thin wrapper, just one namespace
13:49tropicalmugjustin_smith might hack it to support the conditional-get parts of the rome fetcher. Beyond that, it's all I need. Thanks again.
13:56TimMc"eduction", really?
13:57BronsaTimMc: it took me by surprise too
14:01justin_smitheduction?
14:01mmeixa typo for Reducation :-)
14:02gfredericksit took me several seconds not to read "education"
14:04mmeixwe could need an "educate" function in clojure, for misbehaved colls... (educate {3.14 :a 1/3 :b}) :-)
14:07justin_smith,{1.0M 1 1 1 1.0 1}
14:07clojurebot{1.0 1, 1 1, 1.0M 1}
14:09mmeixIs there a better way to extract a number's digits than this: (- (int %) 48) (str 42) - looks like cheating to me...
14:09mmeixsorry: (map #(- (int %) 48) (str n))
14:11Bronsajustin_smith: it's the new name for `iteration`
14:11hashpuppycan someone explain what this does: (defrecord Click [pos] IFn (-invoke [_ state] (click pos state)))
14:12hashpuppyit's in clojurescript
14:12Bronsahashpuppy: it makes your record invokable
14:12dbaschmmeix: see this blog post for a number of ways http://diegobasch.com/life-the-universe-and-technical-interviews
14:12Bronsaso you can do ((Click. foo) 1)
14:13justin_smithBronsa: context?
14:13mmeixdbasch thanks!
14:17TimMcjustin_smith: eduction
14:17chronnojustin_smith: http://clojure.github.io/clojure/branch-master/clojure.core-api.html#clojure.core/eduction
14:19danneuIn Om, you can use `ref` to expose an arbitrary dom node so that you can, for example, focus it in a callback. But how do you do that in Reagent?
14:21Bruce_Wayneanyone ever see when two strings are the same but don’t pass the = test
14:21sg2002assault_ninjaD9ULSuSkji9YPmKbA462
14:21Bruce_Waynebut they do pass the = test after wrapped in a prn
14:21danneuBruce_Wayne: do they pass the == test
14:22Bruce_Wayneis that a thing
14:22Bruce_Wayne?
14:22danneu,(== 1 1.0)
14:22clojurebottrue
14:22Bruce_Waynedanneu: no they don’t because they are strings not numbers
14:23danneuoh, it's just for numbers?
14:23danneui now see "nums" in the docstring, but i recall it being useful in another circumstance
14:24SagiCZ1is there a way to read only last n lines of a file, skipping the lines before?
14:25danneunvm
14:25justin_smithBruce_Wayne: the equal after prn thing is odd, you should take the base64 of their byte-array representation next time
14:25danneuSagiCZ1: line-seq + take-last?
14:26justin_smith,(String. (clojure.data.codec.base64/encode (.getBytes "hello"))) ; Bruce_Wayne
14:26clojurebot#<CompilerException java.lang.ClassNotFoundException: clojure.data.codec.base64, compiling:(NO_SOURCE_PATH:0:0)>
14:26justin_smith,(require 'clojure.data.codec.base64)
14:26clojurebot#<FileNotFoundException java.io.FileNotFoundException: Could not locate clojure/data/codec/base64__init.class or clojure/data/codec/base64.clj on classpath: >
14:26justin_smithhrmph
14:26justin_smith,(require 'clojure.data.codec)
14:26clojurebot#<FileNotFoundException java.io.FileNotFoundException: Could not locate clojure/data/codec__init.class or clojure/data/codec.clj on classpath: >
14:27SagiCZ1danneu: i think take-last still realizes the elements before
14:27justin_smithSagiCZ1: danneu: it definitely does
14:27SagiCZ1i was thinking maybe some magic with interop .seek ... but i have never used it
14:28danneuSagiCZ1: how about http://commons.apache.org/proper/commons-io/apidocs/org/apache/commons/io/input/ReversedLinesFileReader.html
14:28justin_smithSagiCZ1: I think you'll need to use interop to seek on the file stream and move backward past N newlines
14:28justin_smithSagiCZ1: or get the one creating the files to do proper rotation so that file size is more reasonable :)
14:29SagiCZ1danneu: thats pretty wicked actually.. what i really need is to read last lines of some sort of log, so this class could help me a lot
14:29SagiCZ1justin_smith: haha.. or i could rotate them myself with some simple script.. would took hours though
14:33justin_smithSagiCZ1: well, many loggers come with rotating options you can turn on
14:36justin_smithI wish there was an easy way to run two branches of the same project ... I mean yeah I can do a clone but I don't need to replicate the whole git apparatus, just have two branches visible and isolated at once...
14:37SagiCZ1justin_smith: why would you need to clone something if you want to make a branch?
14:37justin_smithSagiCZ1: to have both running at once
14:38justin_smithlooks like I can use git-new-workdir http://nuclearsquid.com/writings/git-new-workdir/
14:38TimMcjustin_smith: If you clone a git repo from one place on disk to another, it uses hardlinks so it takes up less space...
14:38SagiCZ1oh i see.. interesting usage, seems like it would be pretty handy
14:38justin_smithTimMc: oh, great, so it just does the right thing
14:39TimMcIt does mess up your remotes, though. :-P
14:39justin_smithTimMc: that was my concern, was getting two copies of everything in the git history
14:39justin_smithTimMc: ugh
14:39justin_smithmess up as in?
14:39TimMcThe second's only remote is the first.
14:39justin_smithoh, that's fine for my usage
14:39justin_smiththanks man
14:39justin_smith(inc TimMc)
14:40justin_smithRaynes: can we have lazybot back pretty please?
14:41Raynesjustin_smith: One lazybot for you sir.
14:41justin_smith(inc Raynes)
14:41RaynesWell wait a second :P
14:41danneuin the meantime, Raynes is manually reading through the #clojure logs and balancing the inc ledger by hand
14:41justin_smithhehe :)
14:41SagiCZ1danneu: xD
14:41Bronsa(inc TimMc)
14:41SagiCZ1he better!
14:41lazybot⇒ 74
14:41RaynesHah, the amount of shits I gave is way too small for that.
14:42RaynesMy time would be better spent moving lazybot to latest irclj and getting real reconnection support.
14:42Raynes:P
14:42Bronsalazybot: <3
14:42RaynesOr anyone's time, for that matter. Blow off work today and do that for me ^
14:42RaynesI'll give you one (1) cookie.
14:43dbaschthe ledger for the karma currency must be consistent and partition-tolerant
14:43justin_smithdbasch: well there are systems that are not C, A, or P
14:44justin_smith2/3 is the best case, 0/3 is the worst
14:44dbaschor you can be trivially CAP with /dev/null
14:45SagiCZ1dbasch: how do you get the ledger number for someone?
14:45dbasch$karma SagiCZ1
14:45lazybotSagiCZ1 has karma 0.
14:46SagiCZ1dbasch: awww
14:46SagiCZ1thats harsh
14:46dbaschkarma don’t come easy around these parts
14:46mmeix(inc justin_smith)
14:46lazybot⇒ 105
14:47justin_smith(inc stuartsierra)
14:47lazybot⇒ 13
14:47justin_smith(inc TimMc)
14:47lazybot⇒ 75
14:50csd_How do I bind *out* to a file object for use with with-open?
14:51hfaafbwhats the point of ^:const?
14:52sg2002assault_ninjaD9ULSuSkji9YPmKbA462
14:53justin_smithcsd_: (with-open [f (java.io.FileWriter. "tmpfile")] (binding [*out* f] (prn {:a 0 :b 1})))
14:54justin_smithcsd_: but for a simple case like that pr-str / spit is easier
14:54csd_ what about binding StringWriter?
14:55justin_smithcsd_: so do you want with-out-str?
14:55justin_smith,(with-out-str (prn {:a 0 :b 1}))
14:55clojurebot"{:b 1, :a 0}\n"
14:56csd_I want to use clojure.data's write-csv function, but it takes a file object to write to, and I want to work with it in the REPL
14:56justin_smithcsd_: it seems odd that there wouldn't be a version that just handed you the string...
14:57turbofailpretty sure you could just use (write-csv *out* ...)
14:57justin_smithcsd_: it takes a writer, so you can hand it a StringWriter directly as an arg
14:57justin_smithor that if you just want to print, yeah
14:57justin_smith,(class *out*)
14:57clojurebotjava.io.StringWriter
14:58csd_ what file object would i use if i wanted to pass the transformed object in my code?
14:58csd_would StringWriter still work
14:59justin_smithnone of this requires a file
14:59justin_smithit takes a writer
14:59justin_smithcreate a StringWriter and pass it in if you want that
15:01csd_i'll give it a shot, thanks
15:13arrdemso has anyone actually built Philip Lord's [n .. 20] unrolling defn yet?
15:13amalloyarrdem: link?
15:14arrdemamalloy: https://groups.google.com/forum/#!topic/clojure/hnkJb9_il_M
15:15amalloyarrdem: that's been an open problem for years. it turns out to be really hard to write a generic unrollng macro, and if you do then it's actually harder to read code that uses it than it is to read hand-unrolled code
15:17arrdemamalloy: oh I totally believe that. I've been kicking the idea around in my head for a day now and "it's hard" is definitely the conclusion. I'm just wondering whether it'll actually achieve a measurable speedup or not. my intuition is not, unless there is an upper bound on apply argument counts that happens to be N ≤ 20
15:17arrdemor at least a bound on the common case
15:19puredangerold ticket for this: http://dev.clojure.org/jira/browse/CLJ-731
15:20dbaschit would be interesting to crawl all clojure from github and see what things people are doing that could be helped by generic, untargeted optimizations
15:20amalloyarrdem: are we sure that building the list is actually the expensive part like puredanger says? i would have guessed it's the looping, and it doesn't look like the timing stuff in the ticket says *why* the variadic call is more expensive
15:20arrdemamalloy: no idea we'd have to actually start looking at JIT'd code
15:20puredangerI don't really know for sure - feel free to do some perf analysis
15:21arrdemamalloy: my gut agrees with you... I'd think that the looping is more expensive than an array which is 1) created, 2) unpacked and then 3) discarded
15:21Bronsavarargs & apply are both slower than fixed args + direct invoke, no idea what % they individually contribute to
15:21Bronsabut usually they go hand in hand
15:21Bronsaeliminating one usually eliminates the other too
15:21arrdemamalloy: just because that array would seem like an ideal candidate for bytecode elision.
15:22puredangeras Rich would say "why guess when you can measure?
15:22dpetrovicsanyone in here use kioo? (https://github.com/ckirkendall/kioo) Ran into something odd with the do-> chaining transformation
15:22arrdempuredanger: measuring is hard :P
15:22puredangercan't say I've ever seen him take that as an excuse :)
15:27Bronsaautomating unrolling + automating inlining would make reading through core.clj so much easier
15:27Bronsaand probably removing manual chunked-seq handling :P
15:30mmeixas an exercise I built a digits-finder ... wondering, if this could be simplified/ improved: https://www.refheap.com/92381
15:43dbaschmmeix: (defn digits [x] (when (pos? x) (concat (digits (quot x 10)) [(rem x 10)])))
15:43dbaschmmeix: although mine returns nil for 0, yours returns the empty sequence
15:44mmeixstudying your solution ...
15:44dbaschalso mine can be lazyfied trivially
15:44Bronsadbasch: it's easy to fix it though, just change the when to an if and return () on the else branch
15:44mmeixit has no loop
15:45dbaschBronsa: yes, it’s trivial
15:45dbaschit should return 0 anyway :)
15:46mmeixamazing how much shorter experienced clojurists get it, every time ...
15:46sdegutisNever mind, figured it out.
15:47mmeix(inc dbasch)
15:47lazybot⇒ 16
15:49dbasch(btw, not that I see a reason to lazify getting the digits of a number)
15:49arrdemhuh
15:50arrdemamalloy: puredanger: looks like that unrolling is a potentially huge perf win unless my benchmark is crap
15:50arrdemhttps://www.refheap.com/92383
15:51arrdemI see the arity unrolled victim with call site unpacking doing a factor of up to 5 better than the apply invocation
15:51arrdemboth apply invocations are identical
15:51justin_smithmmeix: it's learning and pattern recognition, you eventually learn to recognize the common tasks, and remember how to express them concisely
15:51puredangerarrdem: also need to cross that with frequency of use
15:52mmeixjustin_smith ja, it's getting better (know this from teaching music theory: lots of gestalt recognition...)
15:55arrdemhttps://www.refheap.com/92385 improved benchmark..
15:56arrdemthe call site arity unpacking (basically static call arity determination) looks like the real win here
15:57arrdemmaybe this makes sense to do, but it really comes down to avoiding or rewriting apply with partial evaluation
16:03turbofailthat would be a nice thing to have
16:05turbofaili would like to be able to use `apply' in more places without throwing performance out the window
16:07turbofailthough i wonder how costly that partial evaluation would be in terms of compile time, in order to do it reliably
16:07arrdemeh you quickly wind up needing a really smart partial evaluator or flat out dependent types in order to do static arity determination of apply :/
16:08arrdemit's not expensive, it just requires purity/effect analysis and a bunch of other stuff we don't have
16:08arrdemit's easier to do if you have an interpreter lying around as well..
16:08{blake}I'm using "->" to do a bunch of serial map associations, like "(-> (assoc % :whatever (whatever-func var1)) -> (assoc :next-key (next-func var2))" etc., and trying to figure out how best to handle when the function (whatever-func, next-key-func) returns a nil. Should I just clean the map out after or is there a better way?
16:09turbofailmight be better to have a wrapper around assoc that doesn't do the association if the value is nil
16:10{blake}turbofail, Ah...yeah, I like that. Thanks!
16:10arrdemdon't we have when-> or something that short circuits at the first nil value?
16:10{blake}arrdem, Maaaybe? =P
16:10neatonkhttp://clojuredocs.org/clojure.core/some-%3E
16:10arrdem(inc neatonk)
16:10lazybot⇒ 1
16:10neatonksome->
16:10arrdemthat's the one
16:11{blake}neatonk, arrdem Cool.
16:11turbofaili dunno how well that would fit into this use case though
16:11{blake}Heh, I don't either. Let me try it.
16:17{blake}Ahhh...No, doesn't work because my code is:
16:17SagiCZ1is there a reason why should the speed of execution depend on size of the queue in this example? is that loop terrible? https://www.refheap.com/92392
16:17{blake}(assoc :key (get-val item)) so I've got a ":key nil" map entry.
16:18{blake}If I recode it as (some-> (get-val item)), it'll work of course, but I'm not sure that's an improvement.
16:18{blake}Good to have "some->" in the toolbox, tho'.
16:20ChazeWhat a strange REPL behaviour. (range 1 6622) yields a list as expected. (range 1 6623) yields ()
16:20SagiCZ1,(range 1 6623)
16:20clojurebot(1 2 3 4 5 ...)
16:20SagiCZ1Chaze: try a new repl instance
16:22ChazeSagiCZ1: nope. It works with the latest clojure.jar, but the problem exists in counterclockwise using clojure "1.5.1"
16:22Chaze(in case anyone wants to try to replicate it)
16:23Chazeits not just in the REPL, it also occurs in my code at different cutoffs
16:25SagiCZ1oh, count is O(n) for lists i guess .. thats the problem then
16:25justin_smithSagiCZ1: yeah, and it breaks laziness too
16:26SagiCZ1justin_smith: whenever i try to make a minimal working example i always omit the part which causes the issue thinking its irelevant
16:26arrdemSagiCZ1: I note that your "loop" is really just (nth (iterate c foo) (count queue))
16:26SagiCZ1arrdem: is it? that sounds strange
16:27arrdemSagiCZ1: you have no data dependency between "c" and e/q
16:27SagiCZ1arrdem: yeah i deleted it from the example, sorry to make it confusing
16:28SagiCZ1if i want to just simply loop through a collection i need at least two bindings in the loop form right? the collection and the next element
16:28arrdemsure, but you could write that as (loop [[head & more] col] ...)
16:28SagiCZ1cool
16:29SagiCZ1internaly it would use first and next maybe?
16:29justin_smith,(loop [coll (range 10)] (if (= (count coll) 1) (even? (first coll)) (recur (next coll))))
16:29clojurebotfalse
16:29justin_smitha loop with only one binding
16:29justin_smiththat iterates to the end of the coll
16:29arrdemSagiCZ1: macroexpand tells no lies :D
16:30SagiCZ1justin_smith: okay so one binding is enough, but since i dont want to repeat (first coll) in my code i will go with the [[element & more] coll]
16:31SagiCZ1wait
16:31SagiCZ1isnt the deconstruing done only in the first pass?
16:31justin_smithit's done on every pass
16:31amalloySagiCZ1: i generally don't like using [x & xs] to walk over a sequence. there are a few problems with it
16:32arrdemamalloy: do share. I was not aware of any.
16:32amalloyfirst, you can't even tell when the sequence becomes empty
16:32SagiCZ1,(seq [])
16:32clojurebotnil
16:32amalloyneither x nor xs can tell you that the collection is empty. if xs is nil, then you know there is at most one element in the collection
16:33amalloyif x is nil, you know that either the collection is empty or there's a nil in it
16:33puredangerthere are a lot of cases where I know the latter
16:33SagiCZ1[e & more] .. when more is empty, seq returns nil right?
16:33puredangererr, know that there ins't nil I should say
16:34arrdemSagiCZ1: seq is defined to return nil for empty sequences
16:34arrdemlazybot: good you're still here
16:34amalloyadditionally, there are laziness concerns: if you destructure into [x & xs] and decide that x is the last element of the sequence that you need to look at, too bad: you've already forced one additional element, by asking for xs
16:34arrdem&(macroexpand '(loop [[x & more] [1 2]] 1))
16:34lazybot⇒ (let* [G__11389 [1 2] vec__11390 G__11389 x (clojure.core/nth vec__11390 0 nil) more (clojure.core/nthnext vec__11390 1)] (loop* [G__11389 G__11389] (clojure.core/let [[x & more] G__11389] 1)))
16:36arrdemnot especially helpful..
16:38SagiCZ1amalloy: could you provide me with a better approach with loop then? i am overthinking this too much..
16:38amalloySagiCZ1: just loop over the coll, and call first when you need to, and rest when you need to
16:39amalloyif you want to avoid calling first twice, then let-bind it to save the result
16:39SagiCZ1rest or next?
16:39amalloywellllll, that depends what you're doing
16:39amalloyrest is a better default choice
16:40dbaschSagiCZ1: why don’t you take a step back and explain what you’re trying to do? It’s not at all obvious from your code snippet
16:40SagiCZ1will remember that.. i know the difference is subtle and i cant think of an example where it migh matter
16:40arrdem&(next '())
16:40lazybot⇒ nil
16:40arrdem&(rest '())
16:40lazybot⇒ ()
16:40sdegutisWhy is there de-dupe now instead of changing distinct based on its argument type?
16:41puredangerthey do different things
16:41sdegutisOh.
16:41puredangerde-dupe removes duplicates in a row
16:41sdegutisAlso why is it not called de-duplicate?
16:41puredangerdistinct has to keep track of all "seen" values, which is prob a bad idea on streams
16:41puredangerwho has time for names that long?
16:41puredanger;)
16:41dbaschpuredanger: java :)
16:42sdegutisWe already have "difference"...
16:42amalloypuredanger: i bet we could find a shorter name for 'first, too
16:42sdegutisAnd "denominator".
16:42puredangercar?
16:42sdegutisAnd "descendents".
16:42arrdemlol
16:42puredangeryou're right, I'm going to remove as many chars from all those as possible.
16:43amalloysdegutis: clojure doesn't really have a consistent approach to abbreviations, name styles, whatever
16:43technomancynrplacd
16:43technomancydem vowels ain't free y'know
16:44amalloyyou just kinda roll with it. it's not like de-dupe is objectively better or worse than de-duplicate, or dedupe for that matter
16:44EvanRpeople say de-dupe in real life
16:44puredangerit's actually dedupe
16:45technomancy"unstutter" is the name I've seen
16:45amalloyoh good. de-dupe seemed weird to me
16:45puredangerI think I wrote de-dupe somewhere incorrectly and it's propagated
16:45technomancy(emphasizes it only removes consecutive dupes)
16:45puredangerhttp://clojure.github.io/clojure/branch-master/clojure.core-api.html#clojure.core/dedupe
16:45llasramtechnomancy: Ooh, I like that one
16:46sdegutisThanks.
16:46amalloy(inc unstutter)
16:46lazybot⇒ 1
16:46sdegutisSince I'm stuck using Clojure, might as well use transducers.
16:46puredangerthat's the spirit
16:46SagiCZ1sdegutis: stuck using clojure
16:46SagiCZ1never heard that before
16:48arrdemI suppose unstutter of n probably wouldn't get used that often..
16:59technomancyhttp://lists.gnu.org/archive/html/emacs-devel/2014-10/msg01000.html
16:59technomancy^ in today's tragicomic packaging security news
16:59michhey
16:59michwhat linux distributions are you using here?
17:00llasramDebian 3 eva <3
17:00llasramEr, "4" even
17:00michllasram: do you also run X or something in it?
17:02TimMctechnomancy: :sad-trombone
17:03technomancyTimMC: I don't even
17:03arrdemtechnomancy: can you sneak .elcs into an elpa package?
17:03technomancyit makes a non-tls request on 443 ._.
17:03technomancyarrdem: anything you can imagine is possible at zombomacs
17:04arrdemtechnomancy: good. so we can MITM ELPA serving .elc viri :D
17:04arrdemover "https"
17:08mgaareseems like there a lot of libs around (new ones even) that still use (ns ... (:use ...))
17:08sdegutisBecause it's just so fun.
17:09arrdemmore importantly we have a bunch of tutorials with high Google PageRank scores that use (:use)
17:09sdegutisIf :use works then it's perfectly fine.
17:09amalloy~blogs
17:09justin_smithalso, it's how other languages usually import libs
17:09clojurebotblogs are never to be trusted
17:09sdegutisIf it isn't fine then it should be removed.
17:10sdegutisThis blog is actually quite trustworthy: http://blog.8thlight.com/colin-jones/2010/12/05/clojure-libs-and-namespaces-require-use-import-and-ns.html
17:10sdegutisDespite being quite aged.
17:10amalloysdegutis: it is trustworthy and *four years old*
17:10sdegutisHence my disclaimer, O slow poke.
17:10amalloyit recommends some stuff that is just Not Done anymore
17:11sdegutisWell I haven't actually read it.
17:11mgaareIsn't (use) "deprecated"?
17:11sdegutisI just know that Colin is trustworthy. I mean, he wrote a book.
17:11technomancyit's good advice if you need 1.3 compatibility
17:11technomancyprotip: you don't need 1.3 compatibility
17:11mgaareor just informally no-longer-idiomatic
17:12mdrogalistechnomancy: core.async is still alpha. You never know.
17:12arrdemEastwood will complain about (:use), right?
17:12Bronsait should
17:12amalloyhey, two years ago a sentence was added to that article saying "don't use :use anymore, use :require/refer"
17:13technomancyis add-watch still alpha?
17:13amalloybut it's just stuck in the middle of some text about how to use :use; i certainly didn't notice it last time i was reading it
17:13sdegutisIn either case, it was a trustworthy blog.
17:13puredangertechnomancy: no
17:13technomancycool
17:13amalloysdegutis: that's the problem with blogs. they are accurate at the time they are written
17:13sdegutisPersonally I think my (ns) lines are way more cluttered than they ought to be.
17:13sdegutisamalloy: Only the accurate ones.
17:13puredangertechnomancy: I removed the alpha tag from almost everything in 1.6 (reducers is one notable exception)
17:14mdrogalispuredanger: :)
17:14arrdemBronsa: huh looks like it warns against unlimited use not against the (:use) form
17:14sdegutisIs 1.7 almost out?
17:14sdegutisWe're still on 1.5.1 and I'm afraid to upgrade.
17:14puredangersdegutis: getting there
17:14sdegutisBut at least we upgraded from 1.3 successfully in early 2013.
17:14justin_smithsdegutis: amalloy: you guys are clearly unfamiliar with nostradamus' blog
17:14Bronsaarrdem: that's good enough for me
17:14puredangersdegutis: http://dev.clojure.org/jira/secure/IssueNavigator.jspa?mode=hide&amp;requestId=10519 is the list of remaining items
17:14sdegutisjustin_smith: I don't know what you're talking about.
17:15sdegutispuredanger: are you Alex Miller?
17:15puredangeryes
17:15sdegutisOh. Hi.
17:15puredangerHi :)
17:15sdegutisI saw you on the Clojure mailing list.
17:15sdegutisYou were saying stuff about Clojure 1.7.
17:15justin_smithsdegutis: he said that blogs are only true when they are written, nostradamus is famous for his "predictions"
17:15arrdempuredanger: ^:deprecated is a thing, right?
17:15justin_smithbad joke, sorry
17:15puredangerarrdem: sure?
17:15sdegutisjustin_smith: Oh. I get the joke now.
17:15sdegutisjustin_smith: It is funny.
17:15amalloyjustin_smith: it's okay. it was a comprehensible joke
17:16sdegutisjustin_smith: You did well.
17:16Bronsapuredanger: arrdem some functions in c.c have :deprecated metadata but there's no automatic warning for that
17:16puredangersdegutis: we will cut a beta when we believe 1.7 is feature complete (I think feature expressions being the major question mark there)
17:16sdegutisI will go read about transducers again. Last time, I got halfway through the page and it looked incredibly un-huge.
17:16arrdemBronsa: yeah was thinking about a eastwood ticket for reaching a ^:depricated var
17:17sdegutisOh no!
17:17arrdemI'm pretty sure that core.async is using it as well in addition to warnings
17:17sdegutispuredanger: But I thought everyone hated that proposal from years ago?
17:18arrdemYep. it's {:deprecated <DEPRECATED_VERSION}
17:18sdegutisIt's just #ifdef ugh!
17:18puredangersdegutis: most people I've talked to already doing effectively feature expressions but with the preprocessor from cljx
17:18arrdemcore.async has no usages of deprecated metadata
17:18sdegutisFeature expressions should be #+js and #+jvm if anything.
17:19sdegutisBecause, supposedly "it's all Clojure" anyway.
17:19puredangersdegutis: the current proposal (and issues) are at http://dev.clojure.org/display/design/Feature+Expressions
17:19puredangerwhich use #+clj and #+cljs (same as cljx)
17:19sdegutisRight, and I'm suggesting it use #+js and #+jvm instead.
17:20puredangersdegutis: well, it's going to be clj and cljs
17:20puredangerthe biggest question remaining is about creating a new file extension for portable clojure files (.cljc)
17:20sdegutisRight, that's why I didn't waste my time suggesting that in any official way.
17:20sdegutisBecause "NOPE" is always the answer to my suggestions.
17:21puredangerwell, I know the feeling
17:21noonianseems like at this point clj and cljs make sense since there is a lot of code out there that uses cljx already
17:22puredangeryes, that certainly is a factor
17:24arrdem"common Clojure"
17:25joshheadIf there is no cljc extension, what would we use? just .clj?
17:25technomancyarrdem: but then what will we call clojure-on-CL-runtime?
17:26arrdemtechnomancy: no that's still "common Clojure" because cljs is "Clojure on JS" and "Clojure" is "Common Clojure on the JVM"
17:26technomancyvenn diagram pl
17:26technomancyplz
17:26arrdemwhich means that Oxlang can die and just be Common Clojure in Common Clojure :P
17:27Bronsaarrdem: are you still working on oxlang/oxcart?
17:27arrdemtechnomancy: if "Common Clojure" (.cljc) is the subset of Clojure common to .cljs and .clj, that means it's a *jure without host interop
17:27joshhead"ClojureCL, not to be confused with ClojureCLR"
17:27puredangerjoshhead: yes, that was the path we were going down
17:28arrdemtechnomancy: thus if you port *jure/Common Clojure thing to another platform, you still have Common Clojure (.cljc)
17:28puredangerjoshhead: getting CLJS to do the right thing with .clj source in the presence of .clj macro files is an issue
17:28arrdemBronsa: oxcart is pretty much dead, I'm still fooling with Oxlang which may or may not die itself
17:29joshheadpuredanger: would this mean .cljs file extension could go away eventually too?
17:29puredangerno
17:29arrdemBronsa: depending on whether or not I decide I've really just reinvented Haskell or Ocaml worse
17:29Bronsaarrdem: gotcha
17:30arrdemBronsa: I think that a "platform abstract static *jure" is an interesting value proposition, but Clojure itself isn't a sufficiently static lang so I'm not convinced that working on Oxcart is useful at least until lib-clojure clearly makes it or breaks it.
17:30joshheadhandling macro files does sound tricky
17:31TEttingerarrdem: was oxcart the "massive speedup for clojure" thing?
17:31arrdemTEttinger: yeah it was/is my GSoC static Clojure compiler
17:32arrdem"ClojureScript on the JVM" I think is what tbaldridge was calling it..
17:32arrdemand that's pretty apt.
17:32joshheadarrdem: is there another static clojure compilation gsoc project?
17:33arrdemjoshhead: there is skummet (I may have gotten the spelling wrong)
17:34arrdemcan't actually find it googling wtf
17:34joshheadarrdem: just came up for me, you spelled it right
17:35Bronsajoshhead: I don't think the dev is working on skummet anymore btw
17:35arrdemjoshhead: so my ultimate issue with both skummet and oxcart is that they require a fork of Clojure, or changes which I project Core will not take thus making them both relatively expensive to maintain.
17:36joshheadbummer, they claimed a 40% reduction in startup time on android, sounded promising
17:38joshheadah yeah that does sound expensive to maintain
17:38arrdemjoshhead: https://groups.google.com/forum/#!topic/clojure-dev/dSPUNKSaV94
17:39arrdemI should fix my Clojure forks to actually work... maybe after 1.7 :P
18:15gazarsgostupid noob question, i have a project.clj and a file core.clj, do they need to be in a particular folder structure for 'lein run' to work ?
18:16gazarsgoguess i should use `lein new` huh
18:16gfredericksyeah that's easiest
18:17gazarsgotrying to pick up some clojure code from a gist someone pasted
18:17dbaschgazarsgo: what error do you get?
18:17gazarsgoi have a new error now that i used lein new :D
18:17dbaschyou need at least a :main namespace and a -main [& args] function in that namespace
18:18gazarsgowell, i am pretty sure their code works... i had to put core.clj in the right spot for their namespace, i think it is working now
18:21gazarsgook, that worked, sorry for rubber ducking
19:00nextstepnew to clojure, starting a new project with some documentation where i'm expected to cite a few papers
19:01nextstepdoes marginalia have facilities for this?
19:02weiI’m looking for a function that I can use with merge-with to combine all the values in a given key into a vector
19:03weie.g. (_ 1 2) => [1 2], (_ [1 2] 3) [1 2 3]
19:05wei(merge-with f {:a 1} {:a 2}) => {:a [1 2]}
19:05justin_smithnextstep: margenalia is nice for formatting where comments go in one column and the code goes in another, I don't know if it has any facilities for footnotes though
19:06metellus,(merge-with vector {:a 1 :b 2 :d 6} {:a 2 :c 4 :d 5}) ;; wei
19:06clojurebot{:c 4, :b 2, :d [6 5], :a [1 2]}
19:07amalloy_metellus: disastrous!
19:07metellusoh?
19:07weiwhat about (comp flatten vector)
19:07amalloy_,(merge-with vector {:a 1} {:a 2} {:a 3})
19:07clojurebot{:a [[1 2] 3]}
19:07metellus~flatten
19:07clojurebotflatten 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.
19:07amalloywei: the whole thing is a lot easier if you start off with {:a [1]} instead of {:a 1}, because then you're clear about whether things are going to be collections or ints or what
19:07weithat’s why I’m asking here :)
19:08weiah, then I can use concat
19:08amalloywei: s/concat/into
19:09nextstepjustin_smith: well, i was just wandering about any facility to cite papers
19:09nextstepnot necessarily as footnotes
19:10nextstepin javadoc you can find many citations too
19:10justin_smithnextstep: what margenalia does is make a nice readable html page out of your code, I don't know that it has any facility to treat anything as a footnote
19:10nextstepi think they format them by hand, which is quit tedious
19:10justin_smithnextstep: wait, what do you mean by citations?
19:11justin_smithalso, s/footnote/citation above, sorry
19:11nextstepjustin_smith: i mean fancy references to papers, like what bibtex does
19:11nextstepno worries
19:11danneuIs there a way to set *out* for all printlns?
19:13dbaschdanneu: with-out-str, for example
19:14dbaschor bind *out* to whatever
19:16jfojtlhi, what do you use for generating load?
19:16danneudbasch: guess i can just define println so that, in development, it wraps println with a with-open and a (binding [*out* file-writer] ...)
19:16dbaschdanneu: ugh
19:16danneuit's a pretty advanced logging system
19:17danneufeel free to steal some pages from my book guys
19:17Bronsadanneu: I mean, you can alter-var-root *out* but that's probably a bad idea.
19:17dbaschdon’t reinvent logging
19:18danneuyeah, i was just hoping for a one-liner that would let me procrastinate replacing my printlns with a logging system for just 1 more week
19:19justin_smithnextstep: I was curious, so I did a quick scan of the margenalia sources, found nothing that looked like code for citations
19:19justin_smithnextstep: but it does have support for directives, seems like that could be extended to make a "citation" directive
19:24justin_smithnextstep: it would be nice to extend margenalia so that you could provide something similar to data_readers.clj with annotations to look for in comments matched up with formatters that render their output
19:25danneuBronsa: (alter-var-root (var *out*) (fn [_] (io/writer "dev.log"))) doesn't seem to change *out*
19:26justin_smithdanneu: (binding [*out* (io/writer "dev.log")] ...)
19:26justin_smithit's a dynamic var
19:27danneujustin_smith: yeah, was looking for a way to just bind it once for all my printlns
19:27justin_smithdanneu: dynamic vars don't work that way
19:27danneuguess i will have to use a logging system like an adult
19:27justin_smithdanneu: see also the persistent problem of cider output going to the wrong place
19:28justin_smithdanneu: it's really not hard, some of them don't even involve making xml or properties files
19:30danneu*drags feet*
19:31amalloyjustin_smith: well, dynamic vars do work that way, except when they're overridden by a binding
19:31amalloy*out* is bound all the time in development, because the repl sets it, so alter-var-root doesn't do anything useful
19:31justin_smithamalloy: thanks for the precision, that's what I meant
19:31justin_smith(inc amalloy)
19:31lazybot⇒ 178
19:32justin_smiththat was a friendly "that's what I meant", not a surly one
19:33nextstepjustin_smith: thanks, directives seem interesting
19:35danneuamalloy: ah right thanks
19:36weiamalloy: kind of bringing back an old topic, but why would you prefer (into [1 2] [1]) to (concat [1 2] [1])? they both produce collections and I don’t care that the end result isn’t also a vector
19:36amalloywei: because (concat (concat (concat ...))) is really bad if you have a lot of things to concat
19:36weiperformance?
19:36clojurebotperformance is http://meshy.org/2009/12/13/widefinder-2-with-clojure.html
19:37amalloywei: try: (first (reduce concat (repeat 2000 [1])))
19:37amalloyand then do the same thing with into
19:37danneualso into uses transients
19:38weiamalloy: surprisingly, concat is faster on my machine for your example. but for 20000, i get a stack overflow :)
19:39justin_smithwei: but do you get the stack overflow faster? that's what's important right? :)
19:40amalloywei: really? when i pick a value small enough to avoid the stackoverflow, into is like three times faster
19:41technomancyshouldn't the lazy one be faster till it's forced?
19:42justin_smithyeah, if you did a quick benchmark with time / dotimes that would be a pitfall for sure
19:42amalloytechnomancy: the lazy one still builds a linked list of thunks
19:43amalloyand you have to traverse them all to get to the first value (which is the same thing that causes the stack overflow, of course)
19:43weiah, I am using time.
19:44amalloywei: you remembered to call (first), right? of course concat is absurdly fast if you don't ever ask for any items
19:44weireduce should force evaluation, right?
19:44dbaschbenchmarking with time is usually a waste of time
19:44weihttps://gist.github.com/yayitswei/db118466ff8ecb813653
19:45justin_smithwei: it's not going to force anything if the reducing function is lazy
19:45amalloyyeah, it was just my lazy benchmarking. the into version is slower if i try harder
19:47dbaschhammockmarking
19:48amalloybut anyway, the important point is that layering concats will cause a stack overflow for no reason
19:49{blake}I find myself doing the following in Clojure: Write some code to do something; discover there's a nil/blank condition; wrap the already written code in a "let" var;make the "body" of the function be an if on said var.
19:50{blake}So, "(do-this (do-that (do-the-other (parm)))" becomes ([let x (do-this...)] (if x x "")).
19:51{blake}Just trying to decide if this is "good" or I like it, or it maybe reflects a weakness.
19:51weiamalloy: got it, thanks
19:51amalloy{blake}: (if x x y) => (or x y)
19:52danneuaside the fact that you can use when-let, consider the possibility of guarding against nils at the edges of your code so that your inner code doesnt need to do nil checks
19:52amalloythus, just (or (do-this ...) "")
19:53{blake}amalloy, danneu Thanks.
19:53{blake}In some cases, it's...well, I guess it's not surprising, it's kind of shaking out how data is going to be passed around.
19:53{blake}Sometimes it's nils, but sometimes it's a map-entry {:key nil}.
19:54{blake}Anyway, "or" and "when-let" will take care of some of the simpler cases. I probably should go through the Clojure cheatsheet again.
19:57danneu{blake}: yeah, it's nice that clojure is lenient with nils. like how (:foo nil) -> nil. but it also makes it easy to remain indecisive about just how far down the chain your program is gonna pass a nil
19:58technomancy...
19:58technomancynice isn't the word I would use
19:58danneutechnomancy: nice in that my yolo cowboy-code live-deploy hotfix doesn't break because i didn't have to answer the question "what if it's nil?" today
19:59danneui can let my future self disarm that bomb
20:00dbaschsomeone set us up the npe
20:00technomancygiven the tragic fact that nil exists on the JVM, clojure offers some help for coding around that flaw.
20:00danneuand by disarm i mean fully rwerite my code from scratch
20:00dysfunactually, the dealing with nil seems very DWIM to me
20:00taliosMONADS!
20:01technomancyit's pretty good at dealing with nils in place of collections
20:01technomancypretty rubbish everywhere else
20:01dysfunthat i'll agree with
20:01amalloy$timer 24 0 0 why not try using MONADS!?
20:01lazybotTimer added.
20:01dysfunbut i'm still not entirely sold that lists not ending in nil is a good thing
20:01technomancyhehe
20:02technomancyeh; it just depends on how you traverse it
20:02technomancy,(next ())
20:02clojurebotnil
20:02taliosCons | Nil
20:02taliosCons | EmptyList
20:03dysfuni can't say it keeps me awake at night
20:03technomancyyou'll get there some day
20:18technomancywhy do people mention monads when talking about options but not when talking about lists?
20:18technomancyI mean, obviously it was a joke, but options are super useful even when you're not working with them monadically.
20:18Travistywhat are options?
20:19technomancyTravisty: https://blogs.janestreet.com/making-something-out-of-nothing-or-why-none-is-better-than-nan-and-null/
20:19TravistyAh, maybe :)
20:20Travistythanks technomancy
20:20bbloomtechnomancy: in the absence of continuations, the list monad + reduce is all you really need anyway :-)
20:27technomancyclojurebot: the option type is a better way of representing nothing: https://blogs.janestreet.com/making-something-out-of-nothing-or-why-none-is-better-than-nan-and-null/
20:27clojurebotA nod, you know, is as good as a wink to a blind horse.
20:34zwertechnomancy what is the advantage of a maybe/option type in a dynamically typed language, where any variable can refer to an object of any type?
20:35bbloomzwer: often, none. however, you may want to explicitly distinguish between None and Some(None)
20:38technomancyzwer: returning an option indicates to the caller every place they should also consider a None
20:38amalloyzwer: a concrete example of bbloom's point: suppose you're writing memoize, and you want a map from function-args to function-result. (get m args) returns nil if the function was uncached or if it was cached and the result was nil
20:39amalloyso you have something like (if-let [[k v] (find m k)] v (f k)), which is an okay workaround but not as easy as just (get m k)
20:39technomancyzwer: in languages with pattern matching, this leads to a style that is far more likely to deal with missing things at the correct point, because you have to match against a call to get the actual value out of the option, which leads you to also handle the None case
20:39technomancyof course the compiler doesn't help you, but a missing clause stands out a lot more
20:40technomancywithout pattern matching there's not much benefit though
20:40amalloytechnomancy: the compiler doesn't help you with what?
20:40technomancyamalloy: it won't tell you when you're missing the None clause
20:40technomancybecause it can't perform exhaustiveness checks
20:41amalloywe're assuming a dynamically-typed language with option, here? i guess that's true then
20:41technomancyyeah
20:41technomancylike Erlang
20:42bbloomwhen i need something option-like, i usually use find or just nil vs [nil]
20:42bbloomso easy to wrap some extra [] around something
20:44technomancyit's a lot like immutability--nice when you can bring it in on your own terms, but far more useful when it's a convention you can assume everyone is on board with.
20:44nathan7technomancy: Rust's matching actually does perform exhaustiveness checks
20:44nathan7technomancy: match some_option { Some(x) => … } won't compile
20:44technomancynathan7: sure; their type system allows for it
20:44nathan7technomancy: yep
20:45nathan7I've kind of lost my appetite for dynamic languages
20:45technomancymeanwhile google go actually implemented nulls. on purpose. M-x tableflip
20:45justin_smithtechnomancy: I am sure you have seen the articles comparing go to algol
20:45nathan7I've written some Go, because it's convenient for small programs
20:45technomancy"Actually, not all dynamic languages have nulls."
20:45technomancy#notalldynamic
20:46nathan7lol
20:46technomancyjustin_smith: yeap =)
20:46nathan7but Go is best described as "unfortunate"
20:46seancorfieldI went to an unsession on Go at The Strange Loop and learned it can do a lot of stuff that is best described as bizarre...
20:46bbloom*shrug* i think null pointers are a very natural idea in languages with mutability
20:46justin_smithtechnomancy: "actually, it's about ethics in generating runtime errors"
20:47technomancyjustin_smith: =D
20:47amalloybbloom: how does mutability make that more or less natural? the two seem unrelated to me
20:47bbloomamalloy: zero-initialized memory on allocation
20:47bbloomvs atomic initialization
20:48bbloomalloc and new are two distinct operations when you have raw memory access
20:48bbloomnew encapsulates alloc on the JVM, but constructors are not atomic. the GC can run during initialization, even for types w/ all final fields
20:49bbloomunlike, say ML or Haskell, where all data constructors are atomic for immutable values
20:49amalloyokay, i think i see what you mean. thanks
20:49nathan7Box<T> in Rust is guaranteed not to be a null pointer, the box type is never constructed until after allocation
20:49bbloomhaving a pointer to nowhere is perfectly reasonable when you have a pointer datatype
20:50nathan7there is an unsafe pointer type which may be null, however
20:50bbloomnathan7: yet Rust has raw pointers and null values in unsafe code
20:50nathan7bbloom: yep
20:50nathan7bbloom: it's fairly well-contained, in my opinion
20:50bbloomyou don't need it often in normal code, but that doesn't mean it isn't useful sometimes
20:50nathan7bbloom: and I write a lot of unsafe code
20:50bbloomyeah, i've been a big proponent of unsafe code blocks since experiencing it in C#
20:50bbloomvery nice design
20:50bbloomand i've written Managed C++ as well :-P
20:50bbloomso i've written LOTS of unsafe CLR code
20:51nathan7half of my code is FFI, the other half is an experimental kernel I'm working on
20:51nathan7and especially in the latter, building safe, zero-cost abstractions around stuff before getting to the meat of it is *amazing*
20:51bbloommy biggest complaint with null in java is that java doesn't have raw pointers
20:51bbloomso there's no good fucking reason why null can't be an object
20:51bbloomas in smalltalk or ruby
20:51bbloomluckily, protocols in clojure can be extended to nil
20:52bbloomnull in java (and C#) is the worst of both worls
20:52bbloomworlds*
20:52bbloomit's not a useful data type (raw pointer) and it's not a valid object
20:52bbloomi guess zero-initialized memory is still a think on the JVM, but that was a design mistake in my opinion too
20:52bbloomC# is adding scala-style "primary constructors"
20:53bbloomhttp://odetocode.com/blogs/scott/archive/2014/08/14/c-6-0-features-part-ii-primary-constructors.aspx
21:15justin_smithbbloom: that seems like a natural way to do immutible datatype initialization
21:23cflemingUgh, sometimes type hinting in Clojure is a total mystery.
21:24cflemingI'm calling a method accepting a CharSequence, Clojure finds it fine if I call it with "", but not if I call it with ^CharSequence (or (:text params) "")
21:25amalloycfleming: http://dev.clojure.org/jira/browse/CLJ-865
21:25amalloy(let [^CharSequence chars (or ...)] (.whatever chars)) would work
21:27cflemingWell that sucks - at least there's a good workaround, thanks.
21:27cfleming15 votes and a patch and it's not moving anywhere?
21:28amalloycfleming: a three-year-old patch, even
21:28cflemingCorrection, 16 votes
21:28amalloyIMO it got bogged down in bikeshedding: the current behavior is terrible, but nobody wants to take an improved behavior because it's not clear what optimal behavior would be
21:29cflemingSo if I understand this correctly, you can never type hint the results of a macro call?
21:29amalloycfleming: you should not rely on the ability to do so. it might, for some macros, turn out to work okay
21:30amalloyadditionally, you can write your own macros to carefully preserve the metadata, if you want
21:30cflemingamalloy: Hoo boy. I'll add an inspection to Cursive for that, just for my own sanity.
21:30cflemingamalloy: That going to hurt when I try to emulate Clojure's type inference though.
21:31amalloycfleming: for example, it looks like -> does carry the metadata for you
21:32amalloy,(meta (macroexpand ' ^String (-> x (identity))))
21:32clojurebotnil
21:32cflemingOr not
21:32amalloywell, i didn't write it very well
21:33amalloyhm, i guess it doesn't. interesting. it saves the metadata on x, but not on the form
21:33amalloy(binding [*print-meta* true] (prn (macroexpand ' ^String (-> ^Foo x (identity)))))
21:33amalloy,(binding [*print-meta* true] (prn (macroexpand ' ^String (-> ^Foo x (identity)))))
21:33clojurebot(identity ^Foo x)\n
21:33cfleming,(meta (macroexpand ^String '(-> x (identity))))
21:33clojurebotnil
21:34cflemingInterestingly, that does something different in my REPL here: I get {:line 1, :column 35}
21:34amalloysure sure, because you've got a different reader. but that's immaterial
21:35cflemingWhich reader is clojurebot using?
21:36amalloywho knows. some stringreader probably
21:36amalloythat is, it's using the clojure reader, but a different java.io.Reader
21:36justin_smith,(class *in*)
21:36clojurebotclojure.lang.LineNumberingPushbackReader
21:36cflemingGot it
21:37cflemingInteresting, I get the same here
21:37amalloyjustin_smith: that doesn't tell you what it's using for its own input
21:37justin_smithahh, yeah
21:37amalloyonly what *in* is bound to once you start running code
21:37cflemingDevious indeed
21:39cflemingAnyway, thanks amalloy, that saved my sanity
21:39cfleming(inc amalloy)
21:39lazybot⇒ 179
21:39justin_smithOK, I hate multimethods so much right now
21:40amalloyjustin_smith: def it to nil, and then call it out of spite
21:40justin_smithI replaced a big case statement with multimethods, in code that gets run multiple times in every page load... and they are so fucking slow
21:40justin_smithso now I have to make a protocol, or put it all back into a case statement again
21:40justin_smithwhich sucks
21:40amalloydid hiredman's patch to reduce locking in multimethods ever get applied?
21:41amalloyit looks like something like it did; they use rwlocks as of 2012. so take heart: it could be much slower
21:42justin_smithstill not fast enough :(
21:42the_dankoevening fellows
21:42the_dankoand ladies
21:43justin_smithhello
21:48the_dankodoing some 4clojure
22:14justin_smithcool, it's a great way to level up your clojure fluency
22:14justin_smith(inc amalloy) ; for 4clojure
22:14lazybot⇒ 180
22:29fairuzhey guys
22:30havenwoodfairuz: hi
22:31fairuzI don't know if I can post Titanium (titandb client) related question here. Their channel seems dead
22:31justin_smithyou can go ahead, no guarantees you'll find an expert
22:40fairuzOk cool. Let me play with it a bit first before asking stupid question :)
22:40fairuzIt's nice to know it's alive in here
22:40Blizzylol.
22:40bbloomfairuz: i don't think he was confirming it was alive. i think he was confirming that we're nice people who may or may answer a question if we're capable of doing so
22:40bbloommay or may not*
22:40fairuzbbloom: True
22:41fairuzI'm referring to at least some people did reply in here :)
22:41havenwoodfairuz: we're all bots written in Clojure
22:42havenwoodbut agreed we're pleasant!
22:45weiwhat’s the best way to handle exceptions in a go block so that an exception doesn’t close the channel? https://gist.github.com/yayitswei/d80d51ee29dc5e2c1117
22:46bbloomwei: if some unfortunate API forces exceptions on you for error handling, catch them immediately and return sensible error codes
22:46bbloomwei: in that particular example, you can move the try down inside the let
22:47bbloomwei: <! won't throw, so there's no need for it to be part of the try block. that should work correctly, but better still would be to take the exception handling out of the go all together and push it in to the process! method
22:47bbloomor some helper that calls process!
22:47bbloommake sense?
22:51weibbloom: the channel seems to still get closed when I move the try block inside the let
22:51weii expect the second >! to trigger a “processing: true”, but that doesn’t happen
22:52bbloomwei: take a closer look at your compiler warnings
22:52bbloomqueue is undefined
22:53bbloomwei: the code that you have should work as is with the correct variable name, but still: 1) move the try inside the let or 2) further move the try inside another call
22:54weioops, i’ve updated the gist. still not working for me in its current form
22:56weiif you comment out the (>! q false), it works as expected
22:58bbloom wei: so (go (>! ... is the same as (put! ... only the go/>! pair is slower
22:58bbloomthose are async sends
22:58weiaha, i was wondering what put! was for
22:58bbloomso there's actually no promise that the false send will occur before teh true send
22:59weii’m not too particular, but i do want the true to process correctly
23:02bbloomi'm experimenting with it locally b/c i've never actually used a try catch in a core.async go block (and i've written quite a bit of core async)
23:03weithanks for taking a look
23:06bbloomwei: this is certainly strange
23:08weiyeah, it’s the first time channels haven’t worked like i’ve expected them to in almost a year that i’ve been using them
23:08weiupdated the gist to explain the issue: https://gist.github.com/yayitswei/d80d51ee29dc5e2c1117
23:10weibbloom: unfortunately I have to take off for a bit. if you discover anything would you mind commenting on the gist?
23:11bbloomwei: *shrug* i've explored it
23:11bbloomnot gonna dig any deeper, sorry
23:11bbloomjust don't put a try/catch in a go
23:11bbloomit's probably broken
23:11bbloomthere's lots of threats around about it being broken elsewhere
23:11bbloomit's also just a questionable idea in the first place
23:12bbloomi'll @ mention tim
23:12bbloomgood luck
23:12weithanks anyways! sounds good
23:54fairuzHi guys. Using LightTable, in the live mode, if I add something to the DB, it will be really be added to teh DB as I type it?
23:54fairuz*the