#clojure log - Oct 27 2014

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

1:14 sm0ke: hello in java.jdbc there is a db/query method to fetch whole result set is there a better way to do this?

1:14 soemthing like a query-seq?

1:15 which could be operated upon lazily

1:16 oops there is a result-set-seq!

1:31 justin_smith: sm0ke: the lazy stuff breaks if you try to realize it outside the transaction context

1:32 but it does work

1:33 sm0ke: justin_smith: i dont understand

1:34 i just want a seq over result as maps, how do i do that?

1:34 lazy seq

1:35 i see that internally query uses result-set-seq so i am more confused now

1:35 justin_smith: sm0ke: just make sure you realize as much of it as you are going to use before exiting the scope where you acquire the results

1:35 sm0ke: 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

1:36 sm0ke: yes that is true, but i dont think it is still lazy

1:36 justin_smith: sm0ke: 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

1:36 sm0ke: by default :result-set-fn is doall

1:36 justin_smith: sm0ke: ahh yeah, but you can change that to actually be lazy

1:37 if you actually wanted the lazy part

1:37 sm0ke: so setting it to identity should be enough?

1:38 justin_smith: I think so

1:42 oskarkv: Style 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?

1:48 m00nlight: Does struct save memory than ordinary map structure ?

2:14 dysfun: m00nlight: don't look at it in those terms. do you want polymorphism? use a record. else use a map

2:14 unless you have funky requirements

2:14 there's a really good diagram of which abstraction to pick, let me find it

2:15 https://github.com/cemerick/clojure-type-selection-flowchart

3:14 m00nlight: dysfun: thanks very much

3:20 dysfun: yw

3:24 oskarkv: which bindings are you using?

3:26 if it's just raw JavaFX you can do something like (-> my-pane .getStylesheets (.add "styles.css"))

3:26 er with a .clear in there as well

4:00 oskarkv: dysfun does not work. And it would be strange if it did: It's a new Pane instance each run.

4:00 dysfun I'm using plain JavaFx

4:01 dysfun: hrm, i'm afraid i don't know then

4:01 i stopped using javafx once i realised it couldn't actually do what i wanted it for

4:01 oskarkv: hehe

4:01 What was that?

4:01 dysfun: i wanted to manipulate the dom of a webkit control from clojure code without involving javascript or clojurescript

4:02 well, that was one of the things (and doesn't work because the DOM is made read-only, presumably to simplify implementation)

4:02 oskarkv: hehe ok

4:03 dysfun: the 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

4:11 oskarkv: dysfun :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

4:12 btw i can probably just rename the css file to something random, and then load that, tricking the cache P

4:22 sm0ke: ok so if i set result-set-fn to something other than doall it causes ResultSetClosed exception

4:22 is there a way to have lazy seq without realizing it immediately?

4:34 dysfun: oskarkv: yeah, you can just increment a number in a filename i suppose

6:30 SagiCZ1: sm0ke: isnt that the point of lazy-seqs?

6:55 dysfun: laziness and i/o resources don't play terribly lovely together

6:57 you'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?

7:02 borkdude: dysfun 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

7:03 dysfun: i haven't gotten around to playing with them yet, so i can't help, sorry

7:03 but if you have a read, i can probably help you through some of it if you're struggling to understand

7:08 borkdude: dysfun I understand what transducers do, but not how they help working with resources

7:08 dysfun in the lazy case

7:10 SagiCZ1: (doc read)

7:10 clojurebot: "([] [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"

7:11 SagiCZ1: if read should be used only with trusted sources, what should i use with untrusted source?

7:13 io/reader i guess

7:14 dysfun: borkdude: i'm reading. gosh, they sound like lazy monads

7:15 clgv: borkdude: when you'd do file processing via transducer you eliminate the need for a lazy-seq

7:15 jonathanj: anyone familiar with instaparse?

7:15 i have a tree sgement like [:command "F" "O" "O"]

7:16 dysfun: damn. i've just realised how this could make some of my code cleaner. so i suppose i'll have to go play

7:16 jonathanj: if i use (insta/transform {:command str}) then i end up with "FOO" whereas what i'm looking for is [:command "FOO"]

7:17 borkdude: clgv the data source for a (sequence xform source), what would that be instead of a lazy seq?

7:19 clgv: borkdude: well a transducer is a stepwise description, so the step could be "read the next thing from file"

7:19 borkdude: clgv the problem with lazy sequences and file resources is that you can't use them within a with-open-file macro for example right?

7:20 clgv because if use consume elements from outside the macro, the file is closed

7:20 clgv: borkdude: yes, you have to consume as much of the lazy-seq as you need within the with-open

7:20 borkdude: clgv ok, so it doesn't really add any benefit in that area

7:21 clgv: borkdude: 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

7:22 borkdude: clgv what are you reading.

7:23 SagiCZ1: how do i convert string to number?

7:23 ,(Double/parseDouble "1.64")

7:23 clojurebot: 1.64

7:23 SagiCZ1: more clojury way?

7:23 clgv: no

7:23 ,(double "1.64")

7:23 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number>

7:23 clgv: ;)

7:24 SagiCZ1: okay :)

7:24 borkdude: (read-string "1.64")

7:25 ,(read-string "1.64")

7:25 clojurebot: 1.64

7:25 clgv: borkdude: I am not sure where I read the finalizing part either the official blog post or on the mailing list

7:25 ha! right :P

7:26 dysfun: borkdude: potentially dangerous

7:26 clgv: then read-edn ;)

7:27 borkdude: dysfun clojure.edn/read-string

7:27 dysfun: also (binding [*read-eval* false]) if you're going to use read-str

7:27 still gotta check what you get back afterwards

7:27 borkdude: dysfun I'm assuming everybody knows I mean that one ;)

7:27 dysfun: i suspect there are lots of people in this channel who don't

7:28 borkdude: dysfun they'll learn

7:29 dysfun: yes, but we prefer them not to learn in production :)

7:29 borkdude: dysfun production is the best teacher ;)

7:29 dysfun: that's definitely true, but it can go quite badly

7:29 clojurebot: I don't understand.

7:31 dysfun: now 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

7:31 borkdude: dysfun of course I agree.

7:37 SagiCZ1: (doc read-string)

7:37 clojurebot: "([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"

7:38 SagiCZ1: ,(read-string "(+ 3 3)")

7:38 clojurebot: (+ 3 3)

7:43 clgv: ,(-> "(+ 3 3)" read-string eval print)

7:43 clojurebot: 6

7:43 clgv: repl yay! ;)

7:44 jonathanj: is there a shorter way to write: (fn [& args] [:foo (apply str args)]) ?

7:44 borkdude: jonathanj you could use a minifier

7:44 clgv: jonathanj: probably not

7:45 or do you want something like that: #(vector :foo (apply str %&))

7:45 jonathanj: hrm

7:46 borkdude: jonathanj I was kidding btw

7:46 clgv: ,(#(vector :foo (apply str %&)) [:a 1 :b 2])

7:46 clojurebot: [:foo "[:a 1 :b 2]"]

7:46 jonathanj: (defn apply-and-tag [tag f] (fn [& args] [tag (apply f args)]))

7:46 might work, i guess

7:47 i want an instaparse transformer that retains tags instead of consuming them

7:47 clgv: though that result looks strange

7:47 ,(apply str [:a 1 :b 2])

7:47 clojurebot: ":a1:b2"

7:47 clgv: ah lol ;)

7:47 ,(#(vector :foo (apply str %&)) :a 1 :b 2)

7:47 clojurebot: [:foo ":a1:b2"]

7:47 jonathanj: thanks

7:53 so instaparse produces trees like [:tag [:another-tag [:foo "FOO"]]]

7:54 what's the easiest way to get the value of the :foo tag?

7:57 mbac: jonathanj, ((apply hash-map (second (second x))) :foo)

7:57 where x = [:tag [:another-tag [:foo "FOO"]]]

7:58 you could also just say (second (second (second x)))

7:58 but that's probably not what you had in mind

8:00 (reduce (fn [x k] ((apply hash-map x) k)) x [:tag :another-tag :foo])

8:00 jonathanj: hrm

8:00 mbac: :P

8:01 jonathanj: hrm, this is kind of inconvenient to work with

8:02 i wonder if i'm missing something

8:03 hyPiRion: jonathanj: you can hide instaparse nodes with the <>-syntax I think

8:03 jonathanj: hyPiRion: 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?

8:04 hyPiRion: jonathanj: well, it sort of depends on what you're doing I guess. (for me it was useful)

8:05 jonathanj: hyPiRion: parsing IRC messages

8:05 hyPiRion: I used it in conjunction with core.match for pattern matching

8:05 jonathanj: hyPiRion: do you have an example?

8:05 i'd be interested to see that

8:14 clgv: criterium question: are the mean durations in the result map always in seconds?

8:16 hyPiRion: jonathanj: 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)

8:17 now, if you know all the different permutations à priori (like you'd do for instaparse), using core.match is very succinct

8:37 Chaze: Hi. Does Clojure have "arrows" (http://www.haskell.org/arrows/) in the core namespace somewhere?

8:37 dysfun: not in core

8:38 Chaze: somewhere that ships with clojure?

8:38 (guess that's what i meant)

8:38 dysfun: check the 'functional programming' section here http://www.clojure-toolbox.com/

8:38 no, not in the base distribution. use a third party library

8:38 unless there's one in contrib somewhere

8:38 but those still require installing

8:39 Chaze: Alright, thanks. Great site

8:40 dysfun: yeah, it is :)

8:48 clgv: Chaze: 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

9:34 jonathanj: is there a shorter way to write (apply hash-map (apply concat xs))?

9:34 zoldar: jonathanj: mapcat ?

9:35 jonathanj: mmm

9:35 zoldar: umm no

9:35 jonathanj: xs is like [[:a 1] [:b 2]]

9:36 mgaare_: (into {} xs) should do it

9:36 jonathanj: oh, awesome

9:44 mgaare: thanks

9:44 mgaare: jonathanj: you're welcome

9:46 jonathanj: what's the convention for naming private variables in a namespace?

9:46 well, private values, rather

9:47 mgaare: use the ^:private metadata tag, and name it however you want

9:54 mavbozo: jonathanj: follow bbatsov's clojure style guide

9:54 jonathanj: https://github.com/bbatsov/clojure-style-guide#private

9:57 stompyj: private variables?!

9:57 whats next? interfaces to classes? I thought this was #clojure, not #kingdomofnouns

9:57 jk

10:00 mavbozo: stompyj: chill down. there will always be someone who doesn't know the proper usage of various terminologies

10:00 stompyj: mavbozo: haha, no, i was legit just messing around. this IRC channel is devoid of the typical pedantic rage that other chans have

10:11 mavbozo: stompyj: haha, it seems that I am in a very tense-serious mood

10:12 stompyj: haha, my bad

10:23 SagiCZ1: btw why dont we have def- ?

10:24 Bronsa: SagiCZ1: because we'd need to have a defmulti-, a defonce-, a defprotocol- etc

10:24 SagiCZ1: just use ^:private, defn- was a bad idea

10:25 SagiCZ1: Bronsa: seriously?

10:25 Bronsa: yes

10:25 SagiCZ1: so should i avoid defn- ?

10:25 Bronsa: use it if you want

10:25 SagiCZ1: ,(def x ^:private 6)

10:25 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Metadata can only be applied to IMetas>

10:25 Bronsa: ,(def ^:private x 6)

10:25 clojurebot: #'sandbox/x

10:25 SagiCZ1: Bronsa: thank you

10:25 Bronsa: SagiCZ1: np

10:28 jonathanj: how do i do something like Python's repr() in Clojure?

10:28 i want to examine a string that may include characters line \r or \n

10:28 perplexa: yo, 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:29 Bronsa: perplexa: (partial a) is just a

10:29 justin_smith: perplexa: do you want to run b on the result of a, or do each in parallel?

10:29 perplexa: also (partial) with a 1 param fn is probably pointless ;P

10:29 Bronsa: yeah just realised :D

10:29 justin_smith: yeah b on a

10:29 Bronsa: perplexa: then comp is ok

10:29 (map (comp - inc) [1 2 3])

10:29 ,(map (comp - inc) [1 2 3])

10:29 clojurebot: (-2 -3 -4)

10:30 Bronsa: otoh if you want to run them in parallel you'd want to use juxt

10:30 ,(map (juxt - inc) [1 2 3])

10:30 mmeix: in the other case (a, and par. b) there would be juxt, as

10:30 clojurebot: ([-1 2] [-2 3] [-3 4])

10:30 perplexa: yeah i have one of those examples myself and tried but

10:30 i don't know which order it is

10:30 ,map (comp inc (partial + 3)) [1 2 3])

10:30 clojurebot: #<core$map clojure.core$map@1cf3511>

10:30 perplexa: ,(map (comp inc (partial + 3)) [1 2 3]))

10:30 clojurebot: (5 6 7)

10:30 perplexa: first inc then +?

10:30 Bronsa: perplexa: no

10:30 perplexa: right to left

10:30 perplexa: ok ty

10:31 Bronsa: that's why I used a non commutative example

10:31 perplexa: oh the - inc was obv.. ;P

10:31 * perplexa facepalms :)

10:33 mgaare: jonathanj: what does repr() do exactly?

10:33 perplexa: (inc Bronsa)

10:33 ,inc Bronsa

10:33 clojurebot: #<core$inc clojure.core$inc@178fdc3>

10:33 perplexa: narf

10:33 i'll never remember this

10:33 hyPiRion: (inc Bronsa)

10:34 lazybot is dead, long live lazybot

10:34 Bronsa: perplexa: it was correct the first time, but lazybot is dead

10:34 perplexa: oh!

10:34 living up to its name i guess

10:35 hyPiRion: hard at work

10:35 Bronsa: Raynes: you owe me an inc

10:36 daniel__: (inc Bronsa)

10:36 ,(inc Bronsa)

10:36 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: Bronsa in this context, compiling:(NO_SOURCE_PATH:0:0)>

10:37 Bronsa: I'm undefined

10:38 mgaare: Bronsa: according to Joseph Heller, we all have to start ignoring you now

10:39 stompyj: (inc mgaare)

10:40 jonathanj: mgaare: for a string it produces an escaped string

10:41 repr("\r") -> "\\r"

10:43 mavbozo`: jonathanj: that's wrong. should be

10:43 repr("\r") -> "'\\r'"

10:44 jonathanj: err, yes sorry

10:46 mgaare: jonathanj: not aware of a core clojure function that does that. pprint ignores newlines. you could also do something using clojure.string/replace

10:47 SagiCZ1: is there a way to have clojure.pprint required no matter what namespace is currently set in the repl?

10:47 mgaare: with :inject in lein, perhaps

10:48 er, :injections

10:49 in fact that's the default usage example for it - https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L242

10:50 SagiCZ1: it says "Forms to prepend to every form that is evaluated inside your project."

10:50 isnt that unecessary?

10:51 mgaare: it's not something you'd want to do in your production profile, to be sure

10:51 SagiCZ1: mgaare: makes sense

10:51 andyf_: 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:52 mavbozo`: jonathanj: do you want to use the escaped string in a regex expression?

10:52 perplexa: btw, is aot broken in lein 2.5?

10:53 andyf_: 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:54 perplexa: coworker said sth like that and reverted to a previous lein version, just curious if anybody has experienced any issues

10:55 mmeix: playing 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:57 jonathanj: mavbozo`: no, i just want to inspect a string

10:59 SagiCZ1: can i simplify (or (= x 5) (= x 10)) so that i wouldnt have to repeat x?

10:59 andyf_: 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:01 gfredericks: SagiCZ1: in this case (#{5 10} x) would work

11:03 hyPiRion: SagiCZ1: (not (distinct? 5 10 x))

11:11 SagiCZ1: gfredericks, hyPiRion thanks

11:14 bostonaholic: mmeix: be careful with that implementation. (map notes (series 15)) will cause infinite recursion

11:16 mmeix: ah ...

11:17 in the mean time I found (some #{x} coll) to test for repetitions, just a bit shorter than my first try

11:18 bostonaholic thanks

11:19 bostonaholic: mmeix: but that's a cool idea. you could then do similar randomness of quarter, eighth, etc. to create some pretty interesting improv solos

11:20 mmeix: of course

11:20 bostonaholic: just play that through my speakers all day, on a blues scale

11:20 mmeix: this is just getting to grips with clojure

11:20 jeffterrell: jonathanj: Try (pr-str)

11:20 ,(pr-str "\r")

11:20 clojurebot: "\"\\r\""

11:20 jonathanj: thanks, that's probably sufficient

11:21 justin_smith: ,(shuffle ["c" "c#" "d" "d#" "e" "f" "f#" "g" "g#" "a" "a#" "b"]) mmeix

11:21 clojurebot: ["g#" "a#" "e" "d" "d#" ...]

11:21 justin_smith: mmeix: your intention is a random permutation of a fixed set, right?

11:22 mmeix: not quite

11:22 patrkris: hi everybody. is there some way to have clojure.java.jdbc always replace undercores with hyphens in the field names of result sets?

11:22 mmeix: this is just a beginning

11:22 justin_smith: mmeix: (take n (shuffle ["c" "c#" "d" "d#" "e" "f" "f#" "g" "g#" "a" "a#" "b"]))

11:22 to answer your "can this be done shorter" question

11:23 SagiCZ1: im 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:23 mmeix: there will be many methods to build more structurally anchored things, a random dodecaphonic series is just the most primitive example ...

11:23 justin_smith: mmeix: sure, just addressing the question in that comment, you are doing shuffle

11:23 mmeix: of course! I had forgotten about shuffle - thank

11:24 this makes it much shorter :-)

11:25 I'm thinking about a more functional version of something like http://web.mit.edu/music21/

11:26 which is great somehow, but overflows with classes and supers and subs ...

11:26 this has to be done much more simple, functional

11:26 I think

11:27 [thus learning Clojure like crazy ;)]

11:28 SagiCZ1: what is the goto benchmarking tool for clojure? or something that looks for hotspots? like which function is called the most

11:28 mmeix: justin-smith apologies & thanks!

11:29 patrkris: SagiCZ1: YourKit and JVisualVM seems to be popular choices

11:29 *seem

11:29 SagiCZ1: patrkris: JVisualVM is not clojure related though? its general jvm?

11:29 patrkris: SagiCZ1: I think you are right, yes

11:30 I don't think there is anything specifically suited for Clojure

11:30 SagiCZ1: patrkris: ok i will try to use that

11:30 stuartsierra: You need a JVM-level tool to get worthwhile performance metrics.

11:30 mavbozo: patrkris: put your converter function in :identifiers arguments in clojure.java.jdbc/query function, default lower-case

11:30 stuartsierra: Even then it's like voodoo.

11:30 mavbozo: patrkris: http://clojure.github.io/java.jdbc/#clojure.java.jdbc/query

11:30

11:30 patrkris: mavbozo: yeah, but I have to do that everywhere I call query, right?

11:31 mavbozo: patrkris: yeah, but we have macros

11:31 patrkris: we do :)

11:34 mavbozo: patrkris: and robert-hooke :p https://github.com/technomancy/robert-hooke/

11:35 SagiCZ1: thats interesting, according to jvisualvm the most called function is clojure.lang.RT.next()

11:39 justin_smith: SagiCZ1: well, what's more important than most called is which one it spends the most time calling

11:43 SagiCZ1: justin_smith: its time as well, but maybe im doing something wrong

11:43 mavbozo: I often get java.lang.OutOfMemoryError: PermGen space when doing too many (refresh) using org.clojure/tools.namespace

11:44 is it just me? or is anyone else having this kind problem?

11:44 stuartsierra: mavbozo: Which JVM?

11:44 mavbozo: java version "1.7.0_67"

11:44 Java(TM) SE Runtime Environment (build 1.7.0_67-b01)

11:44 Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode)

11:45 SagiCZ1: mavbozo: i've had this problem in a completely different circumstance (jetty hot deploy) but you could try turning permgen garbage collection on

11:45 justin_smith: mavbozo: 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:46 stuartsierra: SagiCZ1, mavbozo: PermGen is GC'd by default.

11:46 SagiCZ1: stuartsierra, mavbozo: see https://stackoverflow.com/questions/7383658/permgen-space-exception?lq=1

11:46 stuartsierra: But you can fill up the space if you're recompiling a large project.

11:46 mavbozo: SagiCZ1: I just increase increase the -XX:MaxPermSize

11:47 stuartsierra: I've had to increase the PermGen size for large projects (hundreds of Clojure source files)

11:48 mavbozo: thanks everyone

11:48 justin_smith: stuartsierra: the top SO answer at that link claims permgen GC is off by default

11:48 stuartsierra: justin_smith: I take no responsibility for what StackOverflow says.

11:49 justin_smith: stuartsierra: OK - I wasn't saying you were wrong, just pointing out the discrepency

11:49 mavbozo: stuartsierra: please add that in Warnings section in https://github.com/clojure/tools.namespace README

11:49 stuartsierra: Older JDKs had PermGen GC disabled by default, but not 1.7.

11:49 mavbozo: I will consider that.

11:49 justin_smith: stuartsierra: thanks for the clarification. Too bad 1.6 is still such a common deployment target.

11:50 stuartsierra: I'm not certain if 1.6 has it enabled by default, but I think it does.

11:50 May depend on the vendor.

11:50 justin_smith: stuartsierra: 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:34 SagiCZ1: is both first and next always in constant time?

12:38 justin_smith: SagiCZ1: 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:40 dopamean_: justin_smith: the other day you mentioned hat i could install a library locally

12:40 and you said something really simple that i have now forgotten

12:40 justin_smith: oh, and seq can wrap a java iterable, and that iterable could hypothetically in a pathological case have a non-linear Iterator?

12:40 dopamean_: originally i wanted to use a library i had written that is not on clojars

12:40 justin_smith: dopamean_: lein install

12:40 dopamean_: doh

12:41 thanks

13:00 SagiCZ1: ,(time (dotimes [_ 10000000] (first (range 5))))

13:00 clojurebot: eval service is offline

13:00 SagiCZ1: ,(+ 5 3)

13:00 clojurebot: 8

13:01 SagiCZ1: anyways 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:02 hyPiRion: SagiCZ1: no, it isn't. It's dependent on the 1-32 first elements, but only if the lazy seq is chunked.

13:02 justin_smith: wat - how would first be dependent on the size of the sequence?

13:03 hyPiRion: It's a bit weird and strange at first, but things are usually chunked unless you do something like (iterate ...) or lazy-seq yourself

13:03 SagiCZ1: i ran two tests..

13:03 (time (dotimes [_ 10000000] (first (range 50000000000000)))) took 12 seconds

13:03 (time (dotimes [_ 10000000] (first (range 5)))) took 4 seconds

13:04 and it is very consistent on my pc

13:04 justin_smith: SagiCZ1: (range 50) takes as long as (range 50000000000000)

13:05 SagiCZ1: it's because of chunking, like hyPiRion said

13:05 first of range realizes the first 32 or so elements

13:06 SagiCZ1: oh.. i see, sorry

13:06 i didnt get hyPiRion's message at first

13:21 rooster_rus: is 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:22 also state variables are lexically scoped within function body

13:23 tropicalmug: Hi 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:28 SagiCZ1: rooster_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:29 justin_smith: tropicalmug: I have had good luck with https://github.com/yogthos/clj-rss

13:30 mmeix: I owe justin_smith some incs

13:30 justin_smith: rooster_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:30 mmeix: (inc justin_smith)

13:31 justin_smith: mmeix: lazybot is out

13:31 thanks though :)

13:31 mmeix: I' keep your (repeatedly 5 (inc justin_smith)) for later :-)

13:32 justin_smith: SagiCZ1: 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:32 tropicalmug: justin_smith That looks good for creating feeds, though that isn't my use case

13:32 justin_smith: rooster_rus: agents are values that manage unsyncronized sequential update, that may help you

13:33 tropicalmug: oh, you want to consume feeds

13:34 tropicalmug: 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:34 tropicalmug: justin_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:34 Thanks!

13:35 justin_smith: https://github.com/scsibug/feedparser-clj this is a ROME wrapper

13:37 tropicalmug: justin_smith :-b

13:42 justin_smith: tropicalmug: it's a pretty thin wrapper, just one namespace

13:49 tropicalmug: justin_smith might hack it to support the conditional-get parts of the rome fetcher. Beyond that, it's all I need. Thanks again.

13:56 TimMc: "eduction", really?

13:57 Bronsa: TimMc: it took me by surprise too

14:01 justin_smith: eduction?

14:01 mmeix: a typo for Reducation :-)

14:02 gfredericks: it took me several seconds not to read "education"

14:04 mmeix: we could need an "educate" function in clojure, for misbehaved colls... (educate {3.14 :a 1/3 :b}) :-)

14:07 justin_smith: ,{1.0M 1 1 1 1.0 1}

14:07 clojurebot: {1.0 1, 1 1, 1.0M 1}

14:09 mmeix: Is there a better way to extract a number's digits than this: (- (int %) 48) (str 42) - looks like cheating to me...

14:09 sorry: (map #(- (int %) 48) (str n))

14:11 Bronsa: justin_smith: it's the new name for `iteration`

14:11 hashpuppy: can someone explain what this does: (defrecord Click [pos] IFn (-invoke [_ state] (click pos state)))

14:12 it's in clojurescript

14:12 Bronsa: hashpuppy: it makes your record invokable

14:12 dbasch: mmeix: see this blog post for a number of ways http://diegobasch.com/life-the-universe-and-technical-interviews

14:12 Bronsa: so you can do ((Click. foo) 1)

14:13 justin_smith: Bronsa: context?

14:13 mmeix: dbasch thanks!

14:17 TimMc: justin_smith: eduction

14:17 chronno: justin_smith: http://clojure.github.io/clojure/branch-master/clojure.core-api.html#clojure.core/eduction

14:19 danneu: In 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:21 Bruce_Wayne: anyone ever see when two strings are the same but don’t pass the = test

14:21 sg2002: assault_ninjaD9ULSuSkji9YPmKbA462

14:21 Bruce_Wayne: but they do pass the = test after wrapped in a prn

14:21 danneu: Bruce_Wayne: do they pass the == test

14:22 Bruce_Wayne: is that a thing

14:22 ?

14:22 danneu: ,(== 1 1.0)

14:22 clojurebot: true

14:22 Bruce_Wayne: danneu: no they don’t because they are strings not numbers

14:23 danneu: oh, it's just for numbers?

14:23 i now see "nums" in the docstring, but i recall it being useful in another circumstance

14:24 SagiCZ1: is there a way to read only last n lines of a file, skipping the lines before?

14:25 danneu: nvm

14:25 justin_smith: Bruce_Wayne: the equal after prn thing is odd, you should take the base64 of their byte-array representation next time

14:25 danneu: SagiCZ1: line-seq + take-last?

14:26 justin_smith: ,(String. (clojure.data.codec.base64/encode (.getBytes "hello"))) ; Bruce_Wayne

14:26 clojurebot: #<CompilerException java.lang.ClassNotFoundException: clojure.data.codec.base64, compiling:(NO_SOURCE_PATH:0:0)>

14:26 justin_smith: ,(require 'clojure.data.codec.base64)

14:26 clojurebot: #<FileNotFoundException java.io.FileNotFoundException: Could not locate clojure/data/codec/base64__init.class or clojure/data/codec/base64.clj on classpath: >

14:26 justin_smith: hrmph

14:26 ,(require 'clojure.data.codec)

14:26 clojurebot: #<FileNotFoundException java.io.FileNotFoundException: Could not locate clojure/data/codec__init.class or clojure/data/codec.clj on classpath: >

14:27 SagiCZ1: danneu: i think take-last still realizes the elements before

14:27 justin_smith: SagiCZ1: danneu: it definitely does

14:27 SagiCZ1: i was thinking maybe some magic with interop .seek ... but i have never used it

14:28 danneu: SagiCZ1: how about http://commons.apache.org/proper/commons-io/apidocs/org/apache/commons/io/input/ReversedLinesFileReader.html

14:28 justin_smith: SagiCZ1: I think you'll need to use interop to seek on the file stream and move backward past N newlines

14:28 SagiCZ1: or get the one creating the files to do proper rotation so that file size is more reasonable :)

14:29 SagiCZ1: danneu: 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:29 justin_smith: haha.. or i could rotate them myself with some simple script.. would took hours though

14:33 justin_smith: SagiCZ1: well, many loggers come with rotating options you can turn on

14:36 I 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:37 SagiCZ1: justin_smith: why would you need to clone something if you want to make a branch?

14:37 justin_smith: SagiCZ1: to have both running at once

14:38 looks like I can use git-new-workdir http://nuclearsquid.com/writings/git-new-workdir/

14:38 TimMc: justin_smith: If you clone a git repo from one place on disk to another, it uses hardlinks so it takes up less space...

14:38 SagiCZ1: oh i see.. interesting usage, seems like it would be pretty handy

14:38 justin_smith: TimMc: oh, great, so it just does the right thing

14:39 TimMc: It does mess up your remotes, though. :-P

14:39 justin_smith: TimMc: that was my concern, was getting two copies of everything in the git history

14:39 TimMc: ugh

14:39 mess up as in?

14:39 TimMc: The second's only remote is the first.

14:39 justin_smith: oh, that's fine for my usage

14:39 thanks man

14:39 (inc TimMc)

14:40 Raynes: can we have lazybot back pretty please?

14:41 Raynes: justin_smith: One lazybot for you sir.

14:41 justin_smith: (inc Raynes)

14:41 Raynes: Well wait a second :P

14:41 danneu: in the meantime, Raynes is manually reading through the #clojure logs and balancing the inc ledger by hand

14:41 justin_smith: hehe :)

14:41 SagiCZ1: danneu: xD

14:41 Bronsa: (inc TimMc)

14:41 SagiCZ1: he better!

14:41 lazybot: ⇒ 74

14:41 Raynes: Hah, the amount of shits I gave is way too small for that.

14:42 My time would be better spent moving lazybot to latest irclj and getting real reconnection support.

14:42 :P

14:42 Bronsa: lazybot: <3

14:42 Raynes: Or anyone's time, for that matter. Blow off work today and do that for me ^

14:42 I'll give you one (1) cookie.

14:43 dbasch: the ledger for the karma currency must be consistent and partition-tolerant

14:43 justin_smith: dbasch: well there are systems that are not C, A, or P

14:44 2/3 is the best case, 0/3 is the worst

14:44 dbasch: or you can be trivially CAP with /dev/null

14:45 SagiCZ1: dbasch: how do you get the ledger number for someone?

14:45 dbasch: $karma SagiCZ1

14:45 lazybot: SagiCZ1 has karma 0.

14:46 SagiCZ1: dbasch: awww

14:46 thats harsh

14:46 dbasch: karma don’t come easy around these parts

14:46 mmeix: (inc justin_smith)

14:46 lazybot: ⇒ 105

14:47 justin_smith: (inc stuartsierra)

14:47 lazybot: ⇒ 13

14:47 justin_smith: (inc TimMc)

14:47 lazybot: ⇒ 75

14:50 csd_: How do I bind *out* to a file object for use with with-open?

14:51 hfaafb: whats the point of ^:const?

14:52 sg2002: assault_ninjaD9ULSuSkji9YPmKbA462

14:53 justin_smith: csd_: (with-open [f (java.io.FileWriter. "tmpfile")] (binding [*out* f] (prn {:a 0 :b 1})))

14:54 csd_: but for a simple case like that pr-str / spit is easier

14:54 csd_: what about binding StringWriter?

14:55 justin_smith: csd_: so do you want with-out-str?

14:55 ,(with-out-str (prn {:a 0 :b 1}))

14:55 clojurebot: "{:b 1, :a 0}\n"

14:56 csd_: 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:56 justin_smith: csd_: it seems odd that there wouldn't be a version that just handed you the string...

14:57 turbofail: pretty sure you could just use (write-csv *out* ...)

14:57 justin_smith: csd_: it takes a writer, so you can hand it a StringWriter directly as an arg

14:57 or that if you just want to print, yeah

14:57 ,(class *out*)

14:57 clojurebot: java.io.StringWriter

14:58 csd_: what file object would i use if i wanted to pass the transformed object in my code?

14:58 would StringWriter still work

14:59 justin_smith: none of this requires a file

14:59 it takes a writer

14:59 create a StringWriter and pass it in if you want that

15:01 csd_: i'll give it a shot, thanks

15:13 arrdem: so has anyone actually built Philip Lord's [n .. 20] unrolling defn yet?

15:13 amalloy: arrdem: link?

15:14 arrdem: amalloy: https://groups.google.com/forum/#!topic/clojure/hnkJb9_il_M

15:15 amalloy: arrdem: 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:17 arrdem: amalloy: 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:17 or at least a bound on the common case

15:19 puredanger: old ticket for this: http://dev.clojure.org/jira/browse/CLJ-731

15:20 dbasch: it 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:20 amalloy: arrdem: 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:20 arrdem: amalloy: no idea we'd have to actually start looking at JIT'd code

15:20 puredanger: I don't really know for sure - feel free to do some perf analysis

15:21 arrdem: amalloy: 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:21 Bronsa: varargs & apply are both slower than fixed args + direct invoke, no idea what % they individually contribute to

15:21 but usually they go hand in hand

15:21 eliminating one usually eliminates the other too

15:21 arrdem: amalloy: just because that array would seem like an ideal candidate for bytecode elision.

15:22 puredanger: as Rich would say "why guess when you can measure?

15:22 dpetrovics: anyone in here use kioo? (https://github.com/ckirkendall/kioo) Ran into something odd with the do-> chaining transformation

15:22 arrdem: puredanger: measuring is hard :P

15:22 puredanger: can't say I've ever seen him take that as an excuse :)

15:27 Bronsa: automating unrolling + automating inlining would make reading through core.clj so much easier

15:27 and probably removing manual chunked-seq handling :P

15:30 mmeix: as an exercise I built a digits-finder ... wondering, if this could be simplified/ improved: https://www.refheap.com/92381

15:43 dbasch: mmeix: (defn digits [x] (when (pos? x) (concat (digits (quot x 10)) [(rem x 10)])))

15:43 mmeix: although mine returns nil for 0, yours returns the empty sequence

15:44 mmeix: studying your solution ...

15:44 dbasch: also mine can be lazyfied trivially

15:44 Bronsa: dbasch: it's easy to fix it though, just change the when to an if and return () on the else branch

15:44 mmeix: it has no loop

15:45 dbasch: Bronsa: yes, it’s trivial

15:45 it should return 0 anyway :)

15:46 mmeix: amazing how much shorter experienced clojurists get it, every time ...

15:46 sdegutis: Never mind, figured it out.

15:47 mmeix: (inc dbasch)

15:47 lazybot: ⇒ 16

15:49 dbasch: (btw, not that I see a reason to lazify getting the digits of a number)

15:49 arrdem: huh

15:50 amalloy: puredanger: looks like that unrolling is a potentially huge perf win unless my benchmark is crap

15:50 https://www.refheap.com/92383

15:51 I see the arity unrolled victim with call site unpacking doing a factor of up to 5 better than the apply invocation

15:51 both apply invocations are identical

15:51 justin_smith: mmeix: it's learning and pattern recognition, you eventually learn to recognize the common tasks, and remember how to express them concisely

15:51 puredanger: arrdem: also need to cross that with frequency of use

15:52 mmeix: justin_smith ja, it's getting better (know this from teaching music theory: lots of gestalt recognition...)

15:55 arrdem: https://www.refheap.com/92385 improved benchmark..

15:56 the call site arity unpacking (basically static call arity determination) looks like the real win here

15:57 maybe this makes sense to do, but it really comes down to avoiding or rewriting apply with partial evaluation

16:03 turbofail: that would be a nice thing to have

16:05 i would like to be able to use `apply' in more places without throwing performance out the window

16:07 though i wonder how costly that partial evaluation would be in terms of compile time, in order to do it reliably

16:07 arrdem: eh 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:08 it's not expensive, it just requires purity/effect analysis and a bunch of other stuff we don't have

16:08 it'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:09 turbofail: might 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:10 arrdem: don't we have when-> or something that short circuits at the first nil value?

16:10 {blake}: arrdem, Maaaybe? =P

16:10 neatonk: http://clojuredocs.org/clojure.core/some-%3E

16:10 arrdem: (inc neatonk)

16:10 lazybot: ⇒ 1

16:10 neatonk: some->

16:10 arrdem: that's the one

16:11 {blake}: neatonk, arrdem Cool.

16:11 turbofail: i 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 Ahhh...No, doesn't work because my code is:

16:17 SagiCZ1: is 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 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 Good to have "some->" in the toolbox, tho'.

16:20 Chaze: What a strange REPL behaviour. (range 1 6622) yields a list as expected. (range 1 6623) yields ()

16:20 SagiCZ1: ,(range 1 6623)

16:20 clojurebot: (1 2 3 4 5 ...)

16:20 SagiCZ1: Chaze: try a new repl instance

16:22 Chaze: SagiCZ1: nope. It works with the latest clojure.jar, but the problem exists in counterclockwise using clojure "1.5.1"

16:22 (in case anyone wants to try to replicate it)

16:23 its not just in the REPL, it also occurs in my code at different cutoffs

16:25 SagiCZ1: oh, count is O(n) for lists i guess .. thats the problem then

16:25 justin_smith: SagiCZ1: yeah, and it breaks laziness too

16:26 SagiCZ1: justin_smith: whenever i try to make a minimal working example i always omit the part which causes the issue thinking its irelevant

16:26 arrdem: SagiCZ1: I note that your "loop" is really just (nth (iterate c foo) (count queue))

16:26 SagiCZ1: arrdem: is it? that sounds strange

16:27 arrdem: SagiCZ1: you have no data dependency between "c" and e/q

16:27 SagiCZ1: arrdem: yeah i deleted it from the example, sorry to make it confusing

16:28 if 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:28 arrdem: sure, but you could write that as (loop [[head & more] col] ...)

16:28 SagiCZ1: cool

16:29 internaly it would use first and next maybe?

16:29 justin_smith: ,(loop [coll (range 10)] (if (= (count coll) 1) (even? (first coll)) (recur (next coll))))

16:29 clojurebot: false

16:29 justin_smith: a loop with only one binding

16:29 that iterates to the end of the coll

16:29 arrdem: SagiCZ1: macroexpand tells no lies :D

16:30 SagiCZ1: justin_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:31 wait

16:31 isnt the deconstruing done only in the first pass?

16:31 justin_smith: it's done on every pass

16:31 amalloy: SagiCZ1: i generally don't like using [x & xs] to walk over a sequence. there are a few problems with it

16:32 arrdem: amalloy: do share. I was not aware of any.

16:32 amalloy: first, you can't even tell when the sequence becomes empty

16:32 SagiCZ1: ,(seq [])

16:32 clojurebot: nil

16:32 amalloy: neither 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:33 if x is nil, you know that either the collection is empty or there's a nil in it

16:33 puredanger: there are a lot of cases where I know the latter

16:33 SagiCZ1: [e & more] .. when more is empty, seq returns nil right?

16:33 puredanger: err, know that there ins't nil I should say

16:34 arrdem: SagiCZ1: seq is defined to return nil for empty sequences

16:34 lazybot: good you're still here

16:34 amalloy: additionally, 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:34 arrdem: &(macroexpand '(loop [[x & more] [1 2]] 1))

16:34 lazybot: ⇒ (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:36 arrdem: not especially helpful..

16:38 SagiCZ1: amalloy: could you provide me with a better approach with loop then? i am overthinking this too much..

16:38 amalloy: SagiCZ1: just loop over the coll, and call first when you need to, and rest when you need to

16:39 if you want to avoid calling first twice, then let-bind it to save the result

16:39 SagiCZ1: rest or next?

16:39 amalloy: wellllll, that depends what you're doing

16:39 rest is a better default choice

16:40 dbasch: SagiCZ1: 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:40 SagiCZ1: will remember that.. i know the difference is subtle and i cant think of an example where it migh matter

16:40 arrdem: &(next '())

16:40 lazybot: ⇒ nil

16:40 arrdem: &(rest '())

16:40 lazybot: ⇒ ()

16:40 sdegutis: Why is there de-dupe now instead of changing distinct based on its argument type?

16:41 puredanger: they do different things

16:41 sdegutis: Oh.

16:41 puredanger: de-dupe removes duplicates in a row

16:41 sdegutis: Also why is it not called de-duplicate?

16:41 puredanger: distinct has to keep track of all "seen" values, which is prob a bad idea on streams

16:41 who has time for names that long?

16:41 ;)

16:41 dbasch: puredanger: java :)

16:42 sdegutis: We already have "difference"...

16:42 amalloy: puredanger: i bet we could find a shorter name for 'first, too

16:42 sdegutis: And "denominator".

16:42 puredanger: car?

16:42 sdegutis: And "descendents".

16:42 arrdem: lol

16:42 puredanger: you're right, I'm going to remove as many chars from all those as possible.

16:43 amalloy: sdegutis: clojure doesn't really have a consistent approach to abbreviations, name styles, whatever

16:43 technomancy: nrplacd

16:43 dem vowels ain't free y'know

16:44 amalloy: you 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:44 EvanR: people say de-dupe in real life

16:44 puredanger: it's actually dedupe

16:45 technomancy: "unstutter" is the name I've seen

16:45 amalloy: oh good. de-dupe seemed weird to me

16:45 puredanger: I think I wrote de-dupe somewhere incorrectly and it's propagated

16:45 technomancy: (emphasizes it only removes consecutive dupes)

16:45 puredanger: http://clojure.github.io/clojure/branch-master/clojure.core-api.html#clojure.core/dedupe

16:45 llasram: technomancy: Ooh, I like that one

16:46 sdegutis: Thanks.

16:46 amalloy: (inc unstutter)

16:46 lazybot: ⇒ 1

16:46 sdegutis: Since I'm stuck using Clojure, might as well use transducers.

16:46 puredanger: that's the spirit

16:46 SagiCZ1: sdegutis: stuck using clojure

16:46 never heard that before

16:48 arrdem: I suppose unstutter of n probably wouldn't get used that often..

16:59 technomancy: http://lists.gnu.org/archive/html/emacs-devel/2014-10/msg01000.html

16:59 ^ in today's tragicomic packaging security news

16:59 mich: hey

16:59 what linux distributions are you using here?

17:00 llasram: Debian 3 eva <3

17:00 Er, "4" even

17:00 mich: llasram: do you also run X or something in it?

17:02 TimMc: technomancy: :sad-trombone

17:03 technomancy: TimMC: I don't even

17:03 arrdem: technomancy: can you sneak .elcs into an elpa package?

17:03 technomancy: it makes a non-tls request on 443 ._.

17:03 arrdem: anything you can imagine is possible at zombomacs

17:04 arrdem: technomancy: good. so we can MITM ELPA serving .elc viri :D

17:04 over "https"

17:08 mgaare: seems like there a lot of libs around (new ones even) that still use (ns ... (:use ...))

17:08 sdegutis: Because it's just so fun.

17:09 arrdem: more importantly we have a bunch of tutorials with high Google PageRank scores that use (:use)

17:09 sdegutis: If :use works then it's perfectly fine.

17:09 amalloy: ~blogs

17:09 justin_smith: also, it's how other languages usually import libs

17:09 clojurebot: blogs are never to be trusted

17:09 sdegutis: If it isn't fine then it should be removed.

17:10 This 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:10 Despite being quite aged.

17:10 amalloy: sdegutis: it is trustworthy and *four years old*

17:10 sdegutis: Hence my disclaimer, O slow poke.

17:10 amalloy: it recommends some stuff that is just Not Done anymore

17:11 sdegutis: Well I haven't actually read it.

17:11 mgaare: Isn't (use) "deprecated"?

17:11 sdegutis: I just know that Colin is trustworthy. I mean, he wrote a book.

17:11 technomancy: it's good advice if you need 1.3 compatibility

17:11 protip: you don't need 1.3 compatibility

17:11 mgaare: or just informally no-longer-idiomatic

17:12 mdrogalis: technomancy: core.async is still alpha. You never know.

17:12 arrdem: Eastwood will complain about (:use), right?

17:12 Bronsa: it should

17:12 amalloy: hey, two years ago a sentence was added to that article saying "don't use :use anymore, use :require/refer"

17:13 technomancy: is add-watch still alpha?

17:13 amalloy: but 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:13 sdegutis: In either case, it was a trustworthy blog.

17:13 puredanger: technomancy: no

17:13 technomancy: cool

17:13 amalloy: sdegutis: that's the problem with blogs. they are accurate at the time they are written

17:13 sdegutis: Personally I think my (ns) lines are way more cluttered than they ought to be.

17:13 amalloy: Only the accurate ones.

17:13 puredanger: technomancy: I removed the alpha tag from almost everything in 1.6 (reducers is one notable exception)

17:14 mdrogalis: puredanger: :)

17:14 arrdem: Bronsa: huh looks like it warns against unlimited use not against the (:use) form

17:14 sdegutis: Is 1.7 almost out?

17:14 We're still on 1.5.1 and I'm afraid to upgrade.

17:14 puredanger: sdegutis: getting there

17:14 sdegutis: But at least we upgraded from 1.3 successfully in early 2013.

17:14 justin_smith: sdegutis: amalloy: you guys are clearly unfamiliar with nostradamus' blog

17:14 Bronsa: arrdem: that's good enough for me

17:14 puredanger: sdegutis: http://dev.clojure.org/jira/secure/IssueNavigator.jspa?mode=hide&requestId=10519 is the list of remaining items

17:14 sdegutis: justin_smith: I don't know what you're talking about.

17:15 puredanger: are you Alex Miller?

17:15 puredanger: yes

17:15 sdegutis: Oh. Hi.

17:15 puredanger: Hi :)

17:15 sdegutis: I saw you on the Clojure mailing list.

17:15 You were saying stuff about Clojure 1.7.

17:15 justin_smith: sdegutis: he said that blogs are only true when they are written, nostradamus is famous for his "predictions"

17:15 arrdem: puredanger: ^:deprecated is a thing, right?

17:15 justin_smith: bad joke, sorry

17:15 puredanger: arrdem: sure?

17:15 sdegutis: justin_smith: Oh. I get the joke now.

17:15 justin_smith: It is funny.

17:15 amalloy: justin_smith: it's okay. it was a comprehensible joke

17:16 sdegutis: justin_smith: You did well.

17:16 Bronsa: puredanger: arrdem some functions in c.c have :deprecated metadata but there's no automatic warning for that

17:16 puredanger: sdegutis: we will cut a beta when we believe 1.7 is feature complete (I think feature expressions being the major question mark there)

17:16 sdegutis: I will go read about transducers again. Last time, I got halfway through the page and it looked incredibly un-huge.

17:16 arrdem: Bronsa: yeah was thinking about a eastwood ticket for reaching a ^:depricated var

17:17 sdegutis: Oh no!

17:17 arrdem: I'm pretty sure that core.async is using it as well in addition to warnings

17:17 sdegutis: puredanger: But I thought everyone hated that proposal from years ago?

17:18 arrdem: Yep. it's {:deprecated <DEPRECATED_VERSION}

17:18 sdegutis: It's just #ifdef ugh!

17:18 puredanger: sdegutis: most people I've talked to already doing effectively feature expressions but with the preprocessor from cljx

17:18 arrdem: core.async has no usages of deprecated metadata

17:18 sdegutis: Feature expressions should be #+js and #+jvm if anything.

17:19 Because, supposedly "it's all Clojure" anyway.

17:19 puredanger: sdegutis: the current proposal (and issues) are at http://dev.clojure.org/display/design/Feature+Expressions

17:19 which use #+clj and #+cljs (same as cljx)

17:19 sdegutis: Right, and I'm suggesting it use #+js and #+jvm instead.

17:20 puredanger: sdegutis: well, it's going to be clj and cljs

17:20 the biggest question remaining is about creating a new file extension for portable clojure files (.cljc)

17:20 sdegutis: Right, that's why I didn't waste my time suggesting that in any official way.

17:20 Because "NOPE" is always the answer to my suggestions.

17:21 puredanger: well, I know the feeling

17:21 noonian: seems like at this point clj and cljs make sense since there is a lot of code out there that uses cljx already

17:22 puredanger: yes, that certainly is a factor

17:24 arrdem: "common Clojure"

17:25 joshhead: If there is no cljc extension, what would we use? just .clj?

17:25 technomancy: arrdem: but then what will we call clojure-on-CL-runtime?

17:26 arrdem: technomancy: no that's still "common Clojure" because cljs is "Clojure on JS" and "Clojure" is "Common Clojure on the JVM"

17:26 technomancy: venn diagram pl

17:26 plz

17:26 arrdem: which means that Oxlang can die and just be Common Clojure in Common Clojure :P

17:27 Bronsa: arrdem: are you still working on oxlang/oxcart?

17:27 arrdem: technomancy: if "Common Clojure" (.cljc) is the subset of Clojure common to .cljs and .clj, that means it's a *jure without host interop

17:27 joshhead: "ClojureCL, not to be confused with ClojureCLR"

17:27 puredanger: joshhead: yes, that was the path we were going down

17:28 arrdem: technomancy: thus if you port *jure/Common Clojure thing to another platform, you still have Common Clojure (.cljc)

17:28 puredanger: joshhead: getting CLJS to do the right thing with .clj source in the presence of .clj macro files is an issue

17:28 arrdem: Bronsa: oxcart is pretty much dead, I'm still fooling with Oxlang which may or may not die itself

17:29 joshhead: puredanger: would this mean .cljs file extension could go away eventually too?

17:29 puredanger: no

17:29 arrdem: Bronsa: depending on whether or not I decide I've really just reinvented Haskell or Ocaml worse

17:29 Bronsa: arrdem: gotcha

17:30 arrdem: Bronsa: 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:30 joshhead: handling macro files does sound tricky

17:31 TEttinger: arrdem: was oxcart the "massive speedup for clojure" thing?

17:31 arrdem: TEttinger: yeah it was/is my GSoC static Clojure compiler

17:32 "ClojureScript on the JVM" I think is what tbaldridge was calling it..

17:32 and that's pretty apt.

17:32 joshhead: arrdem: is there another static clojure compilation gsoc project?

17:33 arrdem: joshhead: there is skummet (I may have gotten the spelling wrong)

17:34 can't actually find it googling wtf

17:34 joshhead: arrdem: just came up for me, you spelled it right

17:35 Bronsa: joshhead: I don't think the dev is working on skummet anymore btw

17:35 arrdem: joshhead: 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:36 joshhead: bummer, they claimed a 40% reduction in startup time on android, sounded promising

17:38 ah yeah that does sound expensive to maintain

17:38 arrdem: joshhead: https://groups.google.com/forum/#!topic/clojure-dev/dSPUNKSaV94

17:39 I should fix my Clojure forks to actually work... maybe after 1.7 :P

18:15 gazarsgo: stupid 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:16 guess i should use `lein new` huh

18:16 gfredericks: yeah that's easiest

18:17 gazarsgo: trying to pick up some clojure code from a gist someone pasted

18:17 dbasch: gazarsgo: what error do you get?

18:17 gazarsgo: i have a new error now that i used lein new :D

18:17 dbasch: you need at least a :main namespace and a -main [& args] function in that namespace

18:18 gazarsgo: well, 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:21 ok, that worked, sorry for rubber ducking

19:00 nextstep: new to clojure, starting a new project with some documentation where i'm expected to cite a few papers

19:01 does marginalia have facilities for this?

19:02 wei: I’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:03 e.g. (_ 1 2) => [1 2], (_ [1 2] 3) [1 2 3]

19:05 (merge-with f {:a 1} {:a 2}) => {:a [1 2]}

19:05 justin_smith: nextstep: 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:06 metellus: ,(merge-with vector {:a 1 :b 2 :d 6} {:a 2 :c 4 :d 5}) ;; wei

19:06 clojurebot: {:c 4, :b 2, :d [6 5], :a [1 2]}

19:07 amalloy_: metellus: disastrous!

19:07 metellus: oh?

19:07 wei: what about (comp flatten vector)

19:07 amalloy_: ,(merge-with vector {:a 1} {:a 2} {:a 3})

19:07 clojurebot: {:a [[1 2] 3]}

19:07 metellus: ~flatten

19:07 clojurebot: flatten is rarely the right answer. Suppose you need to use a list as your "base type", for example. Usually you only want to flatten a single level, and in that case you're better off with concat. Or, better still, use mapcat to produce a sequence that's shaped right to begin with.

19:07 amalloy: wei: 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:07 wei: that’s why I’m asking here :)

19:08 ah, then I can use concat

19:08 amalloy: wei: s/concat/into

19:09 nextstep: justin_smith: well, i was just wandering about any facility to cite papers

19:09 not necessarily as footnotes

19:10 in javadoc you can find many citations too

19:10 justin_smith: nextstep: 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:10 nextstep: i think they format them by hand, which is quit tedious

19:10 justin_smith: nextstep: wait, what do you mean by citations?

19:11 also, s/footnote/citation above, sorry

19:11 nextstep: justin_smith: i mean fancy references to papers, like what bibtex does

19:11 no worries

19:11 danneu: Is there a way to set *out* for all printlns?

19:13 dbasch: danneu: with-out-str, for example

19:14 or bind *out* to whatever

19:16 jfojtl: hi, what do you use for generating load?

19:16 danneu: dbasch: guess i can just define println so that, in development, it wraps println with a with-open and a (binding [*out* file-writer] ...)

19:16 dbasch: danneu: ugh

19:16 danneu: it's a pretty advanced logging system

19:17 feel free to steal some pages from my book guys

19:17 Bronsa: danneu: I mean, you can alter-var-root *out* but that's probably a bad idea.

19:17 dbasch: don’t reinvent logging

19:18 danneu: yeah, 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:19 justin_smith: nextstep: I was curious, so I did a quick scan of the margenalia sources, found nothing that looked like code for citations

19:19 nextstep: but it does have support for directives, seems like that could be extended to make a "citation" directive

19:24 nextstep: 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:25 danneu: Bronsa: (alter-var-root (var *out*) (fn [_] (io/writer "dev.log"))) doesn't seem to change *out*

19:26 justin_smith: danneu: (binding [*out* (io/writer "dev.log")] ...)

19:26 it's a dynamic var

19:27 danneu: justin_smith: yeah, was looking for a way to just bind it once for all my printlns

19:27 justin_smith: danneu: dynamic vars don't work that way

19:27 danneu: guess i will have to use a logging system like an adult

19:27 justin_smith: danneu: see also the persistent problem of cider output going to the wrong place

19:28 danneu: it's really not hard, some of them don't even involve making xml or properties files

19:30 danneu: *drags feet*

19:31 amalloy: justin_smith: well, dynamic vars do work that way, except when they're overridden by a binding

19:31 *out* is bound all the time in development, because the repl sets it, so alter-var-root doesn't do anything useful

19:31 justin_smith: amalloy: thanks for the precision, that's what I meant

19:31 (inc amalloy)

19:31 lazybot: ⇒ 178

19:32 justin_smith: that was a friendly "that's what I meant", not a surly one

19:33 nextstep: justin_smith: thanks, directives seem interesting

19:35 danneu: amalloy: ah right thanks

19:36 wei: amalloy: 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:36 amalloy: wei: because (concat (concat (concat ...))) is really bad if you have a lot of things to concat

19:36 wei: performance?

19:36 clojurebot: performance is http://meshy.org/2009/12/13/widefinder-2-with-clojure.html

19:37 amalloy: wei: try: (first (reduce concat (repeat 2000 [1])))

19:37 and then do the same thing with into

19:37 danneu: also into uses transients

19:38 wei: amalloy: surprisingly, concat is faster on my machine for your example. but for 20000, i get a stack overflow :)

19:39 justin_smith: wei: but do you get the stack overflow faster? that's what's important right? :)

19:40 amalloy: wei: really? when i pick a value small enough to avoid the stackoverflow, into is like three times faster

19:41 technomancy: shouldn't the lazy one be faster till it's forced?

19:42 justin_smith: yeah, if you did a quick benchmark with time / dotimes that would be a pitfall for sure

19:42 amalloy: technomancy: the lazy one still builds a linked list of thunks

19:43 and 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:43 wei: ah, I am using time.

19:44 amalloy: wei: you remembered to call (first), right? of course concat is absurdly fast if you don't ever ask for any items

19:44 wei: reduce should force evaluation, right?

19:44 dbasch: benchmarking with time is usually a waste of time

19:44 wei: https://gist.github.com/yayitswei/db118466ff8ecb813653

19:45 justin_smith: wei: it's not going to force anything if the reducing function is lazy

19:45 amalloy: yeah, it was just my lazy benchmarking. the into version is slower if i try harder

19:47 dbasch: hammockmarking

19:48 amalloy: but 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 So, "(do-this (do-that (do-the-other (parm)))" becomes ([let x (do-this...)] (if x x "")).

19:51 Just trying to decide if this is "good" or I like it, or it maybe reflects a weakness.

19:51 wei: amalloy: got it, thanks

19:51 amalloy: {blake}: (if x x y) => (or x y)

19:52 danneu: aside 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:52 amalloy: thus, just (or (do-this ...) "")

19:53 {blake}: amalloy, danneu Thanks.

19:53 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 Sometimes it's nils, but sometimes it's a map-entry {:key nil}.

19:54 Anyway, "or" and "when-let" will take care of some of the simpler cases. I probably should go through the Clojure cheatsheet again.

19:57 danneu: {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:58 technomancy: ...

19:58 nice isn't the word I would use

19:58 danneu: technomancy: 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:59 i can let my future self disarm that bomb

20:00 dbasch: someone set us up the npe

20:00 technomancy: given the tragic fact that nil exists on the JVM, clojure offers some help for coding around that flaw.

20:00 danneu: and by disarm i mean fully rwerite my code from scratch

20:00 dysfun: actually, the dealing with nil seems very DWIM to me

20:00 talios: MONADS!

20:00 * talios re-idles

20:01 technomancy: it's pretty good at dealing with nils in place of collections

20:01 pretty rubbish everywhere else

20:01 dysfun: that i'll agree with

20:01 amalloy: $timer 24 0 0 why not try using MONADS!?

20:01 lazybot: Timer added.

20:01 dysfun: but i'm still not entirely sold that lists not ending in nil is a good thing

20:01 technomancy: hehe

20:02 eh; it just depends on how you traverse it

20:02 ,(next ())

20:02 clojurebot: nil

20:02 talios: Cons | Nil

20:02 Cons | EmptyList

20:03 dysfun: i can't say it keeps me awake at night

20:03 technomancy: you'll get there some day

20:04 * talios stomach map contains nil, I need lunch.

20:18 technomancy: why do people mention monads when talking about options but not when talking about lists?

20:18 I mean, obviously it was a joke, but options are super useful even when you're not working with them monadically.

20:18 Travisty: what are options?

20:19 technomancy: Travisty: https://blogs.janestreet.com/making-something-out-of-nothing-or-why-none-is-better-than-nan-and-null/

20:19 Travisty: Ah, maybe :)

20:20 thanks technomancy

20:20 bbloom: technomancy: in the absence of continuations, the list monad + reduce is all you really need anyway :-)

20:27 technomancy: clojurebot: 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:27 clojurebot: A nod, you know, is as good as a wink to a blind horse.

20:34 zwer: technomancy 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:35 bbloom: zwer: often, none. however, you may want to explicitly distinguish between None and Some(None)

20:38 technomancy: zwer: returning an option indicates to the caller every place they should also consider a None

20:38 amalloy: zwer: 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:39 so 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:39 technomancy: zwer: 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:39 of course the compiler doesn't help you, but a missing clause stands out a lot more

20:40 without pattern matching there's not much benefit though

20:40 amalloy: technomancy: the compiler doesn't help you with what?

20:40 technomancy: amalloy: it won't tell you when you're missing the None clause

20:40 because it can't perform exhaustiveness checks

20:41 amalloy: we're assuming a dynamically-typed language with option, here? i guess that's true then

20:41 technomancy: yeah

20:41 like Erlang

20:42 bbloom: when i need something option-like, i usually use find or just nil vs [nil]

20:42 so easy to wrap some extra [] around something

20:44 technomancy: it'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:44 nathan7: technomancy: Rust's matching actually does perform exhaustiveness checks

20:44 technomancy: match some_option { Some(x) => … } won't compile

20:44 technomancy: nathan7: sure; their type system allows for it

20:44 nathan7: technomancy: yep

20:45 I've kind of lost my appetite for dynamic languages

20:45 technomancy: meanwhile google go actually implemented nulls. on purpose. M-x tableflip

20:45 * nathan7 nods solemnly

20:45 justin_smith: technomancy: I am sure you have seen the articles comparing go to algol

20:45 nathan7: I've written some Go, because it's convenient for small programs

20:45 technomancy: "Actually, not all dynamic languages have nulls."

20:45 #notalldynamic

20:46 nathan7: lol

20:46 technomancy: justin_smith: yeap =)

20:46 nathan7: but Go is best described as "unfortunate"

20:46 seancorfield: I 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:46 bbloom: *shrug* i think null pointers are a very natural idea in languages with mutability

20:46 justin_smith: technomancy: "actually, it's about ethics in generating runtime errors"

20:47 technomancy: justin_smith: =D

20:47 amalloy: bbloom: how does mutability make that more or less natural? the two seem unrelated to me

20:47 bbloom: amalloy: zero-initialized memory on allocation

20:47 vs atomic initialization

20:48 alloc and new are two distinct operations when you have raw memory access

20:48 new encapsulates alloc on the JVM, but constructors are not atomic. the GC can run during initialization, even for types w/ all final fields

20:49 unlike, say ML or Haskell, where all data constructors are atomic for immutable values

20:49 amalloy: okay, i think i see what you mean. thanks

20:49 nathan7: Box<T> in Rust is guaranteed not to be a null pointer, the box type is never constructed until after allocation

20:49 bbloom: having a pointer to nowhere is perfectly reasonable when you have a pointer datatype

20:50 nathan7: there is an unsafe pointer type which may be null, however

20:50 bbloom: nathan7: yet Rust has raw pointers and null values in unsafe code

20:50 nathan7: bbloom: yep

20:50 bbloom: it's fairly well-contained, in my opinion

20:50 bbloom: you don't need it often in normal code, but that doesn't mean it isn't useful sometimes

20:50 nathan7: bbloom: and I write a lot of unsafe code

20:50 bbloom: yeah, i've been a big proponent of unsafe code blocks since experiencing it in C#

20:50 very nice design

20:50 and i've written Managed C++ as well :-P

20:50 so i've written LOTS of unsafe CLR code

20:51 nathan7: half of my code is FFI, the other half is an experimental kernel I'm working on

20:51 and especially in the latter, building safe, zero-cost abstractions around stuff before getting to the meat of it is *amazing*

20:51 bbloom: my biggest complaint with null in java is that java doesn't have raw pointers

20:51 so there's no good fucking reason why null can't be an object

20:51 as in smalltalk or ruby

20:51 luckily, protocols in clojure can be extended to nil

20:52 null in java (and C#) is the worst of both worls

20:52 worlds*

20:52 it's not a useful data type (raw pointer) and it's not a valid object

20:52 i guess zero-initialized memory is still a think on the JVM, but that was a design mistake in my opinion too

20:52 C# is adding scala-style "primary constructors"

20:53 http://odetocode.com/blogs/scott/archive/2014/08/14/c-6-0-features-part-ii-primary-constructors.aspx

21:15 justin_smith: bbloom: that seems like a natural way to do immutible datatype initialization

21:23 cfleming: Ugh, sometimes type hinting in Clojure is a total mystery.

21:24 I'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:25 amalloy: cfleming: http://dev.clojure.org/jira/browse/CLJ-865

21:25 (let [^CharSequence chars (or ...)] (.whatever chars)) would work

21:27 cfleming: Well that sucks - at least there's a good workaround, thanks.

21:27 15 votes and a patch and it's not moving anywhere?

21:28 amalloy: cfleming: a three-year-old patch, even

21:28 cfleming: Correction, 16 votes

21:28 amalloy: IMO 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:29 cfleming: So if I understand this correctly, you can never type hint the results of a macro call?

21:29 amalloy: cfleming: you should not rely on the ability to do so. it might, for some macros, turn out to work okay

21:30 additionally, you can write your own macros to carefully preserve the metadata, if you want

21:30 cfleming: amalloy: Hoo boy. I'll add an inspection to Cursive for that, just for my own sanity.

21:30 amalloy: That going to hurt when I try to emulate Clojure's type inference though.

21:31 amalloy: cfleming: for example, it looks like -> does carry the metadata for you

21:32 ,(meta (macroexpand ' ^String (-> x (identity))))

21:32 clojurebot: nil

21:32 cfleming: Or not

21:32 amalloy: well, i didn't write it very well

21:33 hm, i guess it doesn't. interesting. it saves the metadata on x, but not on the form

21:33 (binding [*print-meta* true] (prn (macroexpand ' ^String (-> ^Foo x (identity)))))

21:33 ,(binding [*print-meta* true] (prn (macroexpand ' ^String (-> ^Foo x (identity)))))

21:33 clojurebot: (identity ^Foo x)\n

21:33 cfleming: ,(meta (macroexpand ^String '(-> x (identity))))

21:33 clojurebot: nil

21:34 cfleming: Interestingly, that does something different in my REPL here: I get {:line 1, :column 35}

21:34 amalloy: sure sure, because you've got a different reader. but that's immaterial

21:35 cfleming: Which reader is clojurebot using?

21:36 amalloy: who knows. some stringreader probably

21:36 that is, it's using the clojure reader, but a different java.io.Reader

21:36 justin_smith: ,(class *in*)

21:36 clojurebot: clojure.lang.LineNumberingPushbackReader

21:36 cfleming: Got it

21:37 Interesting, I get the same here

21:37 amalloy: justin_smith: that doesn't tell you what it's using for its own input

21:37 justin_smith: ahh, yeah

21:37 amalloy: only what *in* is bound to once you start running code

21:37 cfleming: Devious indeed

21:39 Anyway, thanks amalloy, that saved my sanity

21:39 (inc amalloy)

21:39 lazybot: ⇒ 179

21:39 justin_smith: OK, I hate multimethods so much right now

21:40 amalloy: justin_smith: def it to nil, and then call it out of spite

21:40 justin_smith: I 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:40 so now I have to make a protocol, or put it all back into a case statement again

21:40 which sucks

21:40 amalloy: did hiredman's patch to reduce locking in multimethods ever get applied?

21:41 it looks like something like it did; they use rwlocks as of 2012. so take heart: it could be much slower

21:42 justin_smith: still not fast enough :(

21:42 the_danko: evening fellows

21:42 and ladies

21:43 justin_smith: hello

21:44 * justin_smith goes off to grab the tv so he can go into proper three monitor mode (browser / repl process / editor)

21:48 the_danko: doing some 4clojure

22:14 justin_smith: cool, it's a great way to level up your clojure fluency

22:14 (inc amalloy) ; for 4clojure

22:14 lazybot: ⇒ 180

22:29 fairuz: hey guys

22:30 havenwood: fairuz: hi

22:31 fairuz: I don't know if I can post Titanium (titandb client) related question here. Their channel seems dead

22:31 justin_smith: you can go ahead, no guarantees you'll find an expert

22:40 fairuz: Ok cool. Let me play with it a bit first before asking stupid question :)

22:40 It's nice to know it's alive in here

22:40 Blizzy: lol.

22:40 bbloom: fairuz: 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:40 may or may not*

22:40 fairuz: bbloom: True

22:41 I'm referring to at least some people did reply in here :)

22:41 havenwood: fairuz: we're all bots written in Clojure

22:42 but agreed we're pleasant!

22:45 wei: what’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:46 bbloom: wei: if some unfortunate API forces exceptions on you for error handling, catch them immediately and return sensible error codes

22:46 wei: in that particular example, you can move the try down inside the let

22:47 wei: <! 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:47 or some helper that calls process!

22:47 make sense?

22:51 wei: bbloom: the channel seems to still get closed when I move the try block inside the let

22:51 i expect the second >! to trigger a “processing: true”, but that doesn’t happen

22:52 bbloom: wei: take a closer look at your compiler warnings

22:52 queue is undefined

22:53 wei: 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:54 wei: oops, i’ve updated the gist. still not working for me in its current form

22:56 if you comment out the (>! q false), it works as expected

22:58 bbloom: wei: so (go (>! ... is the same as (put! ... only the go/>! pair is slower

22:58 those are async sends

22:58 wei: aha, i was wondering what put! was for

22:58 bbloom: so there's actually no promise that the false send will occur before teh true send

22:59 wei: i’m not too particular, but i do want the true to process correctly

23:02 bbloom: i'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:03 wei: thanks for taking a look

23:06 bbloom: wei: this is certainly strange

23:08 wei: yeah, 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:08 updated the gist to explain the issue: https://gist.github.com/yayitswei/d80d51ee29dc5e2c1117

23:10 bbloom: unfortunately I have to take off for a bit. if you discover anything would you mind commenting on the gist?

23:11 bbloom: wei: *shrug* i've explored it

23:11 not gonna dig any deeper, sorry

23:11 just don't put a try/catch in a go

23:11 it's probably broken

23:11 there's lots of threats around about it being broken elsewhere

23:11 it's also just a questionable idea in the first place

23:12 i'll @ mention tim

23:12 good luck

23:12 wei: thanks anyways! sounds good

23:54 fairuz: Hi 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:54 *the

Logging service provided by n01se.net