#clojure log - Aug 25 2011

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

0:02 scottj: the difficulty of getting libraries to compile responses made me appreciate the jvm

0:28 dnolen: chouser: slides?

1:05 leeda: Hi, if I have a byte-array, how can I tell if it corresponds to a JPG image?

1:05 ibdknox: don't jpegs have a header?

1:06 leeda: Probably. So I should just try to look at the header? I was wondering if there's any library that can look at a byte-string and detect the mimetype automatically?

1:09 nkoza: leeda: http://sourceforge.net/projects/jmimemagic/

1:16 if I change an atom inside a dosync block, and the transaction fails.. is the atom reverted to their previous state?

1:29 MasseR: nkoza: AFAIK yes, but it is later retried

1:29 SO that there are no dirty values anywhere

1:29 No wait, atom? Not inside transaction afaik

1:30 nkoza: so if transaction is retried the atom will be mutated again?

1:30 MasseR: Only refs

1:30 I'd say so

1:30 Don't count on me

1:45 amalloy: go ahead, count on MasseR

2:18 scottj: where is the cljs require goog magic covered? goog.dom and goog.events don't make sense to me, I'm not sure what they refer to. [goog.Timer :as timer] makes sense, I can see Timer in the closure api. [goog.events.EventType :as event-type] makes sense I see it in the api too. but how dom/append gets mapped to DomHelper (guessing) and how events/listen maps to EventHandler (guessing) O dpm

2:18 I don't understand

2:29 nm I was in the package reference all this time not the file reference

3:29 klutometis: There doesn't appear to be a `transient?' predicate; does any know how I'd fake one?

3:32 amalloy: &(for [x [{}, (transient {})]] (instance? x clojure.lang.ITransientCollection))

3:32 lazybot: java.lang.ClassCastException: clojure.lang.PersistentArrayMap cannot be cast to java.lang.Class

3:32 amalloy: &(for [x [{}, (transient {})]] (instance? clojure.lang.ITransientCollection x))

3:32 lazybot: ⇒ (false true)

3:34 klutometis: amalloy: Ah, fantastic; thanks.

3:35 amalloy: klutometis: you can derive these yourself by having a look at ##(supers (class (transient {})))

3:35 lazybot: ⇒ #{clojure.lang.ILookup clojure.lang.ITransientMap java.lang.Runnable clojure.lang.ITransientAssociative java.lang.Object clojure.lang.ATransientMap java.util.concurrent.Callable clojure.lang.Counted clojure.lang.AFn clojure.lang.ITransientCollection clojure.lang.IFn}

3:39 klutometis: amalloy: Indeed; for some reason I was thinking of transients as magical types and it didn't occur to me that they're classes like everything else. ;)

3:40 amalloy: heh. in java everything's a type, even when that obviously makes no sense

3:40 er, an object. or has a type? i'm kinda sleepy, apparently

3:47 klutometis: amalloy: Yeah, I was about to modify my statement that "transients are types (classes)" to "transients are objects," until I realized that both are true (even in the plural).

4:12 robbe-: I have a circular structure (basically conscell with refs), how would I print a ref without the REPL exploding?

4:13 Using format instead of print seems to be a good start.

4:17 amalloy: &(doc *print-depth*)

4:17 lazybot: java.lang.Exception: Unable to resolve var: *print-depth* in this context

4:17 amalloy: &(doc *print-level*)

4:17 lazybot: ⇒ "; *print-level* controls how many levels deep the printer will print nested objects. If it is bound to logical false, there is no limit. Otherwise, it must be bound to an integer indicating the maximum level to print. Each argument to print is at level 0; if an arg... http://gist.github.com/1170222

4:21 robbe-: Oh, thanks :)

4:28 wgethis: how to do (length ("hello")) in clojure?

4:46 raek: wtetzner: (count "hello")

5:02 scottj: &(get (assoc (clojure.lang.PersistentTreeMap.) :a 1) "from")

5:02 lazybot: java.lang.ClassCastException: clojure.lang.Keyword cannot be cast to java.lang.String

5:03 scottj: wtf?

5:14 thorwil: ,(get (assoc (clojure.lang.PersistentTreeMap.) :a 1) :a)

5:14 clojurebot: 1

5:14 thorwil: scottj: how is it supposed to deliver a value for "from", when there is no such key?

5:14 scottj: is it part of PersistentTreeMap's contract that all keys be the same type? Does clojure never promote maps automatically to PersistentTreeMap?

5:14 thorwil, I expected nil

5:15 &(get (assoc {} :a 1) "from")

5:15 lazybot: ⇒ nil

5:17 thorwil: it does seem like clojure.lang.PersistentTreeMap does not like non-keyword keys (?)

5:17 scottj: no it's fine with them, they just have be the same and you have to request the right one

5:17 thorwil: ,(type (assoc {} :a 1))

5:17 clojurebot: clojure.lang.PersistentArrayMap

5:18 scottj: &(get (assoc (clojure.lang.PersistentTreeMap.) "a" 1) "from")

5:18 lazybot: ⇒ nil

5:19 robbe-: Is there a difference in behaviour with nested dosync blocks vs one big dosync block enclosing all operations?

5:19 thorwil: ic

5:22 scottj: robbe-: I don't think so, http://soft.vub.ac.be/~tvcutsem/talks/presentations/STM-in-Clojure.pdf

5:23 robbe-: Hey, that's my professor.

5:23 :D

5:24 thorwil: scottj: you don't need the get in front, even

5:25 scottj: robbe-: I don't use the stm, was just going off the couple words about that in his slides, there may be differences in the real implementation

5:34 dhaivat: Clojure has waaaay too many parentheses. I wrote one web app, and it (in total) had 748 parentheses.

5:36 scottj: dhaivat: save them, you can recycle them with cut and paste

5:49 Chousuke: dhaivat: have you ever counted the number of parentheses in a java app?

5:50 robbe-: (or the loc)

5:50 :p

5:50 Chousuke: you're likely to have more parens in a typical java app than in a clojure app that does the same thing :P

5:50 they're just better hidden

5:54 scottj: (defn write [code, like, this]

5:54 (to really, piss, people, off);

5:54 )

8:35 MasseR: Damnit, if clojure would just start up faster, I'd probably write all my tools in it

8:35 manutter: jark

8:36 or nailgun I suppose

8:37 MasseR: Having a server running for command line programs seems kinda wrong. Been thinking that though

8:37 Hm.. jark seems interesting

8:38 manutter: Yeah me too, if I had more RAM to throw around I probably would think about it some more

8:38 MasseR: Oh yeah, that too

8:38 what is the memory footprint of jvm/clojure?

8:39 bsteuber: how about js startup time?

8:39 if it's good, why not use clojurescript for your tools?

8:40 MasseR: openjdk

8:40 I'm intrigued by it, but not enough to install sunjdk )

8:40 :)

8:43 manutter: looks like I'm soaking up just over 500M on a clean start of the jark vm

8:44 That's going to be subject to the params you start the vm with of course.

8:48 Chousuke: at one point I was running the cake vms persistently at about 32 MB at start

8:48 it really depends on the JVM parameters

8:50 I think the default is to preallocate 128MB or something

8:50 the JVM expects that it will be running something enterprisey for a long time so it optimises for it :P

8:55 MasseR: Hmm... I think I'm going to like jark

8:57 manutter: jark is kinda fun :)

8:58 No! No! Bad programmer! Close that window and get back to PHP!

8:58 *sigh*

8:58 MasseR: manutter: I feel you

8:58 FOr a while I laughed. Then I realized I'm in the same boat

9:01 agz: (-> 1 #(+ % 1)) -> gives me java.lang.Integer cannot be cast to clojure.lang.ISeq

9:01 MasseR: jark doesn't recognize my -main function :/

9:02 agz: is it right?

9:02 (-> 1 inc) -> is just fine

9:02 MasseR: ,(-> 1 #(+ % 1))

9:02 clojurebot: #<CompilerException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.ISeq, compiling:(NO_SOURCE_PATH:0)>

9:03 manutter: You can't use the -> macro with the #() macro, bad things happen

9:03 MasseR: manutter: Why is that?

9:04 agz: ,(-> 1 (fn [x] (+ x 1)))

9:04 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.UnsupportedOperationException: nth not supported on this type: Long>

9:04 manutter: (macroexpand '(-> 1 #(+ 1 %)))

9:04 agz: and this why not?

9:04 manutter: doh

9:04 ,(macroexpand '(-> 1 #(+ 1 %)))

9:04 clojurebot: (fn* 1 [p1__8345#] (+ 1 p1__8345#))

9:04 manutter: eh, maybe I'm misremembering

9:05 agz: feels a bit inconsistent :(

9:05 manutter: I thought something like this had come up before and that was the answer

9:05 but looks like the cases aren't quite parallel

9:05 agz: hmm -> can be parallelized? :O

9:06 manutter: no, wait

9:06 agz: (don't think so)

9:06 dnolen: agz: -> is pure syntax transformation. you're pushing anything through anything.

9:06 manutter: I missed the fn* 1 in the expansion

9:06 I was right after all

9:06 agz: yep but then why not accept the fn -version

9:06 dnolen: ,(-> 1 ((fn [x] (+ x 1))))

9:06 clojurebot: 2

9:06 agz: ,(-> 1 (fn [x] (+ x 1)))

9:06 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.UnsupportedOperationException: nth not supported on this type: Long>

9:06 manutter: ,(macroexpand '(-> 1 (fn [x] (inc x))))

9:07 clojurebot: #<ExecutionException java.util.concurrent.ExecutionException: java.lang.UnsupportedOperationException: nth not supported on this type: Long>

9:07 dnolen: agz: you need to wrap in an extra set of parens.

9:07 agz: dnolen: what is the special character there? :O

9:07 dnolen: ohh .. OHHH!!! thx :D

9:07 dnolen: ,(-> 1 (#(% + 1)))

9:07 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>

9:07 manutter: basically, -> is a macro that re-writes your source code

9:08 dnolen: ,(-> 1 (#(+ % 1)))

9:08 clojurebot: 2

9:08 manutter: There we go

9:08 I didn't know there was a workaround, but that makes sense

9:08 agz: yeah it's really cool

9:09 another one guys

9:09 I installed a lots of leiningen stuff

9:09 and my interpreter "lost" my agents :)

9:10 (def a (agent [])) (send a conj 1) (await a) <- and no response, interpreter hangs(?) as the thread never finishes

9:10 manutter: Hmm, I've seen that one

9:11 agz: I've deleted ~/.m2 and just started a plain new clojure 1.2.1

9:11 manutter: Yep, same thing happened to me

9:11 agz: but still no

9:11 manutter: ohh what was the solution? :O

9:11 manutter: I ended up re-installing a bunch of stuff, I think my .lein dir and possibly my .m2 dir

9:11 clean re-install of the latest lein cleared it up

9:12 agz: ahhaaam

9:12 so you deleted .lein also?

9:12 (where lein selfinstall puts stuff??)

9:14 MasseR: \o/ I broke jark already :D

9:15 manutter: agz: I believe that's how I fixed it, it's been a few weeks

9:15 MasseR: lol, how?

9:16 MasseR: manutter: By doing 'jark lein' on a non lein directory

9:16 I can't start the jark vm server anymore

9:16 manutter: oh, ouch

9:16 agz: manutter: thx, i will try it out!

9:17 MasseR: "exception failure: int_of_string"

9:18 manutter: MasseR: the vm server isn't hanging around stuck somewhere is it?

9:19 MasseR: pgrep jark and pgrep jvm both return nothing

9:19 manutter: how about "java"?

9:19 netstat -lanp | grep 4005

9:19 MasseR: ha! There

9:20 Yup, jark lein kills it

9:20 Even on a lein project

9:21 manutter: I've never used jark lein, what's it supposed to do?

9:22 MasseR: I don't know. That's what I was testing

9:23 But even still, apparently unlike jark website says, jark isn't started automatically and it doesn't recognize the -main function so as it is, it's quite useless

9:23 ./

9:23 :/

9:25 manutter: hmm, I'm pretty sure I did a simple "hello world" type jark script, but I don't recall what the exact syntax was.

9:26 MasseR: http://pastebin.com/nmG7xXHZ that's quite as simple as it gets. (The dofoo was for testing)

9:28 manutter: how did you run the command?

9:29 MasseR: ./foo.clj and jark foo.clj

9:29 manutter: I wonder if it matters which dir you start jark from vs which dir you start the script from, hmm...

9:29 did you get any errors or just no output?

9:30 MasseR: With little modifications I get no output but also no errors (If I do (def foo (println "foo"))) it prints the foo), but that version prints 'clojure.lang.Var\n2'

9:31 manutter: when I run your script locally I get "java.io.FileNotFoundException: Could not locate foo__init.class or foo.clj on classpath"

9:32 oh, duh, I didn't name it "foo".

9:33 There, with proper naming, I get "Hello world" as my output.

9:33 MasseR: jark client version 0.4

9:36 Odd

9:40 manutter: I just re-installed and restarted jark, and I get "Hello World" just fine using your code.

9:40 openjdk vs sun-java6?

9:42 robbe-: Is filter the idiomatic way to find an element in a list?

9:42 I need only one result, so that would be (first (filter ...

9:45 MasseR: openjdk

9:46 manutter: MasseR: I'm on sun-java6, maybe thats the difference?

9:48 Somelauw: openjdk works for nonreparenting windows if you modify your .xinitrc, but sunjdk is what you need to get intellij to work. Since I don't use intellij, I go for openjdk.

9:49 MasseR: manutter: I'll try changing

9:57 No luck with suns jdk

10:03 If I prepend the file with a (comment) it doesn't throw any errors

10:46 Scorchin: Is there any way to do order-by on multiple keys in a map? E.g. I have a list of maps holding :name and :sport keys and I want them to be grouped by :name and then for each :name — e.g. "Bob" — to have their sports in ascending order.

10:57 gtrak: how would you get to a servlet request attribute from a custom ring middleware?

10:59 babilen: Scorchin: Take a look at sort-by -- For example: (sort-by (columns [:name :sport] YOUR_MAP)) (not necessarily correct, play with it)

11:00 Scorchin: Err, you probably want to switch :name and :sport -- I'll be back later.

11:01 tufflax: babilen what is that columns fn?

11:03 Scorchin: babilen: thanks, will check it out

11:04 gtrak: oh, I see there's a :servlet-request attribute

11:04 tufflax: Scorchin sort seem to be stable, so you can sort by sport first, then by name. Or of couse you can make a new comparator fn, it's easy in this case. But maybe there is something better... hmm

11:05 seems*

11:06 MasseR: Is clojureql capable of sqlite btw?

11:07 coopernurse: MasseR: haven't tried it, but I suspect if you get the right JDBC driver it would work

11:07 gtrak: clojureql doesn't do any ddl stuff

11:08 coopernurse: perhaps this one: http://www.xerial.org/trac/Xerial/wiki/SQLiteJDBC#UsingSQLiteJDBCwithMaven2

11:10 which in project.clj would look like: [org.xerial/sqlite-jdbc "3.6.16"]

11:10 again, haven't tried it though..

11:12 looks like that driver has some native code. not sure how that plays with maven/lein - presumably you'd have to manually install the .so/.dll file

11:14 MasseR: coopernurse: xerial?

11:19 coopernurse: MasseR: yeah, that appears to be one java sqlite driver, which might work with clojureql

11:19 lrenn: I don't suppose I could get some volunteers to run: (java.net.InetAddress/getByName "4294967303")

11:20 For some reason it resolve to an IP for me even though dig/nslookup/etc don't resolve.

11:20 also different on Lion vs. Snow Leopard which is blowing up a test.

11:21 coopernurse: ; user=> (java.net.InetAddress/getByName "4294967303")

11:21 ; #<Inet4Address 4294967303/72.3.199.16>

11:21 that's on clj 1.2.1 - snow leopard

11:21 Fossi: user=> (java.net.InetAddress/getByName "4294967303")

11:21 java.net.UnknownHostException: 4294967303 (NO_SOURCE_FILE:0)

11:21 linux gentoo

11:21 lrenn: See, wtf?

11:22 coopernurse: lemme try some os tools with that. very ood

11:22 Fossi: 1.6.0_26 Java HotSpot(TM) Client VM

11:22 coopernurse: odd

11:22 $ host 4294967303

11:23 4294967303 has address 72.3.199.16

11:23 lrenn: yeah, host gives me two different ips, then says not found.

11:23 coopernurse: honestly, I'm not sure what that even means.. what would a dns server do with that

11:23 lrenn: is it converting the string into bytes or something...

11:23 coopernurse: great question

11:24 dig resolves it too

11:24 lrenn: host 42949673034294967303 has address 8.15.7.1174294967303 has address 63.251.179.13Host 4294967303 not found: 3(NXDOMAIN)

11:24 Fossi: Host 4294967303 not found: 3(NXDOMAIN)

11:24 dig resolves it for me

11:25 manutter: ,(+ (* 72 256 256 256) (* 199 256 256) (* 3 256) 16)

11:25 clojurebot: 1221002000

11:25 manutter: interesting...

11:25 Fossi: stil, what kind of address is that supposed to be?

11:26 lrenn: when it resolves, we all resolve it to something different, so i don't think that's it.

11:26 it's not supposed to be an address, we have some code that was expecting an UnknownHostException.

11:26 One of our devs upgraded to Lion and the test started failing.

11:27 we all use macs at work, but I checked my linux box on home and it does the same thing Lion is doing (resolves)

11:27 coopernurse: lemme try a linux vps box I have

11:27 ok, interesting

11:28 it appears to depend on your nameserver

11:28 linux vps - running bind locally, doesn't resolve

11:28 linux vm on my mac - hitting a DNS server on my dlink access point - does resolve

11:32 lrenn: thanks guys. i don't want waste anymore of anyones time on it.

11:32 strange though...

11:32 Fossi: the implementation might have changed

11:32 // if host is an IP address, we won't do further lookup

11:32 if (Character.digit(host.charAt(0), 16) != -1

11:32 || (host.charAt(0) == ':')) {

11:32 lrenn: Lion actually resolves it to 0.0.0.7

11:32 :)

11:33 Fossi: that smells like a fishy bit to me

11:33 cemerick: Do pull requests always notify everyone that has commit privs on a repo?

11:39 Fossi: lrenn: i would guess it's somehow interpreted as an ipv6 address

11:39 and depending on the machines setup that might resolve or not

11:39 lrenn: Fossi: thought of that, but it returns an instance of IPV4

11:39 #<Inet4Address 4294967303/72.3.199.16>

11:39 (even the odd 0.0.0.7)

11:40 gotta split, thanks again everyone.

11:45 babilen: Scorchin, tufflax: Ah, sorry - forgot about that. It is : http://paste.debian.net/127362/ -- It is from "The Joy of Clojure" 7.1.2

11:49 Scorchin: babilen: I google'd it when I started getting stack traces :)

11:49 babilen: but, thanks!

11:50 babilen: Scorchin: Actually just read http://clojuredocs.org/clojure_core/clojure.core/sort-by (the third example is exactly what you are looking for and uses an anonymous function instead)

11:51 Scorchin: babilen: yup, that's what I'm using :)

11:51 but now I've got another issue :/

11:51 babilen: Scorchin: Perfect -- Sorry for the confusion :)

11:52 Scorchin: I now have a sorted list of maps — where maps containt :name and :sport keys — but I only want the very last :sport key for each :name. This seems like a difficult thing to pull off :/

12:00 whidden_: Hi guys, question: When using swank.clojure where do the pre/post function assertion messages go? I don't seem to see them on in any of the regular places.

12:01 arohner: whidden_: it depends on how your code was called

12:02 usually, it goes to where the repl output goes, but if the call happened in another thread, it might go to the console (the terminal where you started the app)

12:03 whidden_: actually, wait. there are no messages, unless the assertion failed, or you did {:post [(do (println ...) true)]}

12:03 whidden_: arohner: hmmm that is what I thought too, and I don't see any messages for assertion failure in those places. Is the assertion a checked or unchecked exception?

12:04 arohner: whidden_: it's a j.l.AssertionError

12:05 what does your assertion look like?

12:07 whidden_: arohner:

12:07 {:pre [(string? label) (map? resource-map) (or (empty? resource-map) (:map-start-time resource-map))

12:07 (map? tsk) (:duration tsk) (or (nil? fit-time) (float? fit-time) (integer? fit-time))]

12:07 :post [(map? %)]}

12:07 arohner: whidden_: do the assertions fire if you call the fn in the repl?

12:07 whidden_: yes

12:08 arohner: whidden_: so then what's the problem?

12:09 whidden_: arohner: when running from another thread or jar file, i don't see the assertion messages anywhere and thus don't know the cause of the failure.

12:10 arohner: whidden_: there isn't a message by default. the assertion just throws the j.l.AssertionError if it fails

12:11 whidden_: maybe you're not catching the exception? or catching it somewhere you don't intend?

12:11 whidden_: arohner: <bing!> crap... I see now what is going on when running.. I catch all those errors in one bucket :(

12:11 arohner: catching it in another place and thinking its an entirly different beast... thanks.. mystery solved.

12:11 arohner: np

12:20 lobotomy_: hmm, trying to run lazybot, it says: Exception in thread "main" java.io.FileNotFoundException: Could not locate irclj/core__init.class or irclj/core.clj on classpath: (registry.clj:1)

12:20 i ran "lein deps" which put an irclj jar into libs/

12:20 michaelr525: hhey!!

12:21 lobotomy_: and the ./lazybot does "java -cp lib/*: ..." so it should pick that up?

12:24 manutter: lobotomy_: are you building a jar file with lein jar?

12:24 or lein uberjar

12:25 lobotomy_: hmm, no, just "lein deps", edit .lazybot/info.clj, then "./lazybot"

12:31 pjstadig: cemerick: yes they do, but i think you get the option to pare the list

12:31 cemerick: pjstadig: hrm?

12:31 oh, notifications

12:31 pjstadig: cemerick: yeah

12:32 cemerick: pjstadig: how? I don't see any X's, hovers, etc…

12:34 lobotomy_: ok, "lein jar" from the main lazybot dir gives the same error, irclj not found...

12:34 wonder if my lein on this machine is somehow broken. grr

12:34 michaelr525: Error occurred during initialization of VM Could not reserve enough space for object heap

12:34 pjstadig: cemerick: yeah never mind...they just show a list of "people to be notified" on the right hand side now

12:35 i thought they used to be checkboxes

12:35 cemerick: Yeah; it makes me feel a little bad to send a pull request and pop notifications on dozens of people.

12:35 technomancy: they used to let you choose who to notify with a big ol' "notify everyone who has ever touched this project" featured prominently at the top

12:35 now it's just committers I think, but it's easy for them to turn down the noise if someone's annoyed

12:36 cemerick: technomancy: Where's *that* knob? I get a pile of noise from repos I have commit on…

12:36 I think you can only turn them on/off globally, which sucks.

12:37 technomancy: it's hidden pretty deep iirc

12:38 oh, never mind; I'm thinking of the option to abdicate committership

12:39 mbac: curl: (22) The requested URL returned error: 404

12:39 Failed to download https://github.com/downloads/technomancy/leiningen/leiningen-2.0.0-SNAPSHOT-standalone.jar

12:39 :(

12:39 simonjb: hi all, I've got a newbie swank-clojure question maybe someone could help me with -- if I've messed up my VM, say by redefining some fundamental function, can I reset swank without restarting emacs?

12:41 mdeboard`: simonjb: Did you do M-x swank<tab> to see if tab-completion has like a swank-reset ? I believe it does

12:42 lobotomy_: now on this other machine, "git clone https://github.com/flatland/lazybot.git" is failing with fatal: https://github.com/flatland/lazybot.git/info/refs download error - The requested URL returned error: 403

12:42 mdeboard`: swank-repl-restart or something

12:42 mbac: oh that was head in the repo not the stable one

12:42 mdeboard`: lobotomy_: Use the git:// or git@ directory

12:42 imo

12:42 simonjb: mdeboard`: I'll have a look, thanks!

12:43 lobotomy_: ok, s/https/git/ indeed works... sigh

12:45 simonjb: mdeboard`: M-x swank<tab> isn't finding anything

12:45 mdeboard`: wow did i say git@ directory? ugh

12:45 anyway lobotomy_ glad it worked

12:45 lobotomy_: ok, "lein jar" is giving the same error on this machine as well

12:46 so in short, lazybot doesn't seem to compile

12:46 mdeboard`: simonjb: uh hm, were you in a clojure-mode buffer when you tried it?

12:47 simonjb: mdeboard`: yes, also tried from the slime-repl buffer -- maybe my swank setup is different from yours?

12:48 mdeboard`: simonjb: Sounds like you tried to do too much getting emacs configured properly for clojure

12:48 lobotomy_: (though on this machine, just "lein" seems to hang forever, after displaying the help text. wtf. how do i determine whether it's my lein or lazybot (or something else) that's broken here)

12:48 mdeboard`: simonjb: I say that because you're' having the problems I did when I first started. Simple fact is that most of the tutorials and blog posts about using slime-repl with emacs are woefully out of date

12:49 simonjb: All you need is leiningen and clojure mode, really.

12:49 lobotomy_: lein takes forever because the jvm takes forever

12:49 lobotomy_: you mean literally forever?

12:49 mdeboard`: simonjb: So if you've got like "require swank" or "require slime" somewhere in your .emacs/init.el you're doing it wrong

12:50 lobotomy_: Oh. Well, no. :P

12:52 simonjb: mdeboard`: I'll check -- I think my setup is pretty minimal -- I installed clojure-mode using package.el and then used leiningen to install swank-clojure; I'm using clojure-jack-in to start swank and slime

12:53 mdeboard`: yeah that sounds about right

12:53 Oh

12:53 right, sorry, M-x slime-repl<tab> will yield restart results. I'm not sure about restarting swank independently of emacs. I'd suspect just stopping the slime-repl then jacking in again would be helpful... but I'm assuming you tried that and it didn't owrk?

13:00 technomancy: simonjb: you should be able to kill the *swank* buffer and re-run M-x clojure-jack-in

13:01 mdeboard`: Oh yeah, derp. Been awhile since I've clojured anything :-\

13:01 tufflax: Scorchin babilen (sort-by (juxt :a :b) ...) is better that columns, because it's in core and it takes all kinds of fns not only keywords, so you can do (sort-by (juxt first second) ...)

13:03 lobotomy_: (heh, "lein" does not in fact hang forever, it just takes around 74 seconds to finish)

13:04 technomancy: lobotomy_: probably you are starting up a non-daemon threadpool which shuts itself down after 60s

13:04 lobotomy_: i am? hmm... ok

13:05 technomancy: fsvo "you"

13:05 lobotomy_: this is from the lazybot main dir

13:05 simonjb: technomancy: perfect! thanks very much -- super awesome job on all your clojure tooling by the way!

13:07 lobotomy_: i see "lein" takes the same 74ish seconds from just my home dir, which has no project.clj in it

13:07 so why would lein start a non-daemon threadpool? is my install broken?

13:09 technomancy: oh, if it's happening in ~ then it must be something else

13:12 lobotomy_: but i'd be more interested in getting lazybot to work/compile/anything, not sure if that's related to the state of my lein :)

13:13 mdeboard`: lobotomy_: I had trouble compiling one of amalloy's project's too :( 4clojure

13:13 I say we blame him

13:13 well, not compiling. I couldn't get 4clojure to work locally because of some threading issue or another that i can't remember

13:14 babilen: tufflax: thanks

13:18 amalloy: in fairness, lazybot is more Raynes's than mine

13:18 babilen: tufflax: Indeed, much better.

13:19 mdeboard`: amalloy: :P

13:19 tufflax: babilen :)

13:20 srid: is there actually a ring middleware that autocompiles ssas -> css? (google doesn't show any)

13:21 lobotomy_: amalloy, so how do i compile and/or run lazybot?

13:22 amalloy: lobotomy_: i just use lein swank to start interactive development

13:22 and ./lazybot will launch it externally

13:23 * srid is impressed with the level of detail in the README of this clojure project https://github.com/kornysietsma/twitter-example

13:24 lobotomy_: ok, wtf. lein swank seems to actually work

13:25 ./lazybot gives that error it always did (see above)

13:27 amalloy: lobotomy_: that's a lot of text to search to try and find your complaint

13:29 lobotomy_: git clone https://github.com/flatland/lazybot.git ; cd lazybot ; lein deps ; ./lazybot

13:29 result: Exception in thread "main" java.io.FileNotFoundException: Could not locate irclj/core__init.class or irclj/core.clj on classpath: (registry.clj:1)

13:29 there is in libs/ an libclj*.jar, which was put there by the lein deps

13:29 and the ./lazybot script says something like java -cp lib/*:... so it should notice it too

13:31 amalloy: works for me

13:31 mdeboard`: works on my machine*

13:32 amalloy: fresh clone of lazybot with lein 1.5.2

13:32 lobotomy_: lein 1.5.2... hmm, i have 1.4.2

13:33 technomancy: lobotomy_: lib/* requires java 6

13:37 lobotomy_: i have java 1.6.0_26

13:42 lein 1.6.1 and ./lazybot gives the same error... sigh

13:43 but now "lein jar" gives a different one: Exception in thread "main" java.security.AccessControlException: access denied (java.lang.RuntimePermission modifyThread) (NO_SOURCE_FILE:1)

13:54 but why does "lein swank" work when "./lazybot" doesn't. ps aux|grep java tells me that with "lein swank", the full command line includes "-classpath <long list of jars including lib/irclj*.jar>". but the ./lazybot script should also do that, with the -cp thing... arrrgh

13:55 fucking hell, i'll soon start programming in c, this java+clojure+leiningen+whatever bullshit is just ridiculous

13:55 and i'll link all the libs statically too! so there

13:56 mdeboard`: lobotomy_: Calm down :P I agree it is frustrating working with the JVM

13:57 sometimes*

14:00 lobotomy_: well, i'd just like to know exactly how to debug this mess

14:00 is there a "clojure classpath & class loader basics for dummies" guide somewhere?

14:01 mdeboard`: lobotomy_: You ARE developing in WinXP right???

14:01 lazybot: mdeboard`: Oh, absolutely.

14:01 lobotomy_: hmm... "lein repl" starts up, gives the same exception (can't find irclj*), but still starts up; but then i enter anything into the repl and it says java.security.AccessControlException: access denied (java.lang.RuntimePermission createClassLoader)

14:02 mdeboard`: lobotomy_: Are your permissions set properly?

14:02 lobotomy_: apparently not

14:15 amalloy, so the newest lazybot is working for you... could you list exactly what you did (which commands) to try it out?

14:15 mdrogalis: Is anyone planning to write a book or longer tutorial about Conjure?

14:16 amalloy: $ git clone git@github.com:flatland/lazybot.git tmp-lazy; cd tmp-lazy; lein deps; ./lazybot

14:16 mdeboard`: mdrogalis: Get Joy of Clojure, and/or Practical Clojure

14:17 mdrogalis: Okay, thanks mdeboard!

14:17 amalloy: mdrogalis: did you really mean Conjure?

14:17 gtklocker: Hello

14:17 amalloy: i don't think conjure is very popular

14:17 mdrogalis: Yeah, amalloy

14:18 Really? Does it not get much pull for web frameworks, then?

14:19 amalloy: no, not really. depending on where you want the tradeoff between magic and control, most people use noir or compojure

14:19 lobotomy_: amalloy, and you have leiningen 1.5.2 and java... what?

14:19 amalloy, the first command there is hopefully equivalent to "git clone git://github.com/flatland/lazybot.git tmp-lazy"

14:20 amalloy: lobotomy_: yes, though note that git@github.com works even if you don't have commit rights

14:20 java version "1.6.0_20"; OpenJDK Runtime Environment (IcedTea6 1.9.9) (6b20-1.9.9-0ubuntu1~10.04.2); OpenJDK Client VM (build 19.0-b09, mixed mode, sharing)

14:21 lobotomy_: Permission denied (publickey). <- no it doesn't :p

14:21 whidden_: Is list all callers C-c C-w c, a slime function, not working for clojure?

14:21 amalloy: well, you have to have a key with github

14:21 whidden_: probably not

14:21 lobotomy_: i have leiningen 1.6.1 and java 1.6.0_24 (official sun thing)

14:21 and, yeah, it doesn't work

14:22 whidden_: <sigh>, if only I had another 36 more hours to the day, i'd try to fix that... oh well.

14:23 amalloy: whidden_: you'd need to fix it on the swank side, which i suspect would be pretty complicated

14:23 in the meantime, M-x find-grep is good enough most of the time :P

14:23 lobotomy_: git clone git://github.com/flatland/lazybot.git tmp-lazy ; cd tmp-lazy ; lein deps ; ./lazybot # crashes due to not finding irclj

14:24 whidden_: yeah, find-grep is our friend.

14:24 technomancy: whidden_: there's some who-calls support in swank-clojure, but it's a bit rudimentary

14:25 (I didn't write it)

14:25 amalloy: lobotomy_: lib/ should contain irclj-0.4.0-20101122.230502-4.jar

14:26 whidden_: technomancy: ok, i'll just stick with find-grep for now.

14:26 amalloy: (though wouldn't it be nice if Raynes ever released a non-snapshot version)

14:27 lobotomy_: other machine with java 1.6.0_26 (64 bit) does the same thing

14:28 10597 2011-08-25 21:27 lib/irclj-0.4.0-20101122.230502-4.jar

14:28 that's there on both machines, lein deps fetches it

14:29 what else... both machines are running ubuntu

14:29 9.10 for the java 1.6.0_24 one and 10.04 LTS for the newer 64-bit one

14:33 scottj: anyone know if clojure will ever automatically change maps into PersistentTreeMaps?

14:34 cemerick: those are for sorted maps

14:34 amalloy: scottj: huh?

14:34 S11001001: scottj: it's extremely unlikely

14:35 scottj: amalloy: I'm using congomongo 1.4 and it was giving me them

14:35 amalloy: S11001001: yes, i guess that's a good answer even though i don't understand the question. any way you read it it's not likely to happen

14:37 scottj: cemerick: ahh I was looking for PTM in the code but will search for sorted

14:37 amalloy: scottj: i can't think of a reason for it to sort things for you, but i also can't see why it would matter if it did

14:37 cemerick: scottj: You almost certainly shouldn't care about the implementing class.

14:38 scottj: amalloy: if you ask PTM's about a key with the wrong type you get an exception instead of nil, as opposed to other map types

14:38 amalloy: cemerick: say, do you know why sorted maps don't have a transient mode? is it somehow technically unfeasible, or just too much work to implement?

14:38 scottj: cemerick: that's what I thought, but turns out not in this case

14:39 &((assoc (clojure.lang.PersistentTreeMap/EMPTY) :a 1) "a")

14:39 lazybot: java.lang.ClassCastException: clojure.lang.Keyword cannot be cast to java.lang.String

14:39 amalloy: scottj: well, that depends on the comparator you use for your sorted map

14:39 cemerick: scottj: keys in sorted maps or sets need to be comparable

14:39 scottj: &((assoc {} :a 1) "a")

14:39 lazybot: ⇒ nil

14:40 scottj: cemerick: in which case you have to care about it

14:40 amalloy: but sure, fair enough

14:40 cemerick: scottj: you have to care about the semantics of the data structure, *not* its implementing class

14:41 amalloy: I don't know right off. Probably more like, no one's gotten around to it.

14:41 I know a fair bit of the transients impl. was done by cgrand, so it may simply be a matter of someone stepping up.

14:41 dnolen: amalloy: I think the goal was to have transients for all the current persistent data structures.

14:42 sadly Clojurists are not as avid about putting new data structures together as the Scalaists

14:42 amalloy: hah

14:42 we have hash maps, who needs data structures

14:42 cemerick: Someone could probably knock them out using deftype in fairly short order.

14:42 ibdknox: (inc amalloy) ;)

14:42 lazybot: ⟹ 1

14:42 * cemerick says oh-so-casually

14:43 dnolen: amalloy: that really is part of the problem. you can go really far with the core data structures even if they are not always ideal.

14:44 amalloy: dnolen: yeah, that wasn't all a joke

14:44 ibdknox: dnolen: this is a problem with any language I think, though

14:45 dnolen: ibdknox: I dunno. Haskell and Scala seem to have data structures for every occasion.

14:45 mdrogalis: I'm trying to make a function that generates an infinite sequence of numbers, 1 to infinity

14:45 amalloy: ibdknox: what? nothing's ever stopped java developers from writing more classes

14:45 mdrogalis: Why does this cause a stack overflow? http://pastebin.com/fnM1EkNF

14:45 amalloy: (iterate inc 1)

14:45 ibdknox: dnolen: they may have many of them

14:45 mdrogalis: I wanted to write a function for it, amalloy. :)

14:45 ibdknox: dnolen: how often do they get used?

14:45 mdrogalis: Just to play with constructing an infinite sequence

14:45 ibdknox: dnolen: you have to first teach people what a finger tree is before they'll use it

14:45 dnolen: ibdknox: precisely when you need them which always at the worst time ;)

14:46 amalloy: $google dbyrne stackoverflow prime sequence

14:46 lazybot: [recursion - Recursive function causing a stack overflow - Stack ...] http://stackoverflow.com/questions/2946764/recursive-function-causing-a-stack-overflow

14:46 ibdknox: haha

14:46 amalloy: mdrogalis: ^ is why

14:46 mdrogalis: Thanks amalloy! Ill read it now

14:46 ibdknox: amalloy: I meant more that people won't use them even if they're there, simply because they don't know what they are, or often, know enough to look for something else

14:48 mdrogalis: amalloy: My function doesn't use filter

14:48 amalloy: mdrogalis: you also seem to be mixing data types. a has to be a seq in order to concat it, and it has to be a number in order to add it

14:48 it uses concat

14:48 which is also lazy

14:48 but now that i look again, that's not your problem

14:48 mdrogalis: Ah, yeah that's wrong, amalloy

14:48 amalloy: your problem is that everything here is evaluated eagerly

14:49 mdrogalis: What's forcing it to do that?

14:49 manutter: mdrogalis: how are you calling generate-infinite-seq?

14:49 mdrogalis: concat?

14:50 (take 10 (generate-infinite-seq))

14:50 amalloy: no, just the fact that everything is eager unless you say so

14:50 manutter: ok, I see it

14:50 amalloy: &(nth ((fn f [n] (concat [n] (f (inc n)))) 1) 1e5)

14:50 lazybot: java.lang.StackOverflowError

14:50 manutter: I think I see it

14:50 amalloy: &(nth ((fn f [n] (lazy-seq (concat [n] (f (inc n))))) 1) 1e5)

14:50 lazybot: ⇒ 100001

14:50 manutter: Isn't concat going to evaluate it's args first?

14:51 mdrogalis: In short, I'm jut trying to write a function that takes 0 parameters, or 1 parameter. If 0 parameters, join "1" with "2 3 4 5"

14:51 If 2 parameters, return "2 3 4 5.."

14:51 manutter: or rather, clojure is going to evaluate the args to concat before passing them to concat proper

14:51 mdrogalis: Ah, that's much clearer, manutter

14:51 So I need lazy-cat?

14:51 manutter: sounds like a winner :)

14:51 amalloy: mdrogalis: that would probably work, but it's not the right answer

14:51 manutter: I've never used it so I won't vouch for it personally ;)

14:52 mdrogalis: Right, the types are still wrong

14:52 amalloy: or, not the idiomatic one

14:52 meh. the issue is more like "you shouldn't be using concat"

14:52 mdrogalis: I know it's not idiomatic Clojure. I just want to try making an infinite sequence myself.

14:52 Why is that?

14:52 amalloy: mdrogalis: because you're just adding one element to the front of a sequence. that's what cons is for

14:53 mdrogalis: So I'm really looking for an "append" sort of function?

14:53 IE [1 2] + [3] => [1 2 3]

14:53 ibdknox: ,(doc cons)

14:53 clojurebot: "([x seq]); Returns a new seq where x is the first element and seq is the rest."

14:53 manutter: Yeah, I think you might be better off using lazy-seq directly and cons

14:53 amalloy: no, you're not. you want to put stuff in front

14:53 just like you're doing. but use cons, not concat

14:53 mdrogalis: I thought that's inefficient?

14:53 ibdknox: ?

14:53 mdrogalis: Okay, wait. What's the difference, then?

14:53 manutter: if you're being lazy, efficiency is not an issue ;)

14:53 amalloy: &(cons 1 [2])

14:54 lazybot: ⇒ (1 2)

14:54 mdrogalis: Ah. I guess changing the head makes sense, that would be quick..

14:54 amalloy: &(concat [1] [2])

14:54 lazybot: ⇒ (1 2)

14:54 amalloy: cons is like the fastest list-building operation there is

14:55 concat has to do a bunch of work, create a lazy seq, look inside some other lazy seqs...cons is just a java constructor invocation

14:55 mdrogalis: I was in here once and someone told me not to use it because it's low level

14:55 Okay. So now I'm really confused. When do I want cons, concat, or lazy-seq?

14:55 amalloy: mdrogalis: indeed. use (iterate inc 1) instead. but since you want to rewrite low-level operations, use low-level operations :P

14:55 dnolen: speaking of which, chouser, you never tried using finger trees w/ to represent source when macros have you?

14:56 mdrogalis: amalloy: Well said. Makes sense.

14:56 dnolen: writing macros I mean.

14:56 amalloy: dnolen: compile-time efficiency problems with match?

14:56 manutter: mdrogalis: so you want cons instead of concat to put them together, and lazy-seq to keep them from generating eagerly

14:57 amalloy: (inc manutter)

14:57 lazybot: ⟹ 2

14:57 dnolen: amalloy: yeah I think the source of slowness w/ large matches is not the compilation algo, it's the source concatenation.

14:57 we're not doing it very intelligently, but maybe it makes sense to just use a better data structure.

14:58 mdrogalis: I would have thought that (lazy-seq [1] [2] [3]) would return [1 2 3]

14:58 Why's it just return (3)?

14:58 ibdknox: ,(doc lazy-seq)

14:58 clojurebot: "([& body]); Takes a body of expressions that returns an ISeq or nil, and yields a Seqable object that will invoke the body only the first time seq is called, and will cache the result and return it on all subsequent seq calls. See also - realized?"

14:58 amalloy: &(do [1] [2] [3])

14:58 lazybot: ⇒ [3]

14:59 mdrogalis: I guess the doc doesn't make sense to me.

14:59 amalloy: ~source lazy-seq

14:59 ibdknox: amalloy: that link is broken

14:59 https://github.com/clojure/clojure/blob/f128af9d36dfcb268b6e9ea63676cf254c0f1c40/src/clj/clojure/core.clj#L557

14:59 mdeboard`: Yeah those docs are impenetrable sometimes

15:00 worst part of clojure imo

15:00 amalloy: it expands to, basically, (fn [] [1] [2] [3]), which evaluates the first two for side effects and returns the second

15:00 *third

15:01 mdrogalis: How is that useful? :/ Im not getting it

15:01 amalloy: uhh

15:01 manutter: mdrogalis: look at the docs for lazy-seq on clojuredocs.org

15:01 amalloy: it's useful for people trying to do things differently than you are

15:01 mdrogalis: Okay. I think something just isn't clicking about manipulating sequences, is all.

15:01 amalloy: but generally, don't try to put multiple expressions in a (lazy-seq ...)

15:02 it will just end in tears

15:02 ibdknox: http://clojuredocs.org/clojure_core/clojure.core/lazy-seq

15:03 mdrogalis: Ohhh, I think I get it

15:03 So lazy-seq generally takes 1 sequence as its argument?

15:03 manutter: mdrogalis: the argument to lazy-seq is a function body -- when you call (lazy-seq [1] [2] [3]), it's like writing a function (defn lazy-body [] [1] [2] [3])

15:03 oops, cross-talk

15:03 mdrogalis: Its starting to make sense now

15:03 clojurebot: Huh?

15:03 mdrogalis: Its like passing it a generator?

15:03 amalloy: mdrogalis: it takes an expression, which it later evaluates to produce a sequence

15:04 mdrogalis: And it only produces that sequence on demand, right?

15:04 manutter: mdrogalis: that's basically it

15:04 mdrogalis: That makes much more sense

15:05 manutter: It does not give you the seq, it gives you a function that gives you a seq

15:05 mdeboard`: mdrogalis: Functions in Clojure (and lisps in general) only RETURN their final value, aka the value in the tail position. All other values NOT in the tail position (aka not last) simply get evaluated for their side effects. They do not RETURN anything.

15:05 ibdknox: mdrogalis: lazy seqs are clojure's version of the generator pattern, yes.

15:06 mdrogalis: Okay, yeah I got'cha now

15:07 That cleared up a lot for me, thanks guys!

15:08 tomoj: a bit weird to say that it gives you a function

15:09 ibdknox: tomoj: hm?

15:09 tomoj: unless I misunderstood, that lazy-seq gives you not a seq but a function that gives you a seq

15:09 ibdknox: ,(type (range 0 3))

15:09 clojurebot: clojure.lang.LazySeq

15:10 tomoj: which is suggestively correct maybe but sounds misleading, since you actually get a seq, and not a function

15:10 ibdknox: ,(satisfies? iseq (range 0 3))

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

15:11 ibdknox: ,(seq? (range 0 3))

15:11 clojurebot: true

15:11 arohner: is there already a bug for a gen-class not paying attention to an :import?

15:11 tomoj: &(isa? clojure.lang.LazySeq clojure.lang.ISeq )

15:11 lazybot: ⇒ true

15:11 arohner: i.e. (:import foo.Bar) (:gen-class :methods [method [Bar] boolean])

15:11 mdeboard`: You're tearing me apart, isa?

15:11 ibdknox: hahaha

15:12 cemerick: arohner: That's by design IIRC. All class names in gen-class specs must be fully qualified.

15:12 arohner: cemerick: why?

15:13 if I have an import that matches, why not use it?

15:14 cemerick: arohner: I can only speculate at the rationale.

15:14 arohner: cemerick: sigh. Ok, thanks

15:15 cemerick: gen-class is often used in areas where the class in question hasn't been generated yet — so I can imagine that trying to carefully resolve only those short class names that are available and imported might have made an already-complicated macro even moreso.

15:17 One could write a gen-class+ that addresses that fairly easily.

15:17 (if one were to really care about it, that is)

15:19 coopernurse: hey folks, I just got a lein build working on a hosted Jenkins service.. cloudbees.com - they have a free tier. (sorry, this sounds like an ad, but I'm just some guy..)

15:19 technomancy: coopernurse: cool! did you have to install lein yourself?

15:19 coopernurse: I can share the incantation if anyone is interested.. they basically give you a private EC2 slice, and lein will happily bootstrap

15:20 technomancy: I followed the guide you had here (sort of) https://github.com/technomancy/leiningen/wiki/Using-Leiningen-with-the-Jenkins-CI-server

15:20 technomancy: I've contacted cloudbees about getting it preinstalled, but I haven't heard back from them in a while

15:20 coopernurse: but it turned out to be even easier

15:20 srid: coopernurse: where can I find details on limitations of their free tier?

15:20 coopernurse: srid: http://www.cloudbees.com/platform-pricing.cb

15:20 you get 300 minutes/month

15:20 on a ec2.small

15:21 srid: coopernurse: thx. oh, does it require me to pay for the EC2 instances?

15:21 coopernurse: technomancy: here's the build steps I used: http://i.imgur.com/2fJPG.png

15:22 srid: given the pain involved in keeping hudson running reliably for more than few days, i'd be inclined to pay for such a service anyway.

15:22 coopernurse: srid: agreed - it's just one of those things you don't want to deal with..

15:22 Hodapp: hmm.... we use Jenkins here and it rarely breaks

15:22 srid: would be awesome if they visually integrate with github

15:22 technomancy: coopernurse: lein test! is deps, clean, test fwiw

15:23 coopernurse: technomancy: ah, thanks

15:23 srid: its not so much about jenkins breaking as maintaining the whole ecosystem of CI servers.

15:25 technomancy: there's also travis for OSS CI; very interesting crowdsourced model

15:41 amalloy: wandering back into a previous conversation, mdrogalis and tomoj, i would say that it gives you a sequence which is backed by a function instead of by data

15:42 dnolen: nice, Racket recommends someone writing a Clojure compat layer, https://github.com/plt/racket/wiki/Intro-Projects

15:45 kwertii: anyone heard of Opa? (http://lambda-the-ultimate.org/node/4336) seems like an ideal sort of application for Clojure

15:46 ska2342: Hi. Is anyone around who understands the impl of the history of Refs?

15:47 ibdknox: kwertii: I'm wary of anything that abstracts away that you're programming for the web. Those sorts of things are always very limited

15:48 kwertii: ibdknox: what do you mean by abstracts away that you're programming for the web? from what I can see, Opa is explicitly about writing web apps and only web apps

15:48 ibdknox: " aiming to make web programming transparent"

15:48 maybe I'm reading that wrong

15:49 kwertii: ibdknox: that means it handles generating boilerplate clientside javascript, validation, XSS protection, database CRUD, etc. for you

15:49 ibdknox: http://opalang.org/

15:50 Somelauw: opa sounds funny

15:50 ibdknox: it means grandfather in German lol

15:50 amalloy: sounds yiddish

15:50 gtrak: how do I use the merge-servlet-keys fn in ring.util.servlet? I'm trying to add a middleware that blocks on authentication errors that depends on that

15:50 kwertii: I don't like the syntax, but it looks like (conceptually) an ideal way to set up web dev. I always hated doing all that redundant boilerplate CRUD code that's 99% exactly the same

15:50 amalloy: hey, i was right!

15:50 technomancy: means father in Korean iirc

15:50 solussd: I guess if anything goes wrong, you can use say 'oopa!'

15:50 kwertii: amalloy: Yiddish is almost exactly the same as German :p

15:51 ibdknox: kwertii: rails tries to do this too

15:51 I've also tried to d oit

15:51 kwertii: ibdknox: sort of... and fails...

15:51 ibdknox: eh

15:51 no real webapp is simple enough to make almost completely declarative

15:51 which the goal of something that abstracts crud boilerplate

15:51 is*

15:52 amalloy: my webserver is just (constantly {:status 404})

15:52 ibdknox: haha

15:52 gtrak: django's admin stuff seems pretty neet, but it's a headache to dig through the layers of abstraction

15:52 amalloy: seems pretty declarative

15:52 ibdknox: ^ best programmer ever

15:52 * ibdknox bows

15:53 ibdknox: gtrak: that's how it always is

15:53 kwertii: ibdknox: consider, say, a user signup page that just collects a username and password. How many times do you have to redundantly declare that in a Rails app (or any other standard web framework)? You have to have a database schema declaration (migration in Rails), a model that maps the db to Ruby, an HTML layer page that shows a box for it, Javascript that validates it on the client, and a controller that glues all of that together.

15:53 ibdknox: yep

15:53 Somelauw: ibdknox: In dutch as well :D

15:53 ibdknox: and you could standardize that

15:53 but what happens when it needs to be slightly different?

15:53 kwertii: ibdknox: yeah, 90%+ of that could be autogenerated

15:53 ibdknox: websites are rarely consistent

15:54 they're not like applications sadly

15:54 they're more like interactive images than anything

15:54 ivan__: ibdknox: yeah, and its not like a lot of the autogened stuff actaully takes long to write from scratch either

15:54 kwertii: ibdknox: it's a pareto distribution, 80% of your cases will be the same. do those automatically and the other 20% manually. ideally, instrument the autogenerator to allow you to plug in modification code, something clojure would be good at.

15:54 * amalloy is jealous that ibdknox apparently works on applications that are consistent

15:54 ivan__: its just we have a desire to automate things :P

15:55 gtrak: I was trying to learn web programming with django a couple years back, I scrapped that and know I'm building everything from scratch with clojure as a learning experiment

15:55 ibdknox: kwertii: scaffolding is generally frowned upon these days

15:55 gtrak: too much crap at once

15:55 ibdknox: gtrak: I bet you'll have a much better understanding of the web as a result

15:55 ivan__: that new seam framework uses it, i immediatly stopped looking at it

15:56 amalloy: gtrak: yes, i like using ring because i can tell exactly what i'm actually doing

15:56 ivan__: spring roo...

15:56 gtrak: yea, that's the plan, though I'm constantly paying the 'new and shiny' context switching overhead

15:56 clojurescript came out and punched me in the face :-)

15:57 ibdknox: lol

15:57 gtrak: me too I guess

15:57 I've spent many years trying to create the ideal web framework

15:57 kwertii: ibdknox: I'm not sure what you mean by 'scaffolding'. if you mean it in the Rails sense of a code template engine that spits out some templates for you to edit, that's not at all what I mean. I mean an engine that auto-generates stuff at runtime which is parameterizable at runtime.

15:58 ibdknox: kwertii: I've written that too

15:58 kwertii: ibdknox: full stack from db to javascript?

15:58 ibdknox: kwertii: I ended up essentially replacing *all* of the crud functionality it generated at run time

15:58 kwertii: ibdknox: I would say that means there is some sort of design flaw somewhere :p

15:58 ibdknox: haha

15:58 you may think so

15:59 and I'm sure there were flaws

15:59 kwertii: ibdknox: I imagine that every step would be potentially customizable, but any given use of it would not need to customize more than 10% or 20%

15:59 gtrak: functional programming has more possibility of composition than OO anyway

15:59 dnolen: interesting, kinda suspected, Opa is built by a bunch of French OCaml hackers.

16:00 https://github.com/MLstate/opalang/graphs/languages

16:00 kwertii: it's 2011 and we still have netsplits?

16:00 mbac: i know kwertii

16:00 wtf

16:01 ibdknox: kwertii: I'm not sure I agree. In my experience you still need to customize those sorts of components quite a bit

16:01 mbac: dnolen, is that a breakdown of LOCs in their git rpos?

16:01 dnolen: mbac: in the opalang repo yeah

16:02 mbac: wow it's based on ocaml?

16:02 opalang

16:02 kwertii: ibdknox: how about building it in pieces... instead of the Grand Unified Vision, some code that would handle generating Javascript for the client that validates the input and AJAX-syncs it to the database layer, all transparently?

16:02 dnolen: lang itself seems a bit odd syntax wise, like a JavaScript-y OCaml

16:02 kwertii: ibdknox: also, without such a framework, you're writing 100% of the code custom anyway, so if you can get that down to 90%, that's a win in some sense

16:03 mbac: yeah, it's thwarting my expectations

16:03 pjstadig: f

16:03 ibdknox: kwertii: some of what you just described is what I'm going to do with pinot

16:03 pjstadig: oops sorry stray keystroke

16:03 ibdknox: kwertii: though my goal isn't to create standard forms, just make them very easy to create

16:04 kwertii: remotes, for example handle abstracting the ajax away

16:04 kwertii: ibdknox: why Rails owned the market is because it automated 10% of what we were all doing in Struts or something similar.. and struts automated 10% of what we were all doing in manually created JSP stuff..

16:04 ibdknox: that sounds very cool

16:05 ibdknox: kwertii: Rails lowered the barrier to entry I think. What they found out in the long run, however, was that they lowered it too far

16:05 kwertii: I think a library of common components can be built

16:05 kwertii: I don't think we have the base for such a thing yet though

16:05 kwertii: ibdknox: they stopped caring about improving it conceptually when they realized they could go around and charge ${ large number} for training and speaking fees

16:06 ibdknox: yeah, it will have to be built up piecemeal and then assembled later

16:06 ibdknox: what I suspect we'll start to see are libraries that include cljs and clj

16:06 and you just require those in the right places

16:06 and the rest is magic

16:06 lnostdal: clojure needs a hackable reader :>

16:07 ibdknox: at some level, pinot is an example of that

16:07 kwertii: ibdknox: a layered system.. there could be a high level Opa-like abstraction on the very top for people who don't care about customization. or, if you do, you can rip that layer off and use the component subsystems yourself, directly.. much like Noir / Compojure / Ring

16:07 ibdknox: yep

16:08 but again, those pieces have to exist and they don't currently

16:08 some of them do

16:08 kwertii: we really need a Clojure equivalent of AllegroCache

16:09 writing relational database mapping layers to Clojure makes me sad

16:10 ibdknox: You know, I don't generally here much talk of ClojureScript here. I get the feeling that the people most excited about it are actually outside of the "core" Clojure community.

16:10 hear*

16:10 mbac: i know ocaml and scheme what clojure tutorial would speak to me

16:10 ibdknox: which is interesting to me

16:10 amalloy: are you excited about cljs?

16:10 amalloy: ibdknox: meh

16:10 ibdknox: why?

16:10 clojurebot: ibdknox: because you can't handle the truth!

16:10 gtrak: it's still kind of a pain to get that all set up, compared to normal clojure

16:11 ibdknox: clojurebot: shutup :-p

16:11 clojurebot: It's greek to me.

16:11 kwertii: mbac: if you know Scheme already, I'd just jump in at learn-clojure.com or clojure.org and start reading about the software transactional memory

16:11 hiredman: because a big chunk of the clojure community doesn't do webapps

16:11 they do big data processing apps

16:11 mbac: oh i don't know THAT much scheme

16:11 i know like 100x more ocaml than scheme

16:11 dnolen: ibdknox: I'm excited but been too busy to play around much with it yet.

16:11 ibdknox: dnolen: you have more important things to work on ;)

16:12 kwertii: ibdknox: I haven't heard much about Clojurescript in general. I've long thought that there should be some abstraction layer on top of javascript for doing DOM manipulation stuff in an arbitrary language, since that's the only way you will get non-JS to work on a Microsoft browser.

16:12 ibdknox: hiredman: based on the state of clojure survey the vast majority of Clojurians are doing websites

16:12 kwertii: ibdknox: I get the sense that most of those are hobby projects though

16:12 ibdknox: that's fair

16:12 pjstadig: ibdknox: or the vast majority of the survey respondents

16:12 kwertii: ibdknox: hiredman is probably right that most PAID Clojurians are doing data stuff

16:13 hiredman: ibdknox: the vast majority of professional clojure devs?

16:13 ibdknox: haha I may be the exception

16:13 kwertii: ibdknox: you are definitely the exception

16:14 the vast majority of Clojure job ads I've seen are either investment banks / hedge funds, or "we're processing Big Data® in Clojure and we have this nifty Ruby on Rails frontend..."

16:14 dnolen: ibdknox: there's quite a few web projects written in Clojure. I'm sure if ClojureScript had come out sooner, the Clojure web projects would be using it.

16:14 ibdknox: dnolen: assuming someone cleans it up some, yeah. Working with it at this point is... rough.

16:14 the goog.* api's are awful

16:14 dnolen: ibdknox: the woven guys (FlightCaster) assessed and seem positive about it, which is a good sign.

16:15 hiredman: actually there is a guy, I forget his name, who wrote a clojure->js compiler months ago and it actually integrates well with existing clojure projects

16:15 amalloy: ibdknox: i may be more excited when there are decent development tools for cljs

16:15 hiredman: (crazy as that sounds)

16:15 mbac: there's no clojure on http://pleac.sourceforge.net/ eh?

16:15 sjl: I tried Clojurescript one night soon after it first came out… it turned out to be way more painful to actually get something on the screen to play with than, say, coffee script.

16:16 ibdknox: dnolen: yeah, we're excited about it too. The stuff I've been able to accomplish is encouraging.

16:16 amalloy: like what? (I'll build them.)

16:16 kwertii: I am convinced that the single main reason Clojure is not used more in pro web frontends now is that there is no ActiveRecord equivalent easy persistence solution, whereas there are thousands of code monkeys who can throw together a Rails app in a few days. doesn't make economic sense to pay someone to hand-roll a DB mapping layer in Clojure.

16:16 dnolen: sjl: agreed. Though I think that is readily fixed by something like cljs-watch.

16:16 amalloy: heh, i know

16:16 * pjstadig groan

16:16 hiredman: https://github.com/zkim/cljs

16:16 sjl: dnolen: Ah, that definitely didn't exist when I was trying it out, yeah.

16:17 Somelauw: Where to find clojure job ads anyway?

16:17 ibdknox: I'll gladly build those sorts of things

16:17 kwertii: Somelauw: indeed.com

16:17 ibdknox: if I know what they are

16:17 I think the cljs-watch at least makes it bearable

16:17 sjl: The "development mode" instructions on the wiki are just so much stranger and more involved than other foo-to-js languages.

16:17 ibdknox: sjl: agreed

16:18 sjl: I have to pull in two separate js files? and goog.require? I just want to use jQuery.

16:18 ibdknox: well, I make that simpler at least

16:18 include bootstrap.js, and roll

16:18 hiredman: sjl: if you look at zkim/cljs it is way simple, it is really too bad using clojurescript with regular clojure got ignored

16:18 mbac: am i just unable to read or is there really no pleac clojure?

16:18 seems like some low-hanging fruit

16:19 sjl: hiredman: what does this fork change?

16:19 hiredman: it isn't a fork

16:19 dnolen: sjl: I'm sure after 2 months CoffeeScript was equally rough ;)

16:19 hiredman: it is a completely seperate implemention from before clojurescript existed

16:19 ibdknox: dnolen: I'm actually not sure

16:20 dnolen: so far the focus for cljs has been on correctness as opposed to experience

16:20 dnolen: ibdknox: what I mean the lang was sorted enough to be useful. ClojureScript is ahead on that front.

16:20 sjl: dnolen: Oh yeah, I just think the choice to build on/around Closure is going to add some inescapable painfulness that Coffeescript just doesn't have.

16:20 hiredman: Ahh

16:20 dnolen: sjl: beyond the limitations of what ClojureScript offers as a language sure.

16:20 ibdknox: yeah

16:21 dnolen: sjl: I like CoffeeScript, and use it. But it's the same stuff I've been doing for like 7 years now.

16:21 ibdknox: the problem is that Google Closure isn't a particularly well respected thing in the JS community

16:21 sjl: I really hope I'm wrong though, because Coffeescript is ugly as sin to me while Clojurescript looks a lot nicer as a language.

16:21 ibdknox: the result of that is that no one cares, there's no experiential documentation for it

16:22 dnolen: ibdknox: the JS community ... meh

16:22 tomoj: good, that gives us a head start

16:22 :P

16:22 ibdknox: dnolen: I agree

16:22 dnolen: ibdknox: this part of what I'm going to rail on in my Strange Loop talk :D

16:22 ibdknox: dnolen: but the lack of experiential documentation *really* hurts a community that hitched their wagon onto it

16:22 gtrak: is there a swank for cljs?

16:23 dnolen: ibdknox: oh definitely. function of time. sure I wish things happened faster.

16:24 ibdknox: dnolen: yeah, I know. Ideally, we just completely abstract closure away and then it doesn't matter.

16:24 sjl: it *is* a lot nicer. I wrote a basic clone of d3 in maybe 100 lines of CLJS

16:25 dnolen: ibdknox: my challenge to front end web development. jQuery is too small. SproutCore too big. WTF. Somebody needs to work on that.

16:25 ibdknox: dnolen: on it.

16:26 sjl: ibdknox: so for cljs-watch, it says the default output is to "resources/public/cljs/bootstrap.js"

16:26 ibdknox: sjl: you can change it

16:26 sjl: Is that the only js file my web server needs to serve, or are there other ones skulking around somewhere that I need to be serving?

16:27 ibdknox: sjl: just that one

16:27 sjl: So it dumps Closure, etc all into that one file? That'd be perfect.

16:27 ibdknox: yes

16:27 it uses the simple optimization by default

16:27 which compiles everything into one file

16:28 you can change it to be like the dev instructions too though if you want it to be faster

16:28 I generally find it acceptable in terms of compilation time

16:29 sjl: Cool, I'll have to try it out

16:29 So… how do I install this and use it?

16:29 ibdknox: grab the cljs-watch file and put it on your path

16:29 as long as you have CLOJURESCRIPT_HOME setup, you're good to go

16:30 ./cljs-watch starts watching the src/ directory based on wherever it was invoked

16:30 sjl: CLOJURESCRIPT_HOME is the git clone of the clojurescript repo, right?

16:31 ibdknox: it's the path to it, yes

16:31 without a trailing slash

16:32 and you have to have done script/bootstrap in clojurescript

16:35 sjl: Dear god, that was so much easier than when I last tried it.

16:35 ibdknox: haha

16:35 dnolen: sjl: open source man.

16:35 ibdknox: for other fun toys

16:35 look at brepl

16:36 sjl: dnolen: Yeah, but if I can't even get something on the screen to poke at it it's hard to contribute.

16:36 scottj: ibdknox: maybe add :output-to to the extended example to make it slightly easier for non-noir people to see specific syntax

16:36 dnolen: sjl: I agree. I haven't had toyed with CLJS much because of the slow code/compile cycle.

16:37 ibdknox: scottj: it's the compiler options syntax, but yeah, that would help :)

16:37 dnolen: ibdknox: did they get our CA?

16:37 your

16:37 sjl: dnolen: Yeah, though cljs-watch seems to reuse the same JVM so it's not excruciating.

16:37 ibdknox: dnolen: they did, I'm on the list now

16:37 dnolen: ibdknox: cool.

16:38 ibdknox: I'm doing the node knockout this weekend

16:38 but after that I'll throw a patch together to add it to cljs proper

16:38 dnolen: ibdknox: gonna write yr knockout in cljs?

16:39 ibdknox: dnolen: I've thought about it... but given the short time period I'm too worried I'll run into an issue that'll eat all our time

16:39 dnolen: ibdknox: 48 hours?

16:39 ibdknox: dnolen: yessir

16:40 dnolen: doing a multiplayer tower defense game :)

16:40 scottj: gtrak: nope, there is a swank-js but not sure if any of it is useful from cljs.

16:40 ibdknox: I love that game :)

16:40 neotyk: Good morning everyone!

16:41 gtrak: ah

16:41 sjl: ibdknox: Hmm, what I am doing wrong here? $ cljs-watch '{:output-to "public/scripts/test.js"}'

16:41 gtrak: don't really understand how you can write clojure without slime/swank

16:41 scottj: gtrak: inferior-lisp

16:41 ibdknox: sjl: cljs-watch src/ {:output-to "blah" :output-dir "blah"}

16:42 gtrak: o i c

16:42 neotyk: cljs-watch? where do I get it from?

16:43 ibdknox: http://github.com/ibdknox/cljs-watch

16:43 scottj: ibdknox: is your td game going to be open sourced?

16:43 neotyk: found it

16:44 scottj: does anyone else using zsh have to escape the {} to cljs?

16:44 ibdknox: scottj: I dunno :) We'll have to see how it goes

16:44 sjl: scottj: Yes

16:44 scottj: sjl: is it all zsh's or some option we have enabled?

16:44 ibdknox: scottj: I definitely don't have to on bash

16:45 sjl: scottj: Not sure, but I'd be surprised if it were an option.

16:45 mbac: can you use defn to pattern match strings?

16:46 dnolen_: mbac: Clojure doesn't have native pattern matching support. But I've been working on that.

16:46 mbac: hmm

16:46 dnolen_: mbac: https://github.com/swannodette/match

16:46 michaelr525_: what's your regular clojure news site? I'm updating from http://planet.clojure.in/

16:46 scottj: michaelr525_: disclojure.org

16:46 gtrak: dnolen_, does lisp have native support for anything?

16:47 scottj: gtrak: lists

16:47 gtrak: ha, i guess so

16:47 ibdknox: dnolen_: btw, I'd love to have a chat sometime about what you'd like to see for the web.

16:47 dnolen_: mbac: pretty much anything you're using to from another lang is in match and then some.

16:47 ibdknox: definitely.

16:48 gtrak: well I guess i mean anything in the core clojure library.

16:48 mbac: hm. can you not define functions with def?

16:48 is it defn only?

16:48 gtrak: you can, ##(def (fn [] "yo"))

16:48 lazybot: java.lang.SecurityException: You tripped the alarm! def is bad!

16:48 mbac: sorry if this is the wrong place for ultra noob questions

16:49 scottj: ibdknox: are there multiplayer td's for mobile? I'd pay for that.

16:49 gtrak: def just binds a var at root level

16:49 lnostdal: any "verbose mode" for lein? .. it seems stuck doing nothing; using CPU for a while, then 0%

16:49 mbac: oh. why's def bad?

16:49 gtrak: mbac, it doesn't work here b/c of the sandbox

16:49 mbac: oh is fn lambda?

16:49 ibdknox: scottj: I'm not sure, to be honest lol

16:49 gtrak: yes

16:49 scottj: ibdknox: ok, was thinking you could phonegap it

16:49 ibdknox: scottj: I haven't seen many (any?) actually multiplayer tower defense games

16:50 scottj: ibdknox: the original(?) starcraft map

16:50 ibdknox: scottj: yeah if it goes well, we may very well try to do that with it

16:50 mbac: er, wait, what did you bind (fn [] "yo") to?

16:50 gtrak: mbac, I forgot to put in the name of the var, like (def myfn (fn [] (body))

16:50 ibdknox: scottj: true

16:50 mbac: haha

16:50 scottj: ibdknox: multiplayer is how I first played it and spent an entire day strategizing with my freshman roomies on our build order

16:50 gtrak: my bad

16:50 ibdknox: scottj: I guess I see that as a step above simple tower defense

16:50 mbac: why is def considered bad?

16:50 gtrak: it's not bad

16:50 ibdknox: scottj: that's in the real-time strategy category for me

16:51 hiredman: mbac: def is not define

16:51 gtrak: mbac, why do you consider it bad?

16:51 mbac: 16:49 < lazybot> java.lang.SecurityException: You tripped the alarm! def is bad!

16:51 something gives me a feeling

16:51 hiredman: mbac: def does not create locals

16:51 gtrak: haha, lazybot is sandboxed to prevent any globabl state or I/O, that doesn't mean you can't do it in your own code

16:52 mbac: oh, does def stick things into the toplevel no matter what scope you say it in?

16:52 gtrak: yes

16:52 mbac: cool

16:52 scottj: ibdknox: are you going to go the all game state in a big map + pure functions route?

16:52 sjl: ibdknox: still no luck. Here's what my session looks like: http://d.pr/etek

16:52 mbac: why does dynamic scoping exist at all?

16:52 gtrak: mbac, but the real story is more complicated, you can bind vars thread-locally and unwind them like a stack

16:53 mbac: is this just to keep it lispy?

16:53 scottj: btw anyone found a cljs unit testing setup they like?

16:53 hiredman: mbac: it is useful for repl work

16:53 mbac: right, why not just have a let that special-cases top-level bindings?

16:53 hiredman: you can re-def a function without having to re-def all the functions that call it

16:54 mbac: oh, it's mutable

16:54 ibdknox: sjl: {:output-to "script/test.js" :output-dir "srcipt/"}

16:54 sjl: ibdknox: I mean I can just symlink the bootstrap.js script to where I want it, so it's not a huge deal.

16:54 gtrak: though sometimes when you re-def a def, you get old functions pointing at the value of the var before

16:54 ibdknox: sjl: yeah, but that should work, so if it doesn't I wanna figure out why :)

16:55 gtrak: you have to refer to the function you're re-deffing all the time by (var thevar) to avoid that and use late-binding

16:55 or #'thevar

16:55 hiredman: gtrak: subtly incorrect

16:55 gtrak: damn, where'd i go wrong?

16:56 mbac: is defn preferred for defining functions even if you're not defining poly-arity function?

16:56 amalloy: mbac: yes, for defining top-level functions use defn

16:56 mbac: i suspect (def a (fun [] "yo")) tickles performance-nazis

16:56 sjl: ibdknox: Yeah, still no luck

16:57 amalloy: mbac: huh? why?

16:57 ibdknox: sjl: I wonder if the escaping screws it up somehow

16:57 gtrak: oh, the definition of defn is more complex than I expected

16:57 mbac: amalloy, don't performance-nazis freak out about unnecessary closures? :)

16:58 wwmorgan: Is there a ring wrapper that takes URL parameters like foo[0]=bar&foo[1]=baz and turns it into { "foo" ["bar", "baz" } ?

16:58 sjl: ibdknox: I tried just passing all the options as a big old string, but that doesn't help either

16:58 gtrak: wth is it doing?

16:58 mbac: (i expect defn does some magic to avoid the closure, but have no idea)

16:58 michaelr525_: after reading this: http://blog.jayfields.com/2011/08/clojure-partition-by-split-with-group.html

16:58 amalloy: (a) no, they don't; (b) neither of those is a closure

16:58 ibdknox: sjl: I used the same function that clojurescript's cljsc uses

16:58 michaelr525_: Isn't the separate function from clojure.contrib.seq iterates over the seq twice?

16:58 amalloy: (that is, neither a def/fn version nor a defn version

16:59 ibdknox: sjl: to grab those options

16:59 sjl: can you try it too

16:59 clojurescript/bin/cljsc ../samples/hello/ {:output ...}

16:59 amalloy: mbac: (fn [] "a") has no free variables, only free constants; "a" is embedded into the generated class

17:00 mbac: oh, you're right.

17:00 amalloy: and closures are super-cheap anyway; you get more performance benefit from using them to close over constant expressions than you lose from having to call a few more constructors

17:01 sjl: ibdknox: cljsc works

17:01 wwmorgan: FYI: got it, it's wrap-nested-params

17:01 ibdknox: sjl: k, I will have to figure that out then.

17:01 sjl: can't do it right this second, but I'll have a fix by tonight

17:02 sjl: ibdknox: It's cool, I'm not using clojurescript for anything important at the moment, just poking around. No rush.

17:02 My Clojure Minecraft bot framework is eating up all the free time I have to play with Clojure-related things anyway, hah.

17:03 ibdknox: hehe :)

17:03 mbac: i really like the stylish use of vectors in clojure

17:03 breaks up the parenthetical monotony

17:04 michaelr525_: ,(require 'clojure.repl )

17:04 clojurebot: nil

17:04 ibdknox: sjl: clojurecraft certainly does look like fun, so I don't blame you

17:04 sjl: ibdknox: It's very fun, just lots to do to make it useful/practical

17:04 michaelr525_: ,(require 'clojure.contrib.seq)

17:04 clojurebot: #<RuntimeException java.lang.RuntimeException: java.io.FileNotFoundException: Could not locate clojure/contrib/seq__init.class or clojure/contrib/seq.clj on classpath: >

17:05 michaelr525_: ,(require 'clojure.contrib.seq-utils)

17:05 clojurebot: #<RuntimeException java.lang.RuntimeException: java.io.FileNotFoundException: Could not locate clojure/contrib/seq_utils__init.class or clojure/contrib/seq_utils.clj on classpath: >

17:05 michaelr525_: err sorry\

17:05 gtrak: mbac, wait till you get to destructuring

17:06 michaelr525_: This function really bothers me: http://clojuredocs.org/clojure_contrib/clojure.contrib.seq/separate

17:06 Isn't the sequence iterated twice here? It doesn't seem to be performance wise..

17:06 gtrak: michaelr525, it's lazy

17:06 amalloy: michaelr525_: it's surprisingly difficult to iterate the sequence only once

17:07 michaelr525_: amalloy: using a for loop in c for example

17:07 gtrak: hopefully whatever you're doing to the data is more complex than an iteration step

17:07 amalloy: because you can't just mutate the lazy-seq returned by (remove) when the one returned by (filter) discovers that the predicate doesn't pass

17:08 michaelr525_: I haven't been writing code in C for years, but when I see something like this it bothers me :)

17:08 gtrak: michaelr525, how would you even do it in C? make copies?

17:08 that seems much worse

17:09 this is a clean, lazy, functional approach

17:09 michaelr525_: well, suppose that you have immutable collections in C, it would be same as in clojure except that it would be iterated only once

17:10 gtrak: you're really not thinking this through

17:10 amalloy: michaelr525_: except it wouldn't be lazy

17:10 mbac: grak, ?

17:10 michaelr525_: amalloy: ok, let's say that these immutable C sequences are lazy as well :)

17:11 mbac: destructuring-bind?

17:11 gtrak: mbac, something like that, yes

17:11 amalloy: michaelr525_: that's my point! C would have the same problem then - you couldn't do it

17:11 try it. pretend you have immutable lazy sequences in C, and split an input sequence up based on a predicate. you can't do it

17:12 you could do it eagerly in clojure if you wanted, by using doall to force everything before you return it

17:12 michaelr525_: hmm

17:12 hiredman: if the language was lazy (not just seqs) you could do it as a reduce

17:13 amalloy: hiredman: really? i guess i'm not used to thinking that lazily

17:13 how would it work in, say, haskell?

17:14 michaelr525_: it annoyed me too, so i wrote https://github.com/flatland/useful/blob/develop/src/useful/seq.clj#L23

17:15 which transforms the input to make sure the predicate is only called once per item, but now it traverses the input seq three times

17:15 hiredman: (reduce (fn [[t f] e] (if (pred e) [(conj t e) f] [t (conj f e)])) [[] []] ...)

17:15 michaelr525_: amalloy: how about something like this:

17:15 while( seq.next ){ if( seq.val is odd ) add to collection1 else add to collection2 }

17:16 pseudo c\ ;)

17:16 amalloy: michaelr525_: you forgot "immutable"

17:16 how do you implement "add to ___"?

17:17 michaelr525_: well, "it just works" :)

17:17 amalloy: good luck with that

17:18 michaelr525_: amalloy: i can't understand what is the principal problem doing it?

17:18 gtrak: ah, C just works so good, why don't we all use it?

17:19 leeda: with leiningen, how can i specify the type of a dependency as "pom"? /cc @technomancy

17:20 michaelr525_: hiredman: so is this solution faster than the elegant one with two filters?

17:20 hiredman: michaelr525_: no idea, and it's not lazy at all in clojure

17:20 amalloy: michaelr525_: it's a solution that would only work if clojure were inherently lazy like haskell is. in clojure as it is now, hiredman's solution eagerly constructs both input seqs immediately

17:20 *output

17:21 michaelr525_: hmm i see

17:21 amalloy: michaelr525_: your solution involved mutating sequence B while you traverse sequence A - discarding immutability. you can discard laziness instead, if you want, but in an eager language you can't create two lazy outputs from the same input without either either mutation or multiple iteration

17:21 michaelr525_: what causes the evaluation of the seq?

17:21 leeda: technomancy: or, is it possible to just specify this: https://gist.github.com/a0ebc8b00fda0db6d831 as a dependency? :P

17:22 gtrak: leeda, anything is possible with robert-hooke

17:22 amalloy: pft

17:22 michaelr525_: hehe

17:22 leeda: gtrak: heh

17:23 hiredman: michaelr525_: anything that isn't lazy

17:23 (e.g. if it doesn't return a lazy-seq it will most likely force at least some part of a lazy-seq)

17:23 amalloy: i think the answer to his specific question in this case was "reduce forces the whole input sequence"

17:23 michaelr525_: reduce is lazy, no?

17:23 hiredman: no

17:24 michaelr525_: ah

17:24 hiredman: there is no way to make reduce lazy in a non-lazy language

17:24 gtrak: how does haskell do it?

17:24 michaelr525_: why clojure is not fully lazy?

17:24 hiredman: haskell is lazy

17:24 technomancy: leeda: dependencies must be in maven repositories, if that's what you're asking

17:24 gtrak: i would think the inherent nature of reduce, turning a vector value into a scalar, can't be lazified

17:25 hiredman: michaelr525_: there are a set of tradeoffs around laziness, but the simplest answer is java interop

17:25 technomancy: gtrak: laziness in clojure is only for seqs, but for haskell it applies to any value

17:25 leeda: technomancy: yeah, i'm trying to specify javax.media/jai_core "1.1.3" as a dependency, but it doesn't seem to be working

17:25 technomancy: i found this article: http://sahits.ch/blog/?p=1038

17:25 hiredman: gtrak: if a process proceeds by the application of functions, and those functions are lazy, the process is lazy

17:26 gtrak: hiredman, can't you just wrap all that in closures and make it lazy?

17:26 technomancy: leeda: gross. did you try :type "pom"?

17:26 leeda: technomancy: which seems to say that i need to specify the dependency type as "pom" (<dependency>...<type>pom</type></dependency>)

17:26 michaelr525_: is there an irc program with a reversed flow - from the top down?

17:26 leeda: technomancy: but where would i put that?

17:26 michaelr525_: I get tired always looking down at the newest text

17:26 technomancy: leeda: in the dependency vector

17:26 hiredman: gtrak: you would effectively be writing a lazy sub language unable to interop easily with the rest of the language

17:26 leeda: [javax.media/jai_core "1.1.3" {:type "pom"}]?

17:27 technomancy: ^

17:27 gtrak: ah, but that would suffice, that's how ring does its middlewares

17:27 technomancy: leeda: lose the brackets and you're set

17:27 err--the braces

17:27 curlies

17:27 leeda: ah ok

17:28 technomancy: awesome, looks like that worked. thanks!

17:29 technomancy: cool

17:30 gtrak: if we have immutable structures, it wouldn't be too hard to make a lazify and deref macro to go with it

17:31 technomancy: sure, it's called delay

17:32 just need all consumers ever to call force

17:33 (doseq [n (all-ns) [_ v] (ns-map n)] (alter

17:33 hiredman: all the time, before everything

17:33 gtrak: i think non-lazy is a sane default for reasoning about a program, no?

17:33 technomancy: -var-root v (fn [f] (fn [o & args] (apply o (map force argsr)))))

17:33 tada!

17:34 gtrak: technomancy, that makes me afraid

17:34 technomancy: gtrak: I had to split it into two IRC messages because a single one could not contain SO MUCH POWER

17:34 much like the Killer Joke that had to be translated one word at a time

17:36 gtrak: my god

17:37 does the universe explode if you run that on clojure.core?

17:37 technomancy: sure, FSVO universe

17:37 hiredman: yes

17:38 technomancy: considering it doesn't check for ifn? first, absolutely.

17:44 leeda: technomancy: another question, is it possible to force lein to use a specific repository for a certain dependency?

17:44 gtrak: so delay all the stuff you're interested in, then make a reader macro to do the force for you

17:45 amalloy: gtrak: sure, eager is a sane default if you're used to it, just like imperative is. i'm used to eager, so thinking about a lazy language is hard for me; but there was a time when i was used to imperative/mutation too

17:45 leeda: technomancy: since the one on maven is not working, i want to use a different repository for it

17:45 technomancy: but it seems to prefer maven's

17:45 michaelr525_: why i can't any longer mark and install packages in package-list-packages?

17:45 gtrak: amalloy, yea, I've never used haskell so I guess I can't make the judgment

17:45 michaelr525_: I an X don't do anytjhin

17:45 gtrak: I think immutability simplifies things very much

17:47 michaelr525_: oh, it's a built in package

17:48 gtrak: amalloy, the jump from mutability to immutability is not conceptually difficult i think, but it can be hard to persuade someone that it's better and necessary full-on, I'm already persuaded that laziness is better at times, but... it messes with the whole knowing what it's going to do aspect of programming that we rely on so much. Is it not an issue in haskell?

17:48 leeda: technomancy: ok, never mind, it was my mistake

17:48 amalloy: (a) i think moving to immutability scares a lot of people; (b) i barely know my way around in haskell, so ask someone else :P

17:49 michaelr525`: hello

17:49 gtrak: well, it made me feel all giddy, but i've only spent a few years programming in total

17:50 technomancy: gtrak: it's a known issue in haskell that you can't easily reason about performance; see http://ro-che.info/ccc/11.html

17:51 gtrak: ha

17:51 technomancy: (I really wish that comic had gone for more than 12 strips)

17:51 hiredman: but in some sense everything has the same issue

17:52 reasoning about performance in the presence of a jit is difficult, etc

17:53 gtrak: hiredman, yes, so no real-time perf guarantees, but there's a whole bunch of work where the benefits outweigh the costs, for instance, you can't have immutables without a GC or ref-counting at least

17:54 hiredman: but even the architecture of a cpu is getting to the point where it can be hard to eyeball performance for native code

17:55 gtrak: on a much smaller scale, though

17:55 dnolen_: hiredman: but you can still ballpark it. I dunno, Clojure kind of maps directly to JVM bytecodes almost, so I think reasoning about performance in Clojure is not so hard.

17:55 technomancy: yeah, that's true. brb; switching to forth.

17:55 =)

17:56 gtrak: all the cache-optimizing stuff is harder to do

17:56 dnolen_: Haskell on the other hand goes through some hardcore transformations.

17:58 hiredman: dnolen_: it does map really well to jvm bytecode, but what is the performance of the bytecode, hard to tell without profiling

17:59 gtrak: hickey cares about identity at slices in time though, that's one of the trade-offs

18:00 dnolen_: hiredman: I dunno. Java was designed to make typical C++ code run quickly. It's easy to see what going to be fast. mutable fields, method lookup, arithmetic.

18:00 C++ looking code.

18:01 all those things are preserved in Clojure, since they are the fast path.

18:01 hiredman: mmm

18:02 dnolen_: of course there's weird run time optimizations, like collapsing method calls, but that's just icing.

18:02 Somelauw: wouldn't dynanicismn make it a bit slower

18:03 hiredman: dnolen_: by collapsing method calls you mean inlining?

18:03 dnolen_: hiredman: yeah

18:03 gtrak: not terribly 'weird'

18:03 hiredman: because I am pretty sure every jvm talk I've seen has called that "THE optimization"

18:03 instead of just "icing"

18:04 inlining multiplies the power of other optimizations by giving them more code to work with

18:05 dnolen_: hiredman: point is, yes it's hard to reason about the nature of the inlining. But I think it's not hard to see what style of code has the potential to get inlined.

18:06 hiredman: dnolen_: sure

18:09 gtrak: dnolen_, it'll run faster than you think it will, not so hard :-)

18:14 there was a cool article about that, something about putting a for-loop body in a separate method can help a lot

18:15 i think b/c it's likely to lower the code in the method under the inlining threshold

18:29 Somelauw: When doing (let [x 5]) would the clojure compiler infer that x is a static int?

18:32 Scriptor: Somelauw: infer wouldn't really be the right word, I think

18:33 x would just be pointing to something that happened to be an int, just like in any other dynamically typed language

18:34 hiredman: actually for locals create by let you do get type inference

18:34 x would be a primitive long (in 1.3)

18:40 Somelauw: Scriptor: I though java created ints on the stack like c.

18:41 hiredman: you asked about clojure, not java

18:41 amalloy: Somelauw: java puts all locals on the stack. it's just that for pointer-typed locals, it has to allocate an object on the heap for the local to point at

18:43 Somelauw: So clojure uses an Integer for that by default?

18:43 Scriptor: exactly

18:43 hiredman: depends

18:43 Scriptor: well

18:43 doesn't it use Long a lot of the time?

18:43 hiredman: no

18:44 dnolen_: Somelauw: 1.2 boxed Integer, not 1.3, unboxed long

18:44 Somelauw: Go clojure 1.3 :D

18:44 Scriptor: yea, long, not Long :p

18:44 dnolen_: Somelauw: arith perf in 1.3 is stellar with much less type hinting.

18:45 mbac: how does the jvm tell the difference between immediates and references? does it use a tag bit?

18:45 amalloy: well, there are still a lot of Longs being used in 1.3 because you pass them around to other functions. but locally you can use primitive longs

18:45 mbac: oh, maybe there's runtime type information

18:45 duh

18:45 dnolen_: amalloy: unless of course you're passing them to fns w/ prim signatures.

18:45 amalloy: sure

18:46 dnolen_: like +, -, *, = etc

18:46 Somelauw: ok thanks

18:46 amalloy: mbac: java has compile-time and run-time type information. stuff like "is this an int or an object" is done at compile time

18:48 hiredman: dnolen_: which are likely to be inlined into static method calls by the compiler and then into jadd by the jit

18:48 dnolen_: hiredman: :)

18:48 mbac: amalloy, is the run-time type information for the GC only?

18:48 amalloy: no, it's mostly to preserve type safety

18:48 hiredman: if only I did expensive computations on numbers, how fast my programs would be

18:49 mbac: oh right, casts

18:49 amalloy: right

18:49 and also virtual/dynamic method dispatch

18:49 mbac: oh right, inheritance :)

18:50 Scriptor: so with 1.2 and before with the boxed ints, did variables just store a reference to an Object?

18:51 dnolen_: hiredman: Clojure is one giant expensive computation on numbers.

18:51 hiredman: dnolen_: blah blah blah turning blah blah blah

18:52 turing

18:52 dnolen_: all the persistent data structure we love so much ...

18:52 hiredman: Scriptor: (let [x (int 1)] ...) x is a primitve int

18:55 Scriptor: as in x is directly placed on the stack as an int?

18:55 hiredman: depends on the jvm

18:56 x inside that let is equiv to 'int x;' in a java method body

18:56 Scriptor: ah, got it

18:57 what if you did (def x 1), I know it creates a Var object, but what does that point to?

18:57 hiredman: a Long or Integer

18:57 vars hold objects

18:58 Scriptor: ah, so unboxing won't work with def?

18:58 meaning, it won't store it as an unboxed long

18:59 hiredman: right, but you can do (def x 1) … (let [x (int x)] …) …

18:59 Scriptor: interesting, thanks!

19:04 amalloy: several times i've seen code like (if (> (count xs) 3) ...), which counts the whole sequence even though it doesn't have to. of course it's not hard to do the short-circuiting manually, but does anyone know of a built-in like (has-more-than 3 xs) that i can point people at?

19:09 Somelauw: amalloy: Unpacking it in a let?

19:09 amalloy: huh?

19:12 Somelauw: Well you don't need to check its length since you can unpack it. Like (let [[a b c & d] 3-elementer] body)

19:14 Oh wait, that doesn't check its length. nvm. Only if-let does for a single element.

19:21 ibdknox: does anyone know the implications of the EPL license on Clojure? Does it limit a company in some way?

19:21 amalloy: Somelauw: that also only works if the length is known at compile time, and is small enough that it's not painful to type out a long destructuring form

19:22 danlarkin: ibdknox: it limits a company in exactly the ways specified in the license, and no others

19:22 amalloy: the easiest way to do it is like (if (nthnext xs 2) (...there are at least three elements...))

19:22 ibdknox: danlarkin: why thank you for that wonderful response.

19:23 danlarkin: ask smart questions if you want smart answers :)

19:23 amalloy: but of course for vectors and other Counted things, that's actually slower than just calling count and comparing

19:23 danlarkin: sorry, that was a little too mean

19:23 ibdknox: Yeah

19:24 definitely encourages people to participate

19:24 danlarkin: yeah yeah yeah

19:24 ibdknox: My question was legitimate, this room is full of professional clojure devs who use clojure at a company. I was essentially asking if anyone hit any gotchas with the license.

19:25 danlarkin: ibdknox: do you have specific concerns about the EPL? or just asking in general

19:25 ibdknox: I'm trying to make sure it's safe for me to leave Noir as EPL

19:25 danlarkin: wikipedia has a good summary

19:26 ibdknox: danlarkin: I've read it.

19:26 Again, just asking if anyone has hit any issues

19:27 technomancy: ibdknox: it means no one can distribute modified versions of noir without making them public, which is probably what you want.

19:27 ibdknox: technomancy: yeah, I thought so too.

19:31 Somelauw: How about (if (last (take 3 (iterate next seq))))

19:32 Nevermind. There is nthnext like you posted.

19:32 mbac: how does clojure qualify .methodCall foo?

19:32 does it figure it out based on the type of foo?

19:33 that seems impossible

19:33 amalloy: Somelauw: and last/take won't work anyway, because the sequence could be [1 2 nil]

19:34 mbac: i notice, say, .substring works even though i didn't import anything

19:34 technomancy: mbac: for non-hinted calls it reflects at runtime

19:34 Somelauw: mbac: I think it is a long sequence of foe getClass getMethods invoke

19:35 mbac: woa

19:35 gtrak: mbac, if you turn on reflection warnings, you can see exactly what it infers or doesn't

19:46 amalloy: mbac: importing has nothing to do with it, in either java or clojure

19:46 mbac: what does import do, then?

19:47 amalloy: it just gives you shortcuts for the classnames, when you need to type them, such as to declare a new variable or perform a cast

19:47 mbac: er? isn't that the same as qualifying names?

19:48 amalloy: System.out.println(x) works, even though i haven't imported the PrintWriter class of which println is a member

19:49 mbac: oic

21:37 gridaphobe: is there any reason to worry about reflection if i'm not doing any java interop?

21:37 amalloy: no

21:38 gridaphobe: thanks :)

21:38 that's what i thought

22:36 * srid is diverting his attention (from clojure) to learn some html/css prettiness

22:50 gstamp: is it possible to type hint a def? I have (def english-analyzer (EnglishAnalyzer. Version/LUCENE_31 #{})) and I'm not sure how it is supposed to be type hinted.

22:54 actually, it looks like if I type hint it where it's used then it works

22:59 cemerick: gstamp: you hint the var's name

23:00 amalloy: cemerick: i was just thinking, you could pick up the hint from the init expr in this case, but it would be wrong in general because vars can change, right?

23:00 gstamp: cemerick: thanks. that seems to work well.

23:01 cemerick: gstamp: *or* the symbol at the call site — either way. Didn't mean to imply one was necessarily superior.

23:02 amalloy: Yeah, alter-var-root, and then newly-loaded code is not helped at all.

23:02 or binding, or whatever

23:02 gstamp: cemerick: I imagine in general it would be easier to manage on the var

23:03 amalloy: okay. just wanted to make sure my hinting fundamentals are halfway solid :P

23:03 cemerick: gstamp: Certainly easier if you have multiple ambiguous interop usages. Plus, it's reasonable documentation.

23:03 amalloy: :-)

23:04 If you're concerned on that front, make sure you keep an eye on 811.

Logging service provided by n01se.net