#clojure log - Oct 30 2012

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

0:18 jonasen: bbloom: about cljs-412, I think the issues I raised here https://groups.google.com/d/msg/clojure-dev/Ge5uEqlUcJk/_b9xEVrKha8J might be related?

0:20 bbloom: jonasen: yes. there are some interrelated issues

0:20 jonasen: var resolution is a bit of a mess at the moment

0:21 jonasen: there's a bunch of janky tricks like (resolve … (dissoc env :locals) …)

0:21 jonasen: and then resolve-var vs resolve-existing-var

0:22 jonasen: and then even more weirdness in that resolve-var can throw a warning, but is sometimes used to generate a different warning, so some odd cases do or don't warn

0:22 jonasen: bbloom: I fixed resolve-var/resolve-existing-var in my fork

0:22 bbloom: at least I think I did :)

0:23 bbloom: but that's several months ago... ClojureScript has moved on since then

0:23 bbloom: jonasen: heh, yeah and new complexity has crept in to the resolution code paths

0:23 jonasen: bbloom: yes

0:24 bbloom: jonasen: but it looks like there is some good ideas in your branches… could you try to break it up a bit? for example the js/ prefixes

0:24 jonasen: that would be a great patch on it's own

0:25 jonasen: bbloom: If I remember correctly, the defprotocol (or was it deftype?) did some very strange things also.. duplicating the resolve-var

0:25 bbloom: jonasen: something is funky in there....

0:26 jonasen: sorry, I mean the defprotocol macro dupicates the logic (badly) of resolve-var

0:26 bbloom: jonasen: a good goal would be to eliminate the *cljs-warn-on-undeclared* flag and to have it always be enabled

0:26 jonasen: we should talk to dnolen and get his buy in on that

0:27 jonasen: also, i'd like to see a more robust "warnings" system in general. as it is, warnings are a side effect. it would be nice to have them be represented in the AST or :env

0:31 jonasen: regarding the "statics", i think that would be a small and welcome patch to replace them with declare/defs. I see no reason why cljs.core.List/Empty shouldn't just be empty-list

0:31 and empty-vector

0:31 same goes for the static methods

0:31 jonasen: bbloom: I totally agree with that

0:32 bbloom: jonasen: you're more likely to get your patches accepted if you distill them down to the essence & open separate patches for each. sadly that sometimes means one patch at a time & bugging dnolen :-)

0:33 jonasen: bbloom: The reason for cljs.core.PersistentVector/EMPTY is that it's a straight port from the java source

0:33 bbloom: jonasen: unsurprising :-)

0:33 jonasen: bbloom: but it's the wrong way to do it IMO

0:33 bbloom: and it confuses the analyzer

0:34 bbloom: jonasen: yup. that seems like a reasonable starting place. could you work up a patch for just that? open a ticket

0:35 jonasen: and if there is a way to get the analyzer to detect that situation: have it emit a deprecated warning!

0:36 jonasen: bbloom: I talked to dnolen about it (a few months ago) and he wasn't too keen on accepting such a patch

0:36 bbloom: jonasen: what did he say about it?

0:36 jonasen: bbloom: I

0:36 bbloom: I'd have to search the IRC logs :)

0:38 bbloom: jonasen: http://clojure-log.n01se.net/date/2012-06-20.html

0:39 jonasen: bbloom: that's the one!

0:39 bbloom: sorry, gotta run!

0:40 bbloom: But I'd love to talk about this stuff more.. there is a lot of fun work with the analyzer still!

0:40 bbloom: jonasen: i don't really buy the "pollution" argument :-P there are LOTS of top levels that should be ^:private

0:40 but aren't

0:40 jonasen: but cljs doesn't really respect private yet… heh

1:42 tomoj: hmm https://www.refheap.com/paste/3e2aa9f9ae734ba5ac89aa71b clj->el would be nice

3:38 why does pmap look at the number of available processors?

3:39 ivan: what else would it do?

3:43 tomoj: https://www.refheap.com/paste/bb37b0cf096f905d8ca995f9c

3:43 er

3:43 (+ 2 (.. Runtime getRuntime availableProcessors)) is 6, here

3:44 yet it appears to use 32 threads at a time due to the chunkiness of range

3:44 maybe that's just cus it's chunky..

3:44 ah yes

3:44 with s/(range)/(iterate inc 0)/ the behavior is as expected

3:56 ebaxt: Hi, I'm trying to extract some information from an XML-file produced by SAP. I'm using clojure.data.zip.xml and trying to figure out how I can do something like the following xpath //ATNAM[text() = "Z_BRAND"]/../ATWRT. I've tried (xml-> l descendants :ATNAM "Z_BRAND" ancestors :ATWRT text) but I get nothing, could someone please point me in the right direction?

4:19 tomoj: datomic.api/touch is confusingly named

4:20 brainproxy: tomoj: how so?

8:20 clgv: ,(type {:a 1})

8:20 clojurebot: clojure.lang.PersistentArrayMap

8:20 deg: Does metadata get passed along when, e.g. I create a new map by assoc'ing into an existing one?

8:21 clgv: deg: yes

8:21 deg: very cool!

8:22 clgv: &(let [m (with-meta {:a 1} {:type :some-map})] (type (assoc m :b 2)))

8:22 lazybot: ⇒ :some-map

8:22 chouser_log: one of the few ways lists differ from lazy seqs

8:24 clgv: chouser: you mean that lists keep metadata and lazy seqs do not, right?

8:24 chouser: well, each step of a lazy seq keeps its own metadata

8:25 clgv: yes. the implementation would have to pass on the metadata from the head if that was desired

8:25 chouser: &(let [L (with-meta '(a b) {:foo :bar})] (meta (next L)))

8:25 lazybot: ⇒ nil

8:25 chouser: ha!

8:25 &(let [L (with-meta '(a b) {:foo :bar})] (next L))

8:25 lazybot: ⇒ (b)

8:26 chouser: oh, next. That returns a lazy seq

8:26 &(let [L (with-meta '(a b) {:foo :bar})] (pop L))

8:26 lazybot: ⇒ (b)

8:26 chouser: &(let [L (with-meta '(a b) {:foo :bar})] (meta (pop L)))

8:26 lazybot: ⇒ nil

8:26 chouser: man, maybe I'm just plain wrong.

8:26 &(let [L (with-meta '(a b) {:foo :bar})] (type (pop L)))

8:26 lazybot: ⇒ clojure.lang.PersistentList

8:27 chouser: &(let [L (with-meta '(a b) {:foo :bar})] (meta (conj L 'c)))

8:27 lazybot: ⇒ {:foo :bar}

8:27 chouser: &(let [L (with-meta '(a b) {:foo :bar})] (meta (cons 'c L)))

8:27 lazybot: ⇒ nil

8:27 chouser: &(let [L (with-meta (seq '(a b)) {:foo :bar})] (meta (conj L 'c)))

8:27 lazybot: ⇒ {:foo :bar}

8:28 chouser: &(let [L (with-meta (map identity '(a b)) {:foo :bar})] (meta (conj L 'c)))

8:28 lazybot: ⇒ nil

8:28 chouser: ok, enough spam, sorry.

8:29 clgv: humm interesting though

8:29 deg: chouser: Ok, meta-question here... What is the lazybot that seems to be executing your code? Is that magic in some IRC client?

8:30 clgv: the question is if you really need to use metadata on lists in practice

8:30 deg: it's an irc bot

8:30 deg: Triggered by the "& in front of the expression??

8:30 lazybot: deg: What are you, crazy? Of course not!

8:30 deg: &(+ 40 2)

8:30 lazybot: ⇒ 42

8:30 deg: Aha

8:31 clgv: deg: but do try to not spam the channel much. it's good for examples to questions

9:09 brainproxy: tyring again to get slime-ritz / lein ritz working ... anyone successfully using it?

9:26 Cubic: Is there anything in core that would let me grab all fields from a class and expose them in my namespace?

9:26 *all static final fields

9:33 clgv: Cubic: no, there is not. maybe there is some lib to do that

9:33 antares_: Cubic: no

9:34 Cubic: Eh, well I guess it's too localized to belong there

9:34 clgv: &(loaded-libs)

9:34 lazybot: ⇒ #{bultitude.core cd-client.core cemerick.url cheshire.core cheshire.factory cheshire.generate cheshire.parse clj-config.core clj-http.client clj-http.cookies clj-http.core clj-http.util clj-time.core clj-time.format clojail.core clojail.jvm clojail.testers cloju... https://www.refheap.com/paste/6257

9:35 Cubic: What's the difference between lazy bot and clojure bot?

9:36 clgv: Cubic: lazybot is more advanced ^^

9:36 right lazybot???

9:36 lazybot: clgv: How could that be wrong?

9:37 clgv: Cubic: the clojure.reflect namespace might help you to write a macro that imports those static final fields to local symbols.

9:38 Cubic: I already wrote that macro, I just wanted to know if there already was one out of pure interest. Though I did it with java.lang.reflect, I wonder if I could do it better with clojure?

9:44 Just for reference, it's here: http://ideone.com/AHYm . It's my first nontrivial (for me) macro, so I probably did something wrong. It kinda does what I want it to, but you have to fully qualify the class names. Is there some way to avoid that?

9:45 clgv: "This page does not existPage not found."

9:45 Cubic: clgv: Sorry http://ideone.com/AHYmr8

9:47 clgv: Cubic: you would need to import the class to avoid full qualified class name

9:47 but since the code is generated why bother?

9:48 or did you mean the class you give as param to the macro must be full qualified?

9:48 Cubic: No I mean, you have to use the maco like this: (export-static-final-fields java.lang.Integer) rather than (export-static-final-fields Integer)

9:48 clgv: ,(resolve 'Integer)

9:48 clojurebot: java.lang.Integer

9:49 Cubic: oh

9:49 clgv: there is the trick ^^

9:49 Cubic: clgv: thanks I'll try that

9:50 clgv: but you could easily skip that. replace (get-static-final-fields (Class/forName (str class))) by (get-static-final-fields ~class)

9:50 then it should be resolved automatically

9:52 oh I overlooked your unquoting. well then it's not that easy^^

9:52 s/overlooked/missed/

9:53 (get-static-final-fields (resolve class)) should work

10:12 tolsen: maybe this is more of a java question, but why does (/ (Double. 4.0) (Double. 0.0)) give a divide-by-zero error while (/ 4.0 0.0) gives Infinity. I understand the latter is by IEEE standard, but why don't boxed Doubles do the same?

10:14 clgv: tolsen: my guess: the operation on the boxed doubles can check the operands whereas the native operation is just executed

10:15 tolsen: clgv: that makes sense

10:26 hmm.. if I write the equivalent boxed double program in java, I get Infinity: http://pastebin.com/rTvhBBMf . Could this inconsistency be considered a bug in clojure?

10:27 nDuff: tolsen: Would you mind using a different pastebin (gist.github.com, refheap, ideone) in the future? pastebin.com is full of flashy, animated ads for anyone not running a blocker.

10:27 tolsen: nDuff: sure. sorry

10:29 * clgv is schocked that there a people without adblock ;)

10:32 TimMc: clgv: People who work in or with the advertising industry have to.

10:32 nDuff: clgv: My last several employers, present included, have made their money off of tasteful advertisements used to promote valuable services. Seeing someone using tasteless ads to promote subpar services still make it big by virtue of their domain name rubs me the wrong way.

10:32 clgv: TimMc: for real? I'd argue that my job performs suffers from it^^

10:33 nDuff: clgv: Anyhow -- if I run adblock, and it prevents me from seeing a bug on a customer site, it's a problem. Been there, done that.

10:33 s/to promote/to fund/

10:34 mpan: &(type 4.0)

10:34 lazybot: ⇒ java.lang.Double

10:34 clgv: tolsen: you have to have a look at where the exception comes from: clojure.lang.Numbers.divide

10:34 mpan: (= 4.0 (Double. 4.0))

10:34 clgv: tolsen: so it's definitely a clojure bug or feature ;)

10:34 goracio: hi there - suppose we have func with (let ) form let returns nil but if i need to return last expr in let how i can do that ?

10:34 mpan: &(= 4.0 (Double. 4.0))

10:34 lazybot: ⇒ true

10:35 nDuff: goracio: let doesn't return nil

10:35 goracio: it returns the last thing within it.

10:35 mpan: goracio: put what you want to return in the expr after all the bindings

10:35 goracio: hmm will check ..

10:35 mpan: like, you have let, then a bunch of pairs of names and bindings, and then the expr you want

10:36 and the overall let-expr will evaluate to the expr

10:36 for example, ##(let [a 1] 1.0)

10:36 lazybot: ⇒ 1.0

10:36 _ulises: ##(let [a 1])

10:36 lazybot: ⇒ nil

10:36 mpan: I mean, usually you use let because you want to use some of the newly-bound names in the expr, but that's a silly example that doesn't

10:37 _ulises: so let can result in nil

10:37 nDuff: _ulises: I don't think anyone said it _can't_

10:37 ...not with statements taken in context, anyhow.

10:37 _ulises: nDuff: 'course; I was just curious if it'd fail :)

10:37 nDuff: *fail with an exception along the lines of "let needs a body" or something

10:38 not being cheeky

10:38 mpan: _ulises: that is very interesting but I don't know what it would be used for

10:39 I recall someone mentioned that / is treated specially?

10:40 a while back I was wondering why / existed yet I wasn't allowed to define a / in the current ns

10:43 Bronsa: user=> (defn / [])

10:43 WARNING: / already refers to: #'clojure.core// in namespace: user, being replaced by: #'user//

10:43 #'user//

10:43 user=> (in-ns 'a)

10:43 #<Namespace a>

10:43 a=> user//

10:43 RuntimeException Invalid token: user// clojure.lang.Util.runtimeException (Util.java:170)

10:44 jkkramer: ,((fn [& ∕] (let [[/ ∕] ∕] (#'/ / ∕))) 12 3)

10:44 clojurebot: 4

10:46 mpan: I'm not sure what to make of that

10:46 is this generally not advisable to do, then>

10:46 ?

10:47 Bronsa: fwiw it's just a one-line patch to LispReader.java to make that work

10:47 goracio: ##(let [a 1] 1.0)

10:48 lazybot: ⇒ 1.0

10:48 goracio: is this form valid only here :) ? ##(let [a 1] 1.0)

10:48 lazybot: ⇒ 1.0

10:48 mpan: the use of ## is a special instruction to the bot

10:48 goracio: ah i see now :)

10:49 mpan: it says, read-eval this, regardless of its position in the line

10:49 whereas # must be at the start

10:49 the rest of that is a standard s-expr

10:50 btw perhaps I picked bad example values

10:50 that could have just as easily been ##(let [a 1] "HELLO WORLD")

10:50 lazybot: ⇒ "HELLO WORLD"

10:50 mpan: or ##(let [a 1] (+ a 1))

10:50 lazybot: ⇒ 2

10:50 mpan: and usually, you'd want to do something with the bindings, as such ^

11:39 sunkencityryleh: I'm wondering how I can do an inject in clojure. I'd like to pick out an element from an array of maps and create a new map with that element as the key and the map as value.

11:40 In ruby i'd use each_with_object or inject if the other method is not available

11:40 (sorry if this is too long) [{id:1,name:'foo'}, {id:2,name:'bar'}].each_with_object({}) { |a,o| o[a[:id]] = a } results in: {1=>{:id=>1, :name=>"foo"}, 2=>{:id=>2, :name=>"bar"}}

11:41 now I do it like this in clojure (apply hash-map (flatten (map get-keypair acts))))

11:41 augustl: sunkencityryleh: inject === reduce basically

11:42 sunkencityryleh: augustl: ok I'll take a look at reduce

11:46 augustl: sunkencityryleh: (reduce (fn [curr prev] (assoc curr (:id prev) prev) ) {} [{:id 1 :name "foo"}, {:id 2 :name "bar"}])

11:47 err a bit weird naming but yeah

11:48 technomancy: is each_with_object new?

11:48 looks kind of like a gross non-functional reduce

11:49 if you're going to bash around something like that why not just close over it?

11:49 oh ruby...

11:51 augustl: technomancy: haha

11:51 as I suspected, it is added by Rails

11:51 so it's not in Ruby

11:52 Rails brings out the best of Ruby, doesn't it

11:53 sunkencityryleh: it's from rails, it's inject but you don't have to do ;memo in the end :)

11:54 technomancy: yeah but what's the point of taking it as a block arg instead of using a closure?

11:55 sunkencityryleh: hm, it's a one-liner for fold-l ?

12:00 I've been dabbling with compojure, one thing I don't get is how middleware is wrapped. doesn't (-> foo bar baz) expand to (bas (bar foo)), but it seems like the middleware is expanded run the other way. i.e. middleware that's last in the (-> expression is run first)

12:01 augustl: sunkencityryleh: correct

12:04 sunkencityryleh: augustl: it seems that there's something funky going on behind the scene there!

12:10 TimMc: foo is the request?

12:12 sunkencityryleh: TimMc: another example: (def app (-> (handler/api app-routes) debug-session1 wrap-session debug-session2) debug-session2 is the middleware that gets run first

12:12 TimMc: gets run first == outermost?

12:12 sunkencityryleh: yes, the last one

12:12 wouldn't -> wrap the other way?

12:13 TimMc: No, this makes sense to me.

12:14 If foo were the request, you'd be right.

12:14 sunkencityryleh: hm

12:15 '(-> '(1 2 3 4) rest rest rest first)

12:15 hiredman: sunkencityryleh: if you wrap a box in red, then green, then white paper, when you go to open it what order do you encounter the papers in?

12:15 sunkencityryleh: 4

12:15 (first (clojure.core/-> (clojure.core/-> (clojure.core/-> (quote (1 2 3 4)) rest) rest) rest))

12:15 TimMc: It's not about ->.

12:15 sunkencityryleh: ok so what am I missing?

12:15 I

12:15 m completely lost :)

12:15 TimMc: sunkencityryleh: If each of those middleware calls is returning a fn, then the last one in the chain is returning the "outermost" fn, which then gets the reqeust object first.

12:16 sunkencityryleh: TimMc: ah, thanks

12:17 TimMc: In hiredman's analogy, each of those fns is a piece of wrapping paper.

12:17 sunkencityryleh: I need to meditate on this

12:19 hiredman: Ok, now I see it (almost)

12:22 when I macroexpand an expression with -> why is there still clojure.core/-> left

12:22 in the expression

12:22 hiredman: because macroexpand is not recursive

12:23 sunkencityryleh: hiredman: ok tnx

12:26 TimMc: sunkencityryleh: ##(let [incw (fn [f] #(f (inc %))), firstw (fn [f] #(f (first %))), stack (-> identity incw firstw)] (stack [0 2 4 6]))

12:26 lazybot: ⇒ 1

12:27 TimMc: Here, identity stands in for the core of your app.

12:29 Here's a version that does the wrapping in the opposite order:

12:29 sunkencityryleh: TimMc: tnx

12:29 TimMc: &(let [incw (fn [f] #(inc (f %))), firstw (fn [f] #(first (f %))), stack (-> identity firstw incw)] (stack [0 2 4 6]))

12:29 lazybot: ⇒ 1

12:30 bhenry: how can i take everything but the last three items in a vector?

12:31 reverse drop 3?

12:31 TimMc: butlast?

12:31 bhenry: butlast only takes the coll

12:31 hiredman: ,(doc drop-last)

12:31 clojurebot: "([s] [n s]); Return a lazy sequence of all but the last n (default 1) items in coll"

12:31 bhenry: boom. thanks hiredman

12:31 TimMc: Ah, right.

12:31 ,(apropos 'last)

12:31 clojurebot: (last butlast drop-last take-last)

12:31 hiredman: checkout the impl of drop-last, it is pretty cute

12:32 ~def drop-last

12:32 TimMc: Oh, is that the one that uses drop and ternary map?

12:32 hiredman: dunno if that works

12:32 TimMc: yeah

12:32 TimMc: Very cute.

12:33 technomancy: oh that is clever

12:41 goracio: can we save 2 values in session ( memory store) ? something like this (session/put! :key val key2 val2)

12:44 thorbjornDX: haha, drop-last :P

13:01 jcromartie: sets are functions

13:01 but *functions are sets*!

13:02 or close enough

13:02 _ulises: yes! \o/

13:02 * jcromartie needs to take a nap now

13:04 bhenry: can things inside of a future start other futures?

13:05 ohpauleez: bhenry: Yes

13:05 they pull from the same pool though

13:19 technomancy: lynaghk: mind if I pm?

13:25 dnolen: bbloom: ping

13:25 bbloom: dnolen: what's up?

13:26 dnolen: bbloom: any thoughts on CLJS-411, I keep coming up with more cases that are broken. Not feeling so hot about the CLJS-369 changes.

13:26 bbloom: there are many more broken cases that have nothing to w/ the top level.

13:27 * bbloom adds watch to that issue :-P

13:27 dnolen: bbloom: part of the issue is that CLJS-369 assumes that lexical scope exists in JS, it does not

13:27 bbloom: even if not at the top level if you have multiple lets in the same fn scope and say you conj some fns into atom, it's going to be broken

13:27 technomancy: (require '[clojure.dev.jira :as jira]) (add-watch (jira/issue 369) (partial email bbloom))

13:28 dnolen: bbloom: nested top level dos w/ lets are broken, very bad for macros

13:28 bbloom: dnolen: bah. sorry about this.

13:28 dnolen: bbloom: I'm kicking myself for not seeing this issue much earlier.

13:29 bbloom: dnolen: give me a few minutes to investigate/think

13:29 dnolen: bbloom: k

13:31 bbloom: an ideal fix would be perhaps somehow always gem-syming let bindings only in compiler.clj - thus punting the issue to backends - some languages will have sane scoping, some won't.

13:31 bbloom: dnolen: yup. my primary motivation was to allow analysis to happen BEFORE introducing insane semantics :-)

13:32 dnolen: by that i mean downstream analysis, like my CPS transform

13:33 dnolen: bbloom: yes, I understand the utility of the fix, but we absolute need to gem-sym bindings for JS unless we introduce significantly more complicated backend machinery - I'd like to have a fix by Friday since this is a pretty nasty issue for all users of CLJS

13:33 bbloom: dnolen: ok. are you going to be around irc for a little while? i've got a couple random things to take care of, but i'll find some time in the next few hours to dig into this

13:34 dnolen: bbloom: I'll be around, thx much.

13:59 uvtc: Why doesn't the clojars page for quil https://clojars.org/quil display its project url? Quil's project.clj file has :url set, and the version is 1.6.0.

13:59 And 1.6.0 is what's displayed at clojars.

14:02 Sorry, perhaps I should ask that on a different channel.

14:03 TimMc: Was :url added after the last release?

14:04 Check the project.clj in the JAR artifact from clojars.

14:04 uvtc: Oh, right, TimMc. Good eye dear.

14:08 bbloom: "One's sentiment toward JavaScript flips between elegance and disgust without transiting intermediate states." -- http://matt.might.net/articles/javascript-warts/

14:08 truer word have never been spoken :-P

14:09 Frozenlock: I'm storing a java class in a `let' and using it further in my code, but I get an error. Is there something that prevents me from doing it? Some kind of special form behavior? (let [my-class some-class] (new my-class some-argument))

14:10 bbloom: dnolen: does Herwig's patch fix the issue? http://dev.clojure.org/jira/secure/attachment/11606/0002-CLJS-401-gensym-let-names-in-statement-context.patch

14:11 dnolen: maybe go with that and back out aea65a693 ?

14:12 TimMc: Frozenlock: I think new takes a literal symbol.

14:12 &(let [foo StringBuffer] (new foo))

14:12 lazybot: java.lang.IllegalArgumentException: Unable to resolve classname: foo

14:13 bbloom: dnolen: hacky gensyms seems like the only quick fix. anything more elegant would require deeper JS analysis

14:13 "el-cheapo gensyming" as he describes it, heh

14:13 Frozenlock: TimMc: Is there a workaround? I don't know in advance what will be the class...

14:14 TimMc: j.l.Class has some appropriate constructor methods.

14:14 Frozenlock: Thanks!

14:14 TimMc: &(let [foo StringBuffer] (.newInstance foo))

14:14 lazybot: ⇒ #<StringBuffer >

14:15 Frozenlock: Magic :)

14:15 TimMc: Frozenlock: And I would bet that there are some nice helper methods in the Clojure compiler that you could use for non-nullary constructors.

14:17 dnolen: bbloom: yeah that patch actually look ok

14:18 tgoossens: Hi

14:18 I'm here to epxress my frustrations

14:18 dnolen: bbloom: thanks for giving it a look, i'll give it a shot and add some more tests cases later.

14:18 tgoossens: At university I have to do (obligated) teamwork in java

14:19 bbloom: dnolen: then let's go with that so we un-break everybody. revert aea65a693 and apply that patch.

14:19 tgoossens: And

14:19 uvtc: hi tgoossens .

14:19 tgoossens: the rest of my team just doesn't get it. How to write simple code

14:19 apparently they like

14:19 instanceof

14:19 and switch case

14:19 bbloom: dnolen: that also means that the :shadow keys aren't necessary in the analyze phase, but we can address that later

14:19 tgoossens: so now. We have monstercode

14:19 that 1) doesn't work

14:20 2) is hell to debug

14:20 But I can't seem to convince them

14:20 it seems like "if its not complicated it is not smart / good"

14:20 uvtc: tgoossens: Do you have a specific question about Clojure?

14:20 dnolen: bbloom: I think we still need that for namespaces right?

14:21 technomancy: tgoossens: that's Java 101. anything simple is viewed with suspicion.

14:21 bbloom: dnolen: oh ugh yeah, duh, right

14:21 tgoossens: lol

14:21 * bbloom goes to fetch more coffee

14:21 tgoossens: No. Just implicitly expressing that I like the way things go in clojure :D

14:22 uvtc: Aye, she's a fine ship she is.

14:22 mpan: tgoossens: not inherently wrong to use instanceof or switch, though I'm sure -- like most tools -- they can be misused

14:23 and if your model for hierarchical relationships is expressed using inheritance, well you've got to put distinguishing logic somewhere, whether as overloaded methods, externally in some control flow block, etc

14:25 Frozenlock: TimMc: You example works fine, but for my class I get an error saying that it doesn't have the .newInstance method o_O

14:25 * Frozenlock is tumbling down the rabbit hole

14:25 TimMc: Then you don't have a Class.

14:26 or you're trying to give it more args

14:26 mpan: just curious what you get if you ask it for its type

14:26 bbloom: dnolen: when you're satisfied that this issue is resolved, i'd like to discuss my experiences working with the compiler with regard to :env, state, codeine, etc. i think i understand the issues better now & this lets issue helped my understanding a bit too

14:27 s/codeine/codegen/

14:27 tgoossens: mpan: Please don't tell me this is good: http://pastebin.com/edNSBXFX

14:28 dnolen: bbloom: sure, I'm pretty sure Herwig's patch will fix the issue. It just pushes gensym into the compiler and out of analysis.

14:28 bbloom: dnolen: yup, let me know how it goes

14:28 dnolen: bbloom: rather you patch removed it, and Herwig's patch put it back in the backend.

14:28 mpenet: Raynes: can lazybot run on password protected servers? (I would like to run it on a grove.io server)

14:28 mpan: tgoossens: meh, not particularly emotional about it one way or the other

14:28 tgoossens: hehe

14:28 mpenet: Raynes: it seems it is not the case after a quick look, but I prefer to ask before diving into the source

14:28 dnolen: bbloom: if you're referring to some of the thoughts you were working out earlier go for it.

14:29 bbloom: dnolen: that's what i get for trying to be clever :-)

14:29 tgoossens: but it's out of context of course

14:29 mpan: you could perhaps convince them to refactor it to be more OO if you shift a lot of the responsibility on the individual objects themselves

14:29 tgoossens: problem: time damnit

14:29 bbloom: dnolen: so i ran into an issue with :env in a few odd cases. for example, it's perfectly valid to have let statements that don't have a body (let [x 1])

14:30 dnolen: in such a case, there are no body statements to get the :env from

14:30 dnolen: if you need the :env in which x is a local, you don't have an easy way to get that

14:30 mpan: tgoossens: I figure, just for me personally, my past employment has drastically relaxed my standards for the sort of code which will offend me personally, but I suppose that's getting off-topic at this point

14:30 TimMc: switch statements are always trouble.

14:30 bbloom: dnolen: one possible solution would be to say that there's really an implicit do there: (let [x 1] (do))

14:30 TimMc: Sometimes there's not much you can do, though.

14:31 bbloom: dnolen: however, a similar situation applies to def

14:31 tgoossens: oh

14:31 don't forget

14:31 the code isn't working :p

14:31 mpan: well, that's a separate issue which you all must work hard to resolve

14:31 bbloom: dnolen: so my thought is that there really needs to be a before and after :env

14:31 TimMc: If Java had syntactic abstraction, you could write "xcase", which would be like "case" with an implicit break at the end of each clause.

14:31 mpan: it will occur regardless of your choice of language or style

14:32 bbloom: dnolen: @namespaces is really just the after-env

14:32 dnolen: does that make sense so far?

14:33 dnolen: i need to step out for a minute, so i'll just say the last bit and hopefully that makes sense without clarification

14:34 dnolen: if the codegen phase emitted AST nodes instead of having the side effect of printing code to *out*, then we could have a similar thing for JS

14:34 dnolen: emitting a var could have an after-env with a binding in it

14:35 dnolen: which would have made this whole issue trivial: we could have looked at the js-env side-by-side with the cljs-env to compute the shadowed symbol

14:36 dnolen: bbloom: yeah not completely following. you should probably write this up somewhere.

14:37 bbloom: also probably needs a more interesting use case then gen-syming let bindings for me to see the point.

14:37 bbloom: dnolen: eh, ok. i'll put that on the list of things to write up when i release my CPS transform (assuming i ever get it working robustly enough to announce it)

14:37 dnolen: then avoiding gen-syming I mean.

14:38 hiredman: emitting strings is pretty meh

14:38 bbloom: hiredman: yeah, i looked into emitting GClosure AST nodes & it looks promising, but i've got too many random projects going on at once already :-P

14:39 gotta run

14:41 hiredman: emitting gclosure ast nodes directly is not an alternative that occured to me, very interesting

14:43 tufflax: I'm doing (apply conj a-coll a-possibly-empty-list) but when the list is empty it's an error, but I simply don't want to add anything. Is there a nice way to work around that problem?

14:45 ro_st: does (partial) evaluate its args?

14:45 TimMc: It's a fn, so yes, the args are evaluated.

14:45 jonasac: is there are reasonable way to tame the stacktraces from running lein test, everytime a test fails my screen fills up

14:46 ro_st: ok so if i want to cache a result locally, i needn't do so separately if i'm using it in a call to partial

14:47 technomancy: jonasac: yeah, but it involves convincing chouser to release longbottom

14:48 mpenet: Raynes: nevermind, I managed to get it working

14:48 jonasac: technomancy: btw thanks for leiningen, new to clojure, was having a really rough time with everything until i met leiningen last night :)

14:49 technomancy: heh; cool =)

14:49 zerokarmaleft: tufflax: i think you want reduce instead

14:50 tufflax: zerokarmaleft yeah that works thanks

14:51 dnolen: hiredman: it could be interesting, tho it's not at all clear if AST rep is something you can expect to be stable.

14:51 technomancy: wow, sometimes you just don't realize how good you have it: https://mobile.twitter.com/jreichhold/status/263338857397907456?p=v

14:51 * technomancy carries on oblivious to 1000 other horrible horrible things you just don't have to think about when not using Java

14:52 AdmiralBumbleBee: java programmers have it good

14:52 egghead: hey Raynes, I'm playing with conch for a little process manager i'm working on, is there any way to get it to find things in the project/resources? (sh/proc "interpreter" "somefile.script") searches project/somefile.script instead of project/resources/somefile.script

14:52 technomancy: job security?

14:52 AdmiralBumbleBee: they're not using C, that's a pretty massive thing to be happy about

14:54 * AdmiralBumbleBee is grumpy today

14:54 ro_st: technomancy: find-file-in-project is now precisely what i need. thanks for your help yesterday

14:54 and you, mpenet

14:54 Frozenlock: TimMc: http://stackoverflow.com/questions/9167457/in-clojure-how-to-use-a-java-class-dynamically?lq=1 The constructor fn solved all my problems :)

14:54 hiredman: dnolen: yeah going to gclosure's ast had not occured to me, I was thinking more a long the lines of delaying generating strings as long as possible, generate some clojurescript defined js ast that can be further manipulated before being turned in to strings (or the gclosure ast)

14:54 Frozenlock: /s/constructor/construct

14:55 * technomancy is glad to have been reminded of it

14:55 ro_st: AdmiralBumbleBee: see if you can find a way to use juxt to improve your mood. i'm pretty sure that's one of the things you can use it for.

14:55 technomancy: I don't use it very often

14:55 ivan: surely it's not a leak if you lose your references to the map?

14:56 uvtc: juxt?

14:56 clojurebot: juxt is a little hard to grok but it's the best thing ever

14:56 ro_st: i still don't understand juxt

14:57 macros are easier

14:57 normanrichards: anyone know how to invoke a db function using clojureql? for example, something to the effect of: (conj! events {:name "blah" :occured_at "now()"})

14:57 bbloom: ,((juxt inc dec) 5)

14:57 clojurebot: [6 4]

14:57 bbloom: that's the best example i've come up with for juxt

14:57 * technomancy polishes his juxt fan club badge

14:58 ro_st: ok, so return a seq of the results of each successive fn to the args

14:58 uvtc: The example that the just docs include makes sense to me: ((juxt a b c) x) => [(a x) (b x) (c x)]

14:58 ro_st: yeah

14:58 technomancy: ro_st: no, return a function that calculates such

14:59 ro_st: oh, yes

14:59 technomancy: ,(map (juxt inc dec) (range 5))

14:59 clojurebot: ([1 -1] [2 0] [3 1] [4 2] [5 3])

14:59 tomoj: &((juxt min max) 1 2 3)

14:59 lazybot: ⇒ [1 3]

14:59 bbloom: uvtc: that makes sense to me too, but not everybody has mastered what i'd call "haskell signature reading skills"

14:59 ro_st: where have you found good use for it, technomancy?

15:00 wait, i can use juxt to turn (map fn1 (map fn2 coll)) into (map (juxt fn1 fn2) coll) right?

15:00 technomancy: it works great when paired with destructuring

15:00 you can turn 3 lines in a let into one

15:00 ro_st: no, that's comp

15:00 ro_st: oh. right

15:01 TimMc: francis-: clojure.lang.Reflector/invokeConstructor looks good.

15:02 francis-: Sorry, that was meant for Frozenlock.

15:02 dnolen: hiredman: it could be interesting, but it just sounds like writing a lot more code and adding another step since we still probably want to go through Closure. hard to see a big benefit.

15:03 bbloom: dnolen: i pseudo-code-ported a few of the uglier emit methods to pure functions & they saw substantial reductions in size.

15:03 dnolen: it also lets you reuse more logic b/c you are more free to re-arrange the order of evaluation without fear of side effects. that means even more savings when applied across multiple emit methods

15:03 dnolen: clearly very low priority, but IMO worth exploring

15:06 hiredman: it is kind of amusing that compilers are often pointed to as an example of functional programming, but clojurescripts compiler is not a function

15:06 dnolen: bbloom: yeah, side effect aspect of emitting strings sucks. tying in to closure AST might be worth it if the win is big enough - tho I suspect it will means we won't be able to track closure compiler so nimbly.

15:08 bbloom: dnolen: there is a helper method interface, IIRC called IR.java, which seems to be reasonably stable, but i really didn't dig in too much

15:08 dnolen: bbloom: http://code.google.com/p/closure-compiler/source/list?path=/trunk/src/com/google/javascript/rhino/Node.java&start=2249, this is the relevant file no?

15:09 bbloom: dnolen: one of them

15:09 dnolen: the Node class has lots of pseudo nodes for optimizations, etc

15:09 dnolen: see also http://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/javascript/rhino/IR.java?spec=svn1996&r=1996

15:10 dnolen: bbloom: so that file the only one we would need to deal w/?

15:11 bbloom: dnolen: maybe? i looked at this a long while ago

15:11 dnolen: this is also why i asked about the js* form

15:12 dnolen: b/c there is no obvious way to do the js* form in a glosure AST world

15:12 dnolen: however, i did come up with some hack to emit a js fragment, so that you could incrementally move towards a functional approach (i.e. one emit method at a time)

15:14 dnolen: bbloom: I agree this looks intriguing. But probably a lot of potholes. I'm curious if this would make compile times w/o optimizations slower / faster.

15:14 bbloom: dnolen: my guess? initially, slower, but ultimately faster

15:14 dnolen: slower since you go from cljs ast -> js ast -> string -> js ast -> string

15:15 dnolen: but once *all* of the emitter is converted, you can call the compiler directly

15:15 dnolen: you won't need to run the js parser

15:15 dnolen: bbloom: the slowest thing about closure isn't the parser - it's advanced optimization. it dominates everything.

15:16 bbloom: dnolen: i believe that :-)

15:16 dnolen: we could probably also get free source maps

15:16 dnolen: i believe the gclosure Node class is semi-mutable

15:16 dnolen: with the only mutable bits being things like line/column metadata

15:16 dnolen: so in the worst case everything everything else gets slower, advanced optimization roughly the same.

15:17 bbloom: yes free source maps would be nice.

15:17 bbloom: we could pretty easily wrap the static public methods if IR.java to call .setLine on each node

15:18 dnolen: i don't think worst case is slower. i think slower is just an intermediate step

15:18 once you're a 100% AST step, you cut out the disk completely

15:18 and there is no to string or from string intermediate step

15:18 which, intuitively, has to be faster? right :-P

15:19 but like you said, advanced optimizations remain the bottleneck

15:19 so the primary advantages would be functional purity, code size reduction, ease of reasoning, and free-ish source maps

15:19 clear disadvantage would be the lose of js*

15:19 however, it could be replaced by js** which returns AST nodes ;-)

15:20 goracio: my compilation time of cljs file with 200 loc takes 20-25 sec usually with simple or whitespaced optm

15:20 dnolen: bbloom: right

15:20 tomoj: goracio: with a fresh jvm?

15:20 bbloom: i have a branch somewhere that i attempted to eliminate js*

15:20 let me look...

15:20 goracio: but cljbuild auto take 4-5 sec

15:20 tomoj: ah right

15:20 dnolen: goracio: you mean 25000+200 lines of JS

15:21 goracio: dnolen: i guess so don't understand why 25k needed

15:21 bbloom: dnolen: see https://github.com/brandonbloom/clojurescript/commits/no-js-form

15:21 aaelony: n

15:22 hiredman: I have a 50 line cljs file that takes 17-20 seconds in andvanced mode

15:22 goracio: tomoj: fresh jvm ? 7 version i use

15:22 dnolen: goracio: because you 200 lines of CLJS wouldn't do anything w/ the other 6500 lines of cljs.core

15:22 w/o

15:22 bbloom: dnolen: it would also be nice to be able to memoize the output of a compilation unit

15:22 dnolen: so in the case of core, we could keep the AST in memory :-)

15:23 dnolen: bbloom: that's true

15:23 bbloom: see those last 3 commits on that branch

15:24 goracio: dnolen: 6500 ok and what for others ? _))

15:24 dnolen: goracio: sorry, not following. others?

15:24 TimMc: dnolen: 6500 < 25000

15:25 15:20 < dnolen> goracio: you mean 25000+200 lines of JS

15:25 goracio: dnolen: 25k lines minus 6500 18,5k left

15:25 dnolen: goracio: sorry just mistyped.

15:25 bbloom: dnolen: step one is minimizing usage of js*

15:26 dnolen: goracio: every CLJS app needs to load the other >6500 lines of cljs.core. w/o any optimization this will become 25000 lines of JS

15:26 bbloom: dnolen: which is already a goal :-)

15:26 TimMc: goracio: It's just like how your Clojure program won't run without the Clojure JAR file being included.

15:26 bbloom: although js* to js/ isn't much of a win, heh

15:26 goracio: actually it's google closure code if we look at it in browser

15:26 dnolen: bbloom: yeah, I think there's like 5 places in core, and the only other place we use it for inlining low level ops.

15:26 bbloom: dnolen: yup, i think we reaaaallly need better inlining support in cljs

15:26 TimMc: Except with CLJS it can't be linked.

15:27 bbloom: dnolen: we do a lot of inlining hacker via macros, where true inlining could help

15:27 dnolen: bbloom: why?

15:27 bbloom: dnolen: b/c i feel like a human compiler

15:27 dnolen: isn't that reason enough to do anything in the lisp world? :-)

15:27 hiredman: silly bbloom, humans are computers, not compilers

15:28 dnolen: bbloom: have you needed to do much inlining w/ when writing CLJS?

15:28 bbloom: dnolen: no, just in core

15:28 TimMc: hiredman: Nonsense, I've been asked to compile a report before at work.

15:28 dnolen: bbloom: so my question remains, why?

15:28 ivan: V8 inlines small functions

15:28 hiredman: TimMc: as a computer you where asked to run a compiler routine

15:28 were

15:29 dnolen: I haven't heard of anyone doing writing their own inlining macros in CLJS since we cover the bases

15:29 bbloom: right, core takes the suffering so that real apps don't have to

15:29 but i want to eat the cake too: we shouldn't need a macro-version of every major bit operation in core :-)

15:30 dnolen: bbloom: in so many ways not a priority. That likes 100 lines of code in core.clj

15:30 bbloom: dnolen: i wasn't proposing it as a priority :-)

15:30 goracio: so with clojure it appears that we can make pretty big apps without classes and objects stuff ))

15:31 bbloom: dnolen: i think minimizing js* usage should be, however

15:31 goracio: just wrote pretty big app from scratch took about 2 weeks and it was pretty easy and fun

15:32 dnolen: bbloom: yes, I think it appears in only 5? 7? places in core.cljs now. happy to take patches the remove the remaining cases that can be removed.

15:32 bbloom: dnolen: what about core.clj ?

15:32 dnolen: did you look at that random old branch i linked to?

15:33 dnolen: bbloom: yes we already talked about that - the inlining macros are the other case.

15:34 bbloom: dnolen: two separate issues. inlining vs js* usage. the js* operates on strings, not AST nodes

15:34 dnolen: the inlining macros have various bugs, btw

15:34 dnolen: max and min both evaluate their arguments multiple times

15:35 dnolen: bbloom: patches welcome ;)

15:35 bbloom: dnolen: instanceof evaluates it's arguments in reverse order

15:36 dnolen: i apparently can't contribute any patches without simultaneously breaking everything ;-)

15:36 dnolen: bbloom: heh, low hanging fruit & compiler improvements not the same kind of patch :)

15:36 bbloom: I'd happily take inlining macro fixes as one patch

15:37 bbloom: on a tangential personal note: i quit my job. anybody looking for a clojure dev in seattle? :-P

15:38 dnolen: bbloom: too bad you're not coming to the Conj

15:38 TimMc: bbloom: I'll keep an ear out. Does Seajure still exist?

15:39 emezeske: goracio: I'm not sure "pretty big app" and "in two weeks" are compatible facts :P

15:39 bbloom: TimMc: it does. i haven't been to it yet and can't go to the next one on thursday, but they apparently happen on the first thursday of each month. i'll try to make it to the next one

15:40 hiredman: next seajure meeting is this thursday at u. zoka

15:40 bbloom: hiredman: i've already volunteered to help out at the TechStars demo day on thursday; and i'm playing in the startup poker tournament that night too :-)

15:41 hiredman: I may or may not be there, and I may or may not have a a clojure powered robot

15:41 TimMc: bbloom: Is moving to Finland an option? :-P

15:41 goracio: emezeske: it' all depends of course but if consider that it is my first project in clojure and func lang then it's ok

15:42 bbloom: TimMc: no, but SF or NY are on the table

15:42 tomoj: bbloom: I'd love to hire you

15:42 TimMc: bbloom: I think ohpauleez's company does some Clojure stuff in NY.

15:42 tomoj: but can't afford you right now

15:43 bbloom: tomoj: heh :-)

15:43 TimMc: paul moved to portland

15:43 TimMc: oop

15:43 emezeske: goracio: By all means, be happy with your first project! I'm not trying to trivialize it. I just wanted to point out that it's probably not really a data point for "clojure is suitable for large programs."

15:44 tomoj: bbloom: hopefully that will change in ~3 weeks

15:44 bbloom: tomoj: what's your startup?

15:44 (i presume it's a startup, if you're expecting a financial event like that, heh)

15:45 TimMc: Why do you assume a startup? Maybe it's for homework help. :-P

15:46 uvtc: hehehe

15:46 bbloom: the ~3 weeks comment implied a financing to me, but maybe i've just been around too many startups

15:47 TimMc: Or maybe tomoj runs a turkey farm, and the Thanksgiving sales will provide money for the rest of the year.

15:48 bbloom: oh, this game is fun... maybe tomoj is planning a bank heist

15:49 hiredman: maybe he has been in contact with some helpful nigerians

15:49 bbloom: are there unhelpful nigerians?

15:49 goracio: emezeske: so i mean it appears that good apps can be written with only functions without classes and objects and inheritance stuff and so on

15:50 emezeske: i think oop is overcompicated and there is a choice like clojure that is good )

15:53 emezeske: goracio: I agree.

15:53 tomoj: bbloom: pm?

15:55 bbloom: tomoj: anytime

15:58 Frozenlock: I have a java class that requires a float. Is there a way to make it accept any number and convert it on-the-fly?

15:59 bbloom: ,(doc float)

15:59 clojurebot: "([x]); Coerce to float"

16:00 Frozenlock: er.. yes.. I'm searching a more universal answer, I have many of those class requiring specific datatypes.

16:01 andrewmcveigh: If I want to use a worker queue in clojure, is the best option still a java BlockingQueue, or similar?

16:01 bbloom: Frozenlock: depends. do you have an interface to reify? can you just simply use a function instead of a method?

16:03 Frozenlock: Well I could wrap each class in a function, each making sure the type is correct and coercing them if needed.

16:03 hiredman: andrewmcveigh: nothing wrong with a nice linkedblockingqueue

16:03 Frozenlock: I have ~15 of these classes.

16:04 * Frozenlock is loosing his hairs over this java library

16:04 andrewmcveigh: hiredman: cheers. It's how I did it last time. Just wanted to make sure I'm not missing anything new/better/etc., in the Clojure world.

16:05 TimMc: Frozenlock: What is it?

16:05 Frozenlock: bacnet4j

16:12 jcromartie: every time my friend hits me up with some kind of programing problem, it's something Clojure solves already… I'll get him one day

16:24 TimMc: Frozenlock: Sounds like a Clojure wrapper might be really useful.

16:26 jonasac: can somone point me in the right direction for using (binding) im following the examples, but still getting an IllegalStateExeption in the repl

16:26 tomoj: bbloom: so cljs-cps could be used to implement something like http://taskjs.org/ , but is more powerful, right?

16:26 Frozenlock: TimMc: Yeah I think also... all these classes and subclasses are becoming really heavy in my code.

16:28 jcromartie: jonasac sure

16:30 bbloom: tomoj: precisely

16:32 tomoj: the goal is more akin to C#'s async/await keywords

16:32 AntelopeSalad: if i do... (:require [compojure.response :as response]) , why doesn't it work when i call response/header later on?

16:32 tomoj: huh

16:32 async/await seem like task.js to me

16:32 jonasac: jcromartie: if i do (def x0) and then call (binding [x 1] (var-get #'x)) i get an IllegalStateException saying "Can't dynamically bind non-dynamic var"

16:33 AntelopeSalad: note: the code above is taken directly from the official github page for compojure

16:33 tomoj: but I never did c# - you get the full power of delimited continuations?

16:33 bbloom: tomoj: yeah, pretty much the same thing

16:33 jcromartie: jonasac: yes, you need to add the :dynamic metadata to your dynamic vars

16:33 (def ^:dynamic x 0)

16:34 jonasac: ow, the book didnt mention that :p

16:34 tomoj: ah, so your main use case for cps is just async/await? me too

16:34 jcromartie: jonasac: it's new-ish

16:34 xeqi: AntelopeSalad: are you looking for ring.util.response/header ? http://ring-clojure.github.com/ring/ring.util.response.html#var-header

16:34 bbloom: tomoj: not really. c# special cases functions that are marked with the async keyword. those functions must return objects of type ITask or ITask<T>, which are just promises with optional continuations, and then turns the async function into a state machine

16:35 jcromartie: jonasac: the fundamental docs on clojure.org are good reading, and I don't mean that in a condescending way… I go there all the time http://clojure.org/vars

16:35 hiredman: difficult to see the difference

16:35 jonasac: i guess this while chapter falls out then cause it uses binding to bind to functions passed in (making a stubbing framework), unless i do that to all the functions in my code

16:35 AntelopeSalad: xeqi: yep, thanks -- then compojure.util :as response to call it as response/header?

16:35 jonasac: while == whole

16:35 bbloom: tomoj: that works great for C# b/c a state machine with a switch statement will outperform a whole bunch of lexical closures tangled together, but it's a less general approach. it really doesn't scale in terms of complexity to a language like closure

16:35 jcromartie: jonasac: I think it's since 1.3

16:35 jonasac: what book?

16:35 AntelopeSalad: oh wait, it's ring not compojure hah

16:35 jonasac: clojure in action

16:35 bbloom: tomoj: there are a few other use cases for a CPS transform

16:35 jonasac: chapter 8.2

16:35 bbloom: tomoj: tail call optimizations is one

16:36 tomoj: another is composeable (aka delimited) continuations

16:36 tomoj: that is shift and reset

16:36 Frozenlock: TimMc: I've often use java interop, but is there some rules of thumb one should follow when doing a wrapper?

16:36 jcromartie: yeah Clojure 1.3 came out just before Clojure in Action

16:36 I think

16:37 jonasac: typically you don't need a whole lot of dynamic vars

16:37 and you can also use let

16:37 bbloom: tomoj: continuations also let's you do some fancy server side cleverness like pg does with arc and HN, but there are a lot of folks who think that's not a great idea :-P

16:37 AntelopeSalad: xeqi: i'm actually not sure now, i was trying to implement some code that someone pasted here the other day -- i'm getting aliasing errors now where it doesn't make sense

16:37 they make a call to response/header

16:38 tomoj: seaside-esque?

16:38 xeqi: jonasac: if you're just wanting to redefing functions for a test you might want ##(doc with-redefs)

16:38 lazybot: java.lang.SecurityException: You tripped the alarm! with-redefs is bad!

16:38 xeqi: hah

16:38 bbloom: tomoj: yeah, that smalltalk framework

16:38 tomoj: simplest case is pg's "arc challenge" http://paulgraham.com/arcchallenge.html

16:39 xeqi: AntelopeSalad: it should be that function but hard to tell without the paste showing how its used

16:39 AntelopeSalad: k, one sec

16:40 what was that site that supported clojure highlighting for pastes?

16:40 AdmiralBumbleBee: refheap

16:40 AntelopeSalad: thanks

16:40 AdmiralBumbleBee: and gist

16:41 egghead: anyone itc going to the LA clojure meetup this thursday?

16:41 AntelopeSalad: xeqi: https://www.refheap.com/paste/6268 , the important bits are probably lines: 12, 16-21 and 35

16:41 i also don't know if 34 will work, will worry about that later

16:41 the repl is crying that compojure.response is already aliased

16:42 xeqi: AntelopeSalad: did you restart your repl after aliasing it?

16:43 or remove the ns?

16:43 jonasac: xeqi: with-redef was just what i needed :)

16:43 AntelopeSalad: every time i make a change i run: (require 'hello-world.core :reload-all) in the repl

16:43 that is when the alias problem comes up

16:43 xeqi: if I understand correctly, that doesn't remove the old ns and redo it

16:43 AntelopeSalad: "alias response already exists in the namespace, aliasing compojure.response"

16:44 i don't even see how that's aliased though

16:44 because i never aliased it

16:44 xeqi: you didn't load the file with it aliases as described in your original question?

16:45 AntelopeSalad: load it in what sense? it never properly gets loaded because of the alias error

16:45 i am running lein repl manually

16:45 start the repl, do the reload all command, start the server

16:46 it seems you're right though, i really don't know what i'm doing haha

16:46 someone recommended to :reload-all as the "right" way to reload code

16:47 i just changed :as response to :as responsefoo and then changed my fn call to responsefoo/header and it failed with no such var

16:47 (after doing a reload-all)

16:47 that confirms that reload-all isn't pickuping up a NS change right?

16:47 *picking

16:49 TimMc: Frozenlock: I don't have any specific recommendations, sorry.

16:49 I guess just try to make something that hides all the insanity that it makes sense to hide.

16:56 AntelopeSalad: xeqi: i'm a bit more confused now, i googled to see if anyone is even using util.response and this code came back: https://github.com/ibdknox/noir/blob/master/src/noir/statuses.clj

16:56 problem is, the guy doesn't reference ring-resp anywhere -- why is he even including it?

16:59 xeqi: AntelopeSalad: most likely was meaning to replace L28-29 and forgot about it

17:00 AntelopeSalad: any thoughts on how to solve this?

17:00 i tried reloading with just (use 'ns) in the repl, same aliasing error as before

17:01 jcromartie: AntelopeSalad: sounds like :reload-all is broken

17:01 xeqi: did you restart your repl?

17:01 AntelopeSalad: no, i did not restart it

17:01 jcromartie: xeqi: the goal is to avoid restarting it

17:02 AntelopeSalad: i'll restart it though now and see

17:02 same problem

17:02 have to go, zzz... i didn't expect something so silly to be 2 hours of debugging haha -- will try again tomorrow

17:03 if the guy who wrote ring is here, please update your docs to include samples on how to use the code you've written -- beginners to the language cannot figure this stuff out with no documentation

17:04 jcromartie: AntelopeSalad: which part of ring?

17:04 AntelopeSalad: sorry I haven't followed the whole discussion

17:06 all this talk about continuations in web apps… what about representing a HTTP session as a lazy seq?

17:07 that the session is a single sequence of requests -> responses

17:10 TimMc: Continuation IDs in URLs work great until you want to bookmark something.

17:11 or use back/forward after being AFK for 15 minutes

17:12 * emezeske *ahem* hacker news *ahem*

17:12 bbloom: oh yeah, it's annoying as hell as an end user. i wouldn't actually recommend writing an app with the same bugs as HN :-P

17:13 jcromartie: heh

17:14 ivan: hey, if you have a durable lazy seq...

17:14 emezeske: Yeah, the only anoying thing is the non-durability

17:15 jcromartie: same problems as seaside though

17:15 and only slightly less debuggable

17:15 bbloom: i think it's a fundamentally failed approach b/c it's effectively the opposite of conservative garbage collection

17:15 technomancy: heh; "HREF considered harmful"

17:15 bbloom: you have external demands on resources that you don't know about

17:15 jcromartie: I dunno, I liked the idea of Seaside but I had a lot of issues

17:15 hm, yeah

17:16 dnolen: jcromartie: the continuation thing is actually good for something very specific that no-one bookmarks - complex form flows

17:16 bbloom: but i think that applies to sessions, full stop.

17:16 dnolen: even complex form flows suck... what if i'm on page 4 of 10 in a survey and then close my laptop and go for a walk?

17:17 the nature of http is stateless

17:18 dnolen: bbloom: I'm not saying there aren't other ways to deal w/ the issue, but it's improvement. I haven't messed w/ JS browser history to support enough to say whether it sucks more or not

17:18 bbloom: *shrug* session state is a hack and always will be

17:19 the only way around it is to have a persistent connection (or some kind of long polling to simulate a persistent connection)

17:19 jcromartie: then might as well say all sessions such

17:19 suck

17:19 bbloom: but even then, you need to support disconnect/reconnect

17:19 again, consider the long survey and a closed laptop

17:19 dnolen: bbloom: perhaps, in anycase DabbleDB seemed to get some good mileage out of the approach. Perhaps other people are catching w/ pure JS apps? I can't say. Haven't done complex forms in a long time.

17:20 catching up

17:21 bbloom: i think that blurring the line between the server and the client is fundamentally a bad idea

17:22 i much rather a rich client app that maintains some in memory state and a server that is either totally stateless or connection oriented

17:22 hiredman: fallacies of network computing?

17:22 bbloom: totally stateless --> session oriented

17:22 er i mean totally stateless --> totally session-less

17:23 hiredman: yup: http://en.wikipedia.org/wiki/Fallacies_of_Distributed_Computing

17:37 tomoj: oh, good, I can stop thinking about the arc challenge now :)

17:40 bbloom: tomoj: it's still a worthwhile mental exercise :-)

17:50 TimMc: Oh man, I just read that. So ridiculous!

17:51 If you can have an arbitrary web lib off to the side, there's no challenge.

17:53 jcromartie: The Arc Challenge is silly: he's starting with a language that defines a form that creates an HTTP handler in a running server, presumably?

17:53 I mean, that's all I can gather from the (defop …) form

17:56 TimMc: Yeah, right after saying that it's general purpose.

18:01 Frozenlo`: Can I use extend-type on a class to control how a new instance is created?

18:01 gfredericks: like hook into the class's constructor?

18:02 * gfredericks tries to figure out how much money he would bet against it if given the opportunity

18:03 Frozenlo`: gfredericks: Yeah, like that :P

18:04 I suppose I could make my own protocol with a method 'new2'

18:04 gfredericks: I do not believe the jvm would go along with that plan

18:05 Frozenlock: even then it'd be a method on instances rather than the class

18:05 maybe you could extend it to java.lang.Class if you don't mind the same behavior for all classes...

18:06 then you'd have to instantiate via reflection...I really don't know a lot about this.

18:07 bhenry: what is an alternative to partition where i can still have a smaller list at the end if the original collection doesn't divide evenly?

18:07 amalloy: ~partition

18:07 clojurebot: partition is probably not what you want; see partition-all.

18:07 bhenry: thanks!

18:34 etherealG: hi, I noticed on 4clojure the order of the problems seems to be a lot harder if done as it takes you through them. simple stuff like recursion comes much later than more complicated ones like interleave. anyone know which order to do them in if learning clojure from scratch?

18:35 AimHere: The problems are rated Elementary, Easy, Medium and Hard or something

18:36 You could go by that

18:38 tomoj: bbloom: yeah

18:42 I'm thinking you could get enough of the good stuff that arc has, separate the client and server better, and get by with just async/await

18:47 antares_: Monger 1.3.3 is released: http://blog.clojurewerkz.org/blog/2012/10/31/monger-1-dot-3-3-is-released/

18:50 tomoj: async/await plus a little more..

19:30 nDuff: Hrm.

19:30 For some reason nrepl.el is trying to use complete.core, but not require'ing it

19:30 so I have to explicitly do that myself.

19:31 * nDuff should probably look for any updates from the emacs-live repo.

19:34 brainproxy: nDuff: I had that problem; does it happen when you do nrepl-jack-in, or only when you're connecting from emacs to an already running nrepl server?

19:36 technomancy: hm; looks like it changed since I originally added completion

19:36 my version requires it correctly =)

19:36 brainproxy: technomancy: any luck with your attempt to get namespace (and dependent namespace) reloading working?

19:36 i.e. when using nrepl.el

19:37 nDuff: brainproxy: I don't use nrepl-

19:37 erm, nrepl-jack-in at all, so can only speak to the latter case.

19:37 technomancy: brainproxy: I got it working, but it was ugly. I don't remember if it got merged to master.

19:37 * nDuff uses gradle (as much as he hates it -- which is well into thousand-burning-suns territory), so nrepl-jack-in doesn't work so well.

19:37 brainproxy: nDuff: okay sure; how are you invoking the nrepl server?

19:38 i mean, are you doing so from the command line w/ lein, or are you embedding it w/in some project

19:38 nDuff: Neither

19:38 Using gradle because lein doesn't support Ivy

19:39 ...my build.gradle invokes clojure.tools.nrepl.cmdline/-main with args ['--port', '6678']

19:39 brainproxy: okay, maybe i'm confused; you are using nrepl.el to connect to an nrepl server?

19:39 ah gotcha

19:40 technomancy: have you had luck with ritz-swank?

19:41 technomancy: haven't tried it

19:41 brainproxy: I've made several attempts to get it working to no avail; but have no problems with swank-clojure

19:41 okay

19:44 scottj: brainproxy: I had trouble with it last time I tried. time before that it worked great. I'd contact author he's very responsive

20:46 holo: hi

20:46 mpan: hi

20:47 Scriptor: hey holo

20:49 holo: hey Scriptor

20:49 mpan: By any chance, does anyone have a recommendation for a genetic algorithm library? I imagine it would probably be in Java and work through interop, so the convenience of that would be a factor.

20:52 gfredericks: ~

20:52 clojurebot: Titim gan éirí ort.

20:53 mpan: hm, internet connection flaking out on me

20:54 btw what's ~ meant to do? random quote from the bot's collection?

20:54 gfredericks: no I sent it accidentally

20:54 mpan: is there documentation of the bots' commands?

20:54 gfredericks: was playing with the ssh client interface

20:54 antares_: ~maven

20:54 clojurebot: Help, I'm trapped in an XmlFactoryFactory!

20:54 gfredericks: I think "~" asks clojurebot to comment on the empty string about which he apparently doesn't know anything

20:54 clojurebot: is an empty string

20:54 clojurebot: Or, for instance, foo.toString().length() is (.. foo toString length)

20:54 mpan: ~test

20:54 clojurebot: forget latest is 1382

20:55 gfredericks: clojurebot: |is| an empty string

20:55 clojurebot: read-string |is| as unsafe as eval unless *read-eval* is bound to false.

20:55 gfredericks: I apparently don't know how to make him respond to "~"

20:56 mpan: wait huh? when do you eval at read-time?

20:56 I'm blanking on any examples

20:56 gfredericks: when you use #=

20:57 I don't know of any use cases that aren't addressed by the newer data readers

20:57 mpan: sorry, but what's hash-equals?

20:57 gfredericks: reader eval :)

20:57 mpan: that sounds scary

20:57 gfredericks: you'll have to try it at the repl as I think the bots disable it

20:57 try (read-string "(1 2 #=(+ 3 4) 5)")

20:58 mpan: is it the same as eval except when?

20:58 gfredericks: I think so

20:58 mpan: what's the need to upset the usual semantics of read?

20:59 or rather, what was

20:59 gfredericks: I think just when you want to read in objects that don't have their own syntax

20:59 hiredman: try (read-string "#=(+ (+ 3 4) 5)")

20:59 gfredericks: hiredman: that's slick; so it just supports top-level function calls?

20:59 mpan: what are "objects that don't have their own syntax"?

21:00 gfredericks: mpan: e.g., records

21:00 queues

21:00 finger trees

21:00 mpan: wait huh?

21:00 hiredman: gfredericks: I think, I forget, it's been I while since I've paid attention to eval reader

21:00 gfredericks: I've never had a real use for #=

21:00 hiredman: records have a syntax now

21:00 gfredericks: hiredman: looks like it also calls macros as functions

21:00 mpan: even so, why would you want them at read-time?

21:00 rather than at eval-time?

21:01 like, why would you want the eval-ed representation?

21:01 gfredericks: maybe for data that you're only reading rather than evaling?

21:01 hiredman: mpan: because the reader can read other things besides code

21:03 gfredericks: so it looks like it reads everything in the list, expects the first item to be a symbol that it resolves to a function, and then calls that function on the other (uneval'd) arguments

21:03 e.g., #=((comp inc +) 4) doesn't work either

21:07 Cubic: How do I supply a type hint for a non-primitive array?

21:08 mpan: all right, thanks guys

21:09 amalloy: &(class (into-array ["x"]))

21:09 lazybot: ⇒ [Ljava.lang.String;

21:11 Cubic: &(defn [x] ^[Ljava.lang.String x)

21:11 lazybot: java.lang.RuntimeException: Unmatched delimiter: )

21:11 Cubic: That's not valid clojure

21:11 mpan: why does (read-string "{:a {:b :c}}") produce what looks to be an exception at the repl yet still yields the expected result?

21:11 or, what does the bot say about ##(read-string "{:a {:b :c}}")

21:11 lazybot: ⇒ {:a {:b :c}}

21:12 gfredericks: mpan: no idea what sort of exception you're seeing

21:12 mpan: works fine for me

21:12 mpan: uh, I can't even reproduce it

21:12 https://www.refheap.com/paste/6272

21:13 I would expect it to be deterministic, but, well... I guess something happened

21:13 gfredericks: I feel like it could have been some kind of stale exception from the previous command

21:13 I've had spooky repls like that before

21:13 not lately

21:14 mpan: previous line was a genuine exception produced

21:14 gfredericks: but anyhow that exception looks like the one generated by my last reader-eval example

21:14 mpan: yes that

21:14 gfredericks: did it print the exception twice then?

21:14 mpan: yes

21:14 gfredericks: heckiphino

21:14 mpan: oh but, the first time was printing it as the result

21:14 gfredericks: ah ha

21:14 mpan: and the other time was printing it as an error message

21:15 gfredericks: spooky repl still

21:15 mpan: i.e. the first one was prefixed by #< and the second time wasn't

21:15 suggesting one was the toString() and the other was... uh... something

21:20 gfredericks: wait, would that constitute a repl bug? if so, should I report it somewhere?

21:29 gfredericks: mpan: probably; repls are complicated. I wouldn't know what to suggest.

21:31 mpan: the repl that lein uses is at its core nrepl? so this gets reported to nrepl?

21:33 antares_: mpan: it uses REPLy

21:34 mpan: is REPLy on top of nREPL?

21:35 oh, hm

21:35 Cubic: lein repl does create an nrepl server if I'm not completely mistaken

21:35 xeqi: reply is a frontend to nrepl, think client server

21:35 mpan: so if there's what appears to be a bug in what appears to be the repl itself? is that in nrepl?

21:35 Cubic: amalloy_: thanks, got it to work

21:39 xeqi: mpan: I'd start by filling it with reply, trptcolin is good about tracking things down and pushing it to nrepl when needed

21:39 though (read-string "{:a {:b :c}}") works fine in `lein repl` for me

22:03 amalloy: my suspicion is that mpan's repl was in some weird/broken state based on something totally unrelated, which cased the first eval-attempt to fail. later attempts worked fine because it was no longer in that state. ie, i don't think nrepl maintainers can ever repro this from just the paste above

22:05 gfredericks: at the very least his previous command, which actually generated the exception, would be needed

23:34 lil`nbv4: when i type `lein ring server` it says "That's not a task. Use "lein help" to list all tasks." i'm using lein 1.7, what could the problem be?

23:37 technomancy: lil`nbv4: best to get on leiningen 2

23:37 xeqi: lil`nbv4: do you have :plugins [[lein-ring "0.7.5"]] in your project.clj?

23:42 lil`nbv4: xeqi: I do now :) i am new to clojure, thanks

23:46 xeqi: then I also recommend using lein2

Logging service provided by n01se.net