#clojure log - Jan 02 2012

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

0:00 technomancy: it means unless you want to go through a bunch of grunt work by hand you're limited to using clojure and no external libraries

0:01 bitops: technomancy: I may be misremembering, but I thought I had read that contrib was bundled with the clojure jar?

0:01 technomancy: no, contrib has been split up into a bunch of separate jars now

0:01 bitops: right, I saw that from the link(s) above

0:02 it's not an issue for me, I'm just trying to figure out what is the right way to get started and set up :)

0:03 graphbum: since I am in the midst of shifting from 1.2 to 1.3, I saw the contrib modularization. so you need to grab numeric tower

0:03 bitops: ah okay

0:03 graphbum: you can do that a number of ways....

0:04 bitops: I'll go out on a limb and assume leiningen is the easiest way?

0:04 graphbum: that's what technomancy was saying

0:04 amalloy: clojurebot: leiningen is always the easiest way

0:04 clojurebot: Ack. Ack.

0:04 bitops: if the right thing to do is having a "playground" project I'm all for that

0:04 amalloy: bitops: yes, sounds good

0:05 bitops: that's sort of interesting, making the standard library a dependency you have to download. not knocking it by any means, just observing…could have useful applications

0:05 graphbum: so you'd like.... "lein new playground" somewhere

0:05 bitops: graphbum: what if I have some existing files I want to leiningenify?

0:06 graphbum: lein will make the structure for you and populate it with some stuff, namely a project.clj I believe

0:06 you can dump whatever you want in there

0:06 in the directory

0:06 bitops: ah, just tried it. pretty painless

0:07 graphbum: you set dependencies inside project.clj

0:07 technomancy: it's not really the standard library

0:07 bitops: well geez, when's the pain going to start?! I was expecting a yak to show up any old time now.

0:07 :P

0:07 technomancy: the standard library is just clojure.set/xml/zip/test/etc that comes with the jar

0:07 amalloy: right. the standard library is the stuff that *does* come with clojure. functions like map, filter, reduce

0:09 graphbum: there's some really useful shit in contrib though...

0:09 useful for me at least

0:10 amalloy: there's some really useful stuff in ring too, but that doesn't make it part of the clojure stdlib

0:13 graphbum: right....except some of that really useful shit from contrib did become part of the standard lib....because it was useful

0:14 bitops: technomancy: I hate to sound like a broken record, but how do I know which version of numeric-tower to import? https://github.com/clojure/math.numeric-tower isn't much help. :(

0:14 technomancy: bitops: I usually try http://search.maven.org

0:16 bitops: technomancy: cool…I found it….but then what to type in the project.clj file? I'm sorry if that's a stupid question, it's not totally clear to me how it maps onto the Maven abstraction.

0:16 technomancy: if you do "lein help tutorial" it should have you covered

0:16 you can skim to the part about adding deps, but at some point you should read the whole thing

0:17 bitops: technomancy: ah okay, thank you, I'll do that

0:17 thanks for all the help! much appreciated :)

0:17 technomancy: sure

0:50 graphbum: did the old repl-utils from clojure.contrib make it into the new modular stuff under 1.3?

0:50 trying to grab what used to be clojure.contrib.repl-utils/show

0:52 amalloy: clojure.reflect/reflect

0:52 graphbum: nice, thanks.

1:26 wow...i did not realize how disruptive 1.3 would be against 1.2 projects I had

2:14 replaca: technomancy: still around?

4:14 tomoj: is there a better way than @(promise) to cause a thread to just do nothing

4:20 amalloy: (.wait (Object.))?

4:31 tomoj: I just get an IllegalMonitorStateException

4:38 woodz: You need to be in a Java 'synchronized' block to acquire an object's monitor and be able to .wait on it. Clojure provides access to this via the 'locking' macro, which has the advantage of releasing the monitor when the enclosed body of code finishes.

4:40 tomoj: so (let [o (Object.)] (locking o (.wait o))) ?

4:41 amalloy: well @(promise) has got to be better than that

4:41 Fossi: :D

4:41 woodz: Yes, except that that particular snippet will tie up whichever thread executes it, probably infinitely, as the new Object isn't available for another thread to signal

4:41 amalloy: woodz: that was the point

4:41 tomoj: that's the goal

4:42 woodz: I joined the conversation a bit late, so missed that bit :-)

4:42 tomoj: if the thread dies, it will be reborn elsewhere automatically

4:42 woodz: ok

4:42 amalloy: fwiw, @(promise) probably requires a bit more resources from the jvm than the .wait approach, but since what you're doing is killing off the thread i doubt it matters

4:44 &(doc monitor-enter)

4:44 lazybot: ⇒ "Special: monitor-enter; Synchronization primitive that should be avoided\n in user code. Use the 'locking' macro."

4:44 amalloy: super-efficient! you can refuse to include the monitor-exit that (locking) would introduce :)

4:45 saving 100% (and also 0%) of the cpu cycles that would be spent on that

4:48 wiseen: https://github.com/wiseen/core.observable - I wrote a .NET RX event handling library for clojure/clojurescript

7:31 rangen: why this says 'unable to find resource'? lein install org.clojars.gjahad/debug-repl "0.3.1" it should work right? http://clojars.org/org.clojars.gjahad/debug-repl refers to this info

7:32 full error: [INFO] Unable to find resource 'org.clojars.gjahad:debug-repl:jar:0.3.1' in repository central (http://repo1.maven.org/maven2). it seems lein does not go to look for clojars repository in this case

7:35 holo: hello

7:35 can someone tell me a very simple case of use (actually useful) for "let" form?

7:41 Chousuke: uhh... any time you want a local variable?

7:41 which is not that uncommon

7:42 or do you use only global variables and literals in your programs? :P

7:46 holo: let can also be used to create closures eg. (defn make-counter-fn (let [foo (atom 0)] (fn [] (swap! inc foo)))) <- now you can call the function returned by make-counter-fn and it will return the number of times it has been called.

7:47 though I guess that's a toy example, it's pretty common in actual code. it's just difficult to come up with good examples without actually having some sort of purpose in mind :P

7:47 I mean closures are common, not counters. :P

7:57 holo: chousuke, I see. I am familiar with closures. I don't use globals or locals yet or anything at all in clojure. I'm just learning clojure from a tutorial

8:00 Chousuke: I'm sure you'll find lots of uses for let once you start writing code, then

8:02 Fossi: for me the most common occurrence is: (let [foo (some-"expensive"-calculation bar baz)] (dothis foo) (dothat foo))

8:03 and expensive can also be hard/annoying to write twice ;)

8:05 hmm i guess: (let [foo (some-"expensive"-calculation bar baz) quux (some-transformation)] (dothis quux) (dothat foo)) is even used more often :)

8:05 as in saving something for later

8:09 holo: Fossi, at the second example there is no reutilization of results

8:11 OK, I guess its cleaner and there is an implicit "do" by using let

8:13 Fossi: ups

8:14 i meant to write (some-transformation foo)

8:18 holo: I see, but for a language which returns an expression by being functional looks to have a strong imperative flavour

8:19 Fossi: well, let isnt needed if your code is purely functional

8:19 other than saving you lots of typing

8:20 oh, and save computation

8:20 but not strictly needed, no

8:20 raek: if the value of one expression is needed in multiple expressions, you still need let in purely functional code

8:21 Fossi: you can recompute it then

8:22 raek: holo: why does Clojure look to have a strong imperative flavour?

8:23 Fossi: i think "let" does

8:24 holo: raek, when, do, loop (something more I may forget) forms are purpposely imperative. anyway this is just from the tutorial I am reading. it's not bad to have imperative constructs.. I mean, it just looks as if that is the idiomatic way of doing things. ultimately what matters is choice not to do it

8:25 antares_: hi. I have the following code with gen-class and no matter what I do, the compiler tells me there is no "state" field on the generated class: https://gist.github.com/3fd54c45bce5cdf9e345 — what am I missing?

8:27 holo: in caml, let in the toplevel would create global variables. if used inside something like those examples from Rossi, it would create local variables

8:29 raek: I think of the implicit do like this: what should (let [...] a b c) mean? (let [...] (do a b c)) is a fairly "natural" interpretation.

8:33 Fossi: raek: well, you could disallow that

9:29 nickik: I want to reset up my emacs. Witch is the best current tutorial to get emacs/Starter Kid/Clojre Mode/slime/swank working?

9:45 CrazyWoods: how to use clojure to start a GUI project?

9:46 vimja: nickik: i used http://data-sorcery.org/2009/12/20/getting-started/ to get started

9:46 benoyst: nickik: I've also found this one interesting: http://postposttechnical.com/2011/11/first-steps-with-clojure/

9:51 CrazyWoods: I've read a very exciting article a few days ago: http://blog.darevay.com/2011/12/a-seesaw-tutorial/

9:51 Hope this helps.

9:53 CrazyWoods: benoyst, thank you

9:53 Fossi: that looks almost nice :)

9:54 benoyst: indeed

10:01 Fossi: does anyone know a tutorial on debugging java via emacs/swank? does that even work?

10:14 zilti: Does someone here use SQLKorma? What type does exec return for a select query?

10:35 bhenry: is there a way to use binding on something qualified as alias/var where alias is the last part of (require '[namespace :as alias])

10:38 Raynes: bhenry: If I understand your question right, then there is nothing stopping you.

10:47 lypanov: if i use someones library that has a line saying (def *vm-session-type* "gui")

10:47 how can i change the value for my usage of the library?

10:47 i assume thats what its for..

10:47 * lypanov is only 20% of the way through joy of clojure :(

10:49 bhenry: lypanov: &&(doc binding)

10:57 zilti: Now that's a strange error: "IllegalAccessException Class clojure.lang.Reflector can not access a member of class lyrionch.util.Whirlpool with modifiers "public static final"" Why can't it access something marked public?

10:58 skelternet: is it accessing it for write?

10:59 oh…Reflector

10:59 zilti: I'm playing around in the repl and did a (def digest (Whirlpool/DIGESTBYTES))

11:01 Any other try to access the class results in a "IllegalAccessError tried to access class lyrionch.util.Whirlpool from class lyrionch.models.usersys$eval699 lyrionch.models.usersys/eval699 (NO_SOURCE_FILE:51)" like error.

11:02 raek: zilti: what is DIGESTBYTES? a method or a field?

11:02 zilti: A static field

11:02 raek: then you should do this: (def digest Whirlpool/DIGESTBYTES)

11:03 the extra parens means method call

11:03 zilti: Hmm thanks. But I get the same error again: IllegalAccessException Class clojure.lang.Reflector can not access a member of class lyrionch.util.Whirlpool with modifiers "public static final"

11:08 lynaghk: Has anyone defined multimethods in ClojureScript before? I'm having some namespace troubles excluding clojure.core/+

11:08 https://gist.github.com/1551222

11:13 zilti: Pro-tip: Declare a class as "public" if you want to access it from another namespace...

11:16 yoklov: is there any slowdown associated with metadata

11:17 actually no nevermind it'll still be way faster than the numerical calculations I'm doing.

11:21 zilti: I have a Java class and I have a Clojure function accessing that class. Now I want to ensure that only one "instance" of the Clojure function is allowed to access the Java class at a time, forcing other instances to wait (because that Java class isn't thread save). What's the best way to achieve this?

11:32 chouser: pods, if only they existed.

11:33 * gfredericks is trying to learn elisp

11:42 TimMc: chouser: pods? A web search didn't reveal anything.

11:43 chouser: yeah, they don't exist

11:43 lynaghk: It's a planned construct that Rich talked about at the Conj

11:43 chouser: http://kotka.de/blog/2010/12/What_are_Pods.html

11:43 TimMc: Ah, got it. I took it to be something that existed in some other language.

11:48 zilti: That's a pity... But how should I do it? I'm quite new to concurrency, especially in Clojure

11:51 TimMc: zilti: It's a single instance that you need to coordinate access to from multiple Clojure threads?

11:51 Maybe you could send thunks to an agent that controls the instance.

11:52 cemerick: That, or there's always `locking`. :-P

11:52 TimMc: Point.

11:53 raek: (def foo-lock (Object.)) (defn foo [...] (locking foo-lock ...))

11:53 zilti: But wouldn't locking refuse the attempt to access the class? What I need is basically that the whole body of the function that accesses the java class is executed "atomically" so that there can't be a second call to the same function at the same time.

11:54 So I had something like a "queue" in mind that just puts the other threads trying to access in a "sleep" state

11:54 TimMc: zilti: locking pauses the thread

11:55 zilti: Ok, then I'll do locking

11:55 raek: zilti: have you checked you java.util.concurrent.BlockingQueue?

11:55 http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/BlockingQueue.html

11:55 *checked out

11:55 TimMc: If you just need to send actions, an agent would be good. But if you need to read *and* write, locking is probably the best.

11:56 zilti: Yes, I'll use locking. I just thought locking would "cancel" a request made at the same time, but if it's pausing the concurrent thread it's ok

11:57 jodaro`: so i'm messing around with aleph/lamina/gloss stuff

11:57 using tcp-client to interact with a server that uses a binary protocol

11:57 i've specified a frame to handle the request

11:57 cemerick: zilti: `locking` uses a Java monitor, just like `synchronized`.

11:58 jodaro`: enqueue it on the connection

11:58 and receive-all the response

11:58 everything appears to work correctly but i'm noticing that my respone is also being decoded using said frame

11:58 which happens to work, but what if i wanted to use a different codec for the response

12:00 jodaro: oh

12:00 looks like i can specify an encoder and decoder

12:04 dbushenko: hi all!

12:04 what's the ultimate mongodb clojar?

12:08 solussd: when using clojure.xml/emit to print xml it turns all of my numbers and booleans in the :attrs map into strings, so when I read it back in using clojure.xml/parse, I have nothing but strings for my :attrs. What is the most straightforward way to detect, and convert into the appropriate type, these attributes?

12:11 cemerick: solussd: XML is textual; there's no reason to expect it to natively round-trip other data types.

12:12 You could speculatively parse attributes using clojure.walk

12:14 solussd: cemerick: hm. too bad clojure.xml/parse can't be fed a schema

12:16 cemerick: solussd: schemas aren't supported in the JDK IIRC.

12:17 OK, so that's wrong.

12:17 I should say, I think schemas can only be used to validate.

12:40 solussd: how do you list all of the interfsaces/protocols a type implements?

12:47 Scorchin: I currently have a return value which looks like: (["h1. " "h1" ""]). To get the second element from the sequence, I'm doing the following: (second (first (["h1. " "h1" ""]))). Is there a better way to do the above?

12:49 yoklov: Scorchin: if it's in a let or a function you could use destructuring

12:50 Scorchin: yoklov: thanks, I'll check that out

12:56 yoklov: Scorchin: something like this ##(let [[[fst snd trd]] (list (vector "h1. " "h1" ""))] snd)

12:56 lazybot: ⇒ "h1"

12:57 yoklov: though, thats still somewhat awkward.

12:59 * yoklov is a noob so theres probably a better way.

13:02 flashingpumpkin: hey guys. I'm curious if someone can quickly help me out. I'm running into java interop problems. I'm following this tutorial, but fail to init a new mesh. (Scroll down to the rendering a triangle bit) - http://code.google.com/p/libgdx/wiki/MyFirstTriangle and the ctor error: http://dpaste.com/680334/

13:05 Chousuke: flashingpumpkin: that sort of stuff usually happens when there are multiple similar constructors

13:06 flashingpumpkin: try typehinting the vertex argument, or force the integer literals to be ints with (int 3)

13:06 flashingpumpkin: Chousuke, there are indeed multiple constructors. But, I'm just rewriting the Java example (that works) into Clojure.

13:06 Chousuke, ok, trying :)

13:08 yoklov: that ctor has varargs in java, does that mean anything for the clojure interop/

13:09 flashingpumpkin: Chousuke, nope. Both does not work. Here's maybe more context for the Mesh constructors: https://gist.github.com/153d4bc319da0b0f9efd

13:09 yoklov: try putting the vertex in an array

13:10 (to-array [vertex]) maybe?

13:11 flashingpumpkin: yoklov, nope

13:11 Chousuke: looks like it should work if you typehint the vertex

13:11 did you try typehinting it and forcing the 3s to ints at the same time?

13:12 flashingpumpkin: Chousuke, yes

13:12 (to-array [^VertexAttribute vertex])

13:14 I had no idea there is such a thing as varargs in java.

13:14 yoklov: Err, I don't really know what I'm talking about so its totally possible that putting it in an array is the wrong thing to do.

13:15 jodaro: ok, another gloss question

13:16 if i have something like

13:16 foo\0bar\0baz

13:17 is (repeated (string :utf-8 :delimiters ["\0

13:17 "]))

13:17 the right way?

13:20 TimMc: I guess try it out?

13:20 jodaro: yeah

13:20 its the 4 part of the protocol

13:20 TimMc: My only question would be whether there is a final delimiter. I guess there has to be.

13:20 jodaro: fourth part of a response, actually

13:21 yoklov: What's the difference between typehinting with #^type and ^type?

13:22 amro: is there a way to get more information out of "No value supplied for key: true"?

13:22 TimMc: yoklov: The latter is deprecated.

13:22 yoklov: otherwise they're the same?

13:22 clojurebot: I don't understand.

13:23 TimMc: amro: Are you trying to build a map?

13:23 I mean, what is the context?

13:23 mattmitchell: jodaro: in your example, what is "string" ?

13:24 clj_newb: this is an honest question; not an attempt at a flame war: I was reading about attmepts of clojure on llvm; and then all tend to mention that the llvm is bad at JIT ... this confuses me, what exactly does the JVM JIT do that the LLVM JIT does not do?

13:24 TimMc: yoklov: Wait, maybe it's the other way around...

13:24 clj_newb: (I was under the impression taht LLVM = the uber JIT, using the latest + best in research tech)

13:25 amro: TimMc: I was passing stuff to a lib, and wasn't sure how it was building a map out of it. was wondering if there's a way to get a representation of the map for debug, at the error

13:25 TimMc: yoklov: Right, ^ is the correct form.

13:25 amro: I fixed it since, but I'd still like to know for future reference

13:28 TimMc: &{:a 1 :b}

13:28 lazybot: java.lang.RuntimeException: Map literal must contain an even number of forms

13:28 jodaro: mattmitchell: its part of gloss

13:28 TimMc: So, not that error...

13:28 jodaro: https://github.com/ztellman/gloss/wiki/Introduction

13:28 TimMc: &(hahs-map :a 1 :b)

13:28 lazybot: java.lang.RuntimeException: Unable to resolve symbol: hahs-map in this context

13:28 TimMc: &(hash-map :a 1 :b)

13:28 lazybot: java.lang.IllegalArgumentException: No value supplied for key: :b

13:28 TimMc: amro: ^ that's what was happening in the lib.

13:28 lypanov: clj_newb: many people don't have much of a clue about it :)

13:29 clj_newb: but using llvm would be a huge amount of work. it'd require custom optimization passes

13:29 the JVM does a crazy amount of stuff.

13:29 sritchie: hey guys, I'm running into what might be a bug with inlined functions

13:29 https://gist.github.com/1551640

13:30 TimMc: &((fn [& {:keys [a b]}] nil) :a 1 :b) <-- amro: you were probably calling a function with keyword args like this one but missing a param

13:30 lazybot: java.lang.IllegalArgumentException: No value supplied for key: :b

13:30 sritchie: the environment seems to be interpreting ^bytes as a var, not a type hint

13:30 jodaro: hrm

13:30 sritchie: but only the second time I evaluate that form

13:31 jodaro: that "works", but the resulting byte buffers seem to be longer than i expect

13:31 if i encode ["foo" "bar"]

13:31 yoklov: clj_newb: LLVM isn't always JIT compiled, it's just availiable as an option. I don't really know, but that at least leads me to believe that it might not be their strongest area.

13:31 jodaro: i guess i'd expect 8 bytes

13:33 TimMc: sritchie: "Can't type hint a local with a primitive initializer"

13:34 clj_newb: lypanov , yoklov: so the core is: "JIT in Java is automatic. JIT in LLVM requires manual work." ?

13:34 sritchie: TimMc: yeah, hinting the original x and y doesn't pass through to the inline definition, unfortunately

13:34 TimMc: can you think of any way to hint those arguments?

13:35 TimMc: sritchie: Never mind, that was my bad -- I was passing in junk.

13:35 and I get the exception you see on the first call.

13:36 sritchie: (java.util.Arrays/equals ^bytes ~x ^bytes ~y)

13:37 sritchie: Also, you might use reduce.

13:38 amro: TimMc: thanks

13:38 TimMc: sritchie: The reduce idea might need work...

13:38 amro: but it said true, not :true, so it was building a map with true as a key I guess?

13:38 TimMc: amro: That's my guess.

13:39 &(hash-map true)

13:39 lazybot: java.lang.IllegalArgumentException: No value supplied for key: true

13:39 TimMc: &(hash-map :true)

13:39 lazybot: java.lang.IllegalArgumentException: No value supplied for key: :true

13:39 amro: yep, I just tried that

13:39 well, in any case I was misusing the API

13:41 yoklov: clj_newb: That could be it. If you really want more information, see if LLVM has an irc channel and ask them there. The clojure channel isn't likely to have many people who would know what optimizations LLVM does during JIT compilation.

13:42 sritchie: TimMc: that doesn't seem to pick up the type hint, unfortunately

13:44 lypanov: llvm has a irc channel on oftc

13:45 clj_newb: pretty much, though i'd rather say JIT in JVM has 30 years worth of experience fixing crap code.

13:45 clj_newb: llvm OTOH has very different goals. it is just an insanely great machine code generator.

13:46 clj_newb: you might also want to try #rubinius some of the guys there have actual experience, i just have 2nd hand guesses ;)

13:51 mattmitchell: if i used an atom as a way to more easily change state of a map, in a non-multi-threaded program, would this be considered misusing an atom?

13:54 jodaro: i think it depends on why you need to do it that way

13:54 TimMc: sritchie: Hmm, how can inlining be debugged?

13:54 sritchie: I'm not sure, I don't really know the expansion rules

13:56 clj_newb: this is starting to make sense now

13:56 I always wondered why such a brilliant langauge like clojure picked java

13:56 now I get it: it makes impelmenting clojure much much easier

13:56 yoklov: versus llvm?

13:56 clj_newb: no need to implement a VM, a FFI, or a JIT

13:56 it's all provided by java

13:57 yoklov: Or the hundreds of libraries that come with java.

13:57 TimMc: ":inline-arities >1?" <- wtf

13:57 clj_newb: Thus, all the effort of implementing clojure goes into implementing the new ideas that clojure provides; rather than the bitch work of setting up the core of a basic language.

13:57 mattmitchell: jodaro: well, there is a function with a lot of nested conditions. I was going to use reduce, but using an atom made it clear since, I only update the map if all of these nested conditions are met by calling swap!

13:57 TimMc: Oh, it's a private fn.

14:03 lypanov: clj_newb: there is a project called vmkit that if it were to be improved could offer all the advantages of JVM and llvm

14:03 but it'd be years of work

14:03 and openjdk is okay ish now

14:03 clj_newb: Currently asking in llvm on irc.oftc.net

14:04 I really like Clojure's approach to concurrency (immutability + vars + atoms + agents + stm); if only I could write programs that did not require the JVM like that ... :-)

14:06 mattmitchell: is there a built-in function for turning a collection of hash-maps into a hash-map, where the keys come from the values of the maps in the collection? Example: (some-fun [{:id 1} {:id 2}] :id) => {1 {:id 1} 2 {:id 2}} etc..

14:08 TimMc: mattmitchell: Ill-defined, what happens with key collisions?

14:08 Or can you assume there are none?

14:08 mattmitchell: TimMc: it can blow up in that case

14:08 yeah, there shouldn't be any

14:08 I'm using reduce right now, but it seems too complex

14:08 TimMc: for might be better

14:09 lypanov: clj_newb: you could, use clojurescript + v8 and implement it all on top of js "threading" concepts ;)

14:09 TimMc: mattmitchell: And maps are fine, no need to specify hash-maps.

14:09 mattmitchell: TimMc: ahh right

14:09 TimMc: could you give me a hint on the "for" approach? :)

14:11 jodaro: hrm, well, treating it as a single string and then splitting it on \x00 works for now

14:11 TimMc: &((fn [fk & ms] (into {} (for [m ms] [(m fk) m]))) :id {:id 1 :a 2} {:id 5 :b 4}) ;; mattmitchell

14:11 lazybot: ⇒ {1 {:a 2, :id 1}, 5 {:b 4, :id 5}}

14:12 mattmitchell: TimMc: awesome thanks

14:12 TimMc: mattmitchell: I think you could sneak a juxt in there, actually.

14:13 mattmitchell: oh maybe juxt and zipmap?

14:13 TimMc: &((fn [fk & ms] (into {} (map (juxt fk identity) ms))) :id {:id 1 :a 2} {:id 5 :b 4}) ;; assumes focal key is a keyword or symbol or other IFn

14:13 lazybot: ⇒ {1 {:a 2, :id 1}, 5 {:b 4, :id 5}}

14:13 mattmitchell: ahh i see

14:20 clj_newb: based on discussions on oftc llvm: ... Why is JITTing important to clojure? There are other scheme implementations, like Chicken ... that appear to be doing file while compiled. How exactly does Clojure use JITting?

14:25 TimMc: clj_newb: One cool thing is that with JIT, macros can expand in different ways depending on what libraries are available, or what version of Clojure is in use.

14:26 clj_newb: TimMc: how does macros related to JITTing?

14:26 lypanov: that can be done without JIT if the system applies system wide opts.

14:26 clj_newb: oh, macros can be done at _runtime_ ?

14:26 rather than multiple compilation passes?

14:27 TimMc: clj_newb: Yeah, JIT means you are distributing source, unexpanded.

14:27 amalloy: i think you two are confusing each other

14:27 clj_newb: amalloy: enlighten us

14:27 TimMc: oh no, an expert!

14:27 * TimMc runs away

14:27 amalloy: TimMc is just saying that the compilation happens in the same environment where code is going to execute

14:27 * clj_newb pulls out a pokeball. Experts: gotta catch em all.

14:27 amalloy: so you know what will be available

14:28 clj_newb: How does this related to JITTing?

14:28 raek: The oracle implementation of the JVM (Hotspot) uses JIT compilation to speed up the virtual machine.

14:28 amalloy: it's not related to java's JITing, but it is basically clojure's JIT: compile it Just In Time, before they run it

14:28 clojure doesn't care at all about java's JIT; it just runs on the jvm and gets a performance boost for free

14:29 TimMc: Yeah, I guess there's a jargon mismatch here.

14:29 AeroNotix: What's a good method for type checking in clojure?

14:29 TimMc: Clj -> .class -> native machine code -- *both* of those steps are compilations.

14:30 clj_newb: amalloy: ah, the point you're getting at is (1) Just in Time macro expansion vs (2) Just in Time compilation + code execution ?

14:30 amalloy: no

14:30 TimMc: &(instance? String "AeroNotix")

14:30 lazybot: ⇒ true

14:30 AeroNotix: Thank you

14:30 amalloy: that's the point that is dividing you and TimMc

14:30 AeroNotix: @TimMC thank you

14:30 TimMc: AeroNotix: isa? can do some fancier stuff

14:30 AeroNotix: thanks, I'll get to google

14:30 amalloy: i guess maybe that's the point i was getting at also

14:31 but it's not just "JIT macro expansion", because clojure really does compile all the code right before it runs. it has to expand the macros to do it, but...

14:34 lypanov: JIT implies continuous. clojure isn't continuous.

14:34 there is no "hotspot" detection in clojure's compiler. its just a compiler.

14:39 clj_newb: the more I learn about clojure; the more brilliant I think it is

14:40 I bet there's even a good, perfectly valid reason, why clojure does not have a builtin (make-me-a-sandwhich :meats '(beef pepperoni) :vegetables '(pickles onions))

14:40 AeroNotix: clj_newb: It does?

14:41 lypanov: clj_newb: glad you get it now, i decided to go down the scala road a year back after a quick dive into clojure burnt me and deeply regret it. back again.

14:44 clj_newb: lypanov: what did you like about scala / how did it burn you?

14:44 lypanov: clj_newb: i liked the fact that i could learn it fast as its similar to other things i've used and that it had a ton of cool language features.

14:44 clj_newb: i was burnt my its complexity.

14:44 by*

14:45 i also simply couldn't deal with the compile times.

14:45 its 2012!

14:45 ;)

14:45 * lypanov doesn't like going back to his c++ days of compile, snore, find bug, repeat

14:55 lypanov: anyone else read lwn.net & have a kindle?

14:55 * lypanov debating making a script for making sane mobi files

14:56 lynaghk: lypanov; have you seen the Send-to-Kindle google chrome extension? It's pretty decent at extracting article text and formatting for Kindle

14:57 lypanov: lynaghk: i'd really like to have a .mobi with nice headers and a ToC etc

14:57 i want to dissect whatever magic instapaper is performing is thats the format i'd like

14:59 lynaghk: Ah, makes sense. I've used Amazon's standard html to mobi converter on a few projects with luck, so hopefully it won't be too difficult.

14:59 Good luck

15:01 lypanov: yeah probably going to use kindlegen for it if i can get it to produce the right file

15:01 thank you :)

15:03 AWizzArd: When I eval *out*, a ^:dynamic var under Clojure 1.3, is that then equivalent to @#'*out*, from an efficiency point of view?

15:04 I noticed that (time (dotimes [i 10000000] *out*)) and (time (dotimes [i 10000000] @#'*out*)) take the same amount of time, vs. (time (dotimes [i 10000000] "hi")), which is much faster (as I expected).

15:07 holo: hello

15:09 AWizzArd: My understanding is: as *out* and *err* are dynamic vars, Clojure needs to deref them at runtime, where deref means: look up the current thread-local value. And this should be equivalent to dereferencing a var. Yes/No?

15:10 amalloy: AWizzArd: it's probably similar, though i suspect *out* is a little easier to inline. why not write both functions, AOT-compile them, and look at the bytecode?

15:11 AWizzArd: amalloy: my background, why I came up with this question is that I want to write a logging function which can log to *out*, and one which logs to *err*. Both fns are 5-liners and are identical, with the exception of their arg to the .write method.

15:12 So instead it would be the right thing to have a factory fn instead, which gets called with those two args. But that of course would make those two logging functions statically log into whatever value *out* or *err* had when I called the factory.

15:13 amalloy: huh? why of course? i don't think i understand you

15:13 AWizzArd: (def out-logger (make-logger *out*)) <-- out-logger always .writes to the same Writer.

15:13 amalloy: (make-logger #'*out*)

15:13 AWizzArd: Exactly.

15:13 This would work.

15:14 But then: (.write #'*out* ...) doesn’t. Of course, because it expects a Writer, not a Var.

15:14 So I would have to deref the arg to make-logger.

15:14 amalloy: right

15:14 AWizzArd: And when I realized this I thought: will this be less efficient than writing explicitly (.write *out* ...)?

15:15 The dotimes micro benchmark from above indicates that it makes no difference at all.

15:15 But looking at the bytecode seems like a reasonable idea.

15:16 amalloy: AWizzArd: i'm doing that already, i'll let you know

15:16 AWizzArd: Oh good, thx.

15:17 simonadameit: Hi, can I add functions (maybe even private ones) to a deftype without implementing an interface?

15:18 AWizzArd: simonadameit: but you still want polymorphism?

15:18 Because otherwise you could just write an ordinary defn or defn- for the private version, which expects one or more instances of a deftype.

15:18 raek: simonadameit: if they do not participate in the protocol, you can just have them outside the defrecord form

15:18 amalloy: AWizzArd: @#'*out* has more obvious work in it: https://gist.github.com/1551956

15:18 raek: as ordinary functions

15:19 simonadameit: raek: you mean without specifying them inside the deftype form?

15:19 raek: yes

15:19 AWizzArd: amalloy: hmm I see

15:20 raek: (defn- foo [...] ...) (defrecord Bar [...] SomeProto (some-method [...] ... (foo ...) ...))

15:20 amalloy: mainly because you have to actually call clojure.core/deref, i think

15:20 as compared to just calling .get on the var

15:21 AWizzArd: amalloy: then I either have to 1) accept this extra work from deref, or 2) duplicte code and write out both fns explicitly or 3) write a macro

15:22 simonadameit: raek but they wont be implemented as methods directly defined in the class backing the deftype?

15:22 raek: simonadameit: yes.

15:23 they will be implemented as a method in a function class instead

15:24 the reason you want to have protocol methods implemented as java methods is fast polymorphism

15:24 simonadameit: ah, ok.. I dont need polymorphism for these functions

15:24 raek: but for a private helper function that is only used in one implementation of the protocol you don't use any polymorphism

15:25 exactly

15:28 simonadameit: thanks raek, .. I guess I will have to get used to this separation of function and data :)

15:29 AWizzArd: amalloy: interesting, it seems there is then no other way to parameterize on dynamic vars.

15:30 amalloy: hm? you could do .get on the Var with interop instead of using the more generic deref, since you don't need genericity

15:32 AWizzArd: amalloy: calling .get will probably also result in more code than what you got for (defn foo [] (println *out*)).

15:33 amalloy: not really. it should just add a single checkcast to that version

15:34 and even that much shouldn't be necessary; if the compiler were able to detect that you only use the value once and always treat it as a Var it could do the cast once and forget it

15:36 simonadameit: what is the name of the protocol that conj is part of?

15:37 amalloy: it's an interface

15:37 clojure.lang.IPersistentCollection/cons, i think

15:39 raek: simonadameit: this can be useful: https://github.com/Chouser/clojure-classes/blob/master/graph-w-legend.png

15:40 augustl: is there a way to disable all of the built-in pages of noir? Such as the default 404 page for example.

15:41 simonadameit: raek thanks, thats great

15:43 is there a performance difference between using extend-type or defining the methods directly in a deftype`

15:43 ?

15:44 amalloy: yes, but not one that's likely to matter if you're implementing something slower than hello world

15:49 bweaver: Hello, does Clojure memoize regex pattern objects when they're written in the #"..." literal format? I'm writing a predicate function that uses re-matches and wonder if there's a performance advantage to declaring the regexp pattern separately vs using it inline.

15:53 amalloy: those are reader macros, so the objects should be embedded in the code

15:53 ie, no memoization is necessary

15:54 raek: bweaver: if you're wondering whether #"..." will only instantiate a Pattern once, then yes (IIRC)

15:54 bweaver: Ok, thanks.

15:59 Xenocorp_: in emacs repl. If I shadow a built-in, how do I reset the repl?

16:03 bweaver: Xenocorp_: You can `(use 'clojure.core)` to re-import all of the core bindings into your namespace. Does that help?

16:04 Xenocorp_: bweaver: That'll do :)

16:04 Thanks

16:15 augustl: is there a reference to all the syntax in clojure? Currently trying to find out what the ampersand in (defn foo [& something] ....) means

16:16 bweaver: augustl: I find that the cheatsheet is helpful `http://clojure.org/cheatsheet`, most other reader stuff is documented in `http://clojure.org/reader`.

16:17 augustl: The amphersand captures the rest of the arguments. So in your example, it means `foo` will accept any number of arguments and they'll be bound into a list called `something`.

16:17 augustl: ah that cheat sheet is useful

16:17 bweaver: augustl: So, for example, calling `(foo 1 2 3)` will bind `something` to `(list 1 2 3)`.

16:17 augustl: Or maybe it's a vector.

16:17 augustl: I see, thanks

16:18 amalloy: neither, actually. but you get a sequential view of it, which is all that matters

16:19 bweaver: Thanks amalloy :)

16:19 amalloy: &((fn [& args] (class args)) 1 2 3)

16:19 lazybot: ⇒ clojure.lang.ArraySeq

16:19 augustl: found the docs in http://clojure.org/special_forms

16:19 for the record

16:19 Scorchin: If I'm using clojure 1.3, how do I add clojure-contrib to my project?

16:22 augustl: Scorchin: I'm using leiningen, I added [org.clojure/clojure-contrib "1.2.0"] to dependencies in project.clj

16:22 Scorchin: augustl: is 1.2.0 the latest stable version? The website wasn't very clear on that

16:22 technomancy: clojurebot: what happened to clojure contrib?

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

16:22 technomancy: clojurebot: what happened to contrib?

16:22 clojurebot: Well... it's a long story: http://dev.clojure.org/display/design/Where+Did+Clojure.Contrib+Go

16:22 amalloy: if you want old-contrib in a 1.3 project, step one is ritual suicide

16:23 Scorchin: technomancy: <3

16:23 augustl: Scorchin: don't remember how I found that version number, I remember struggling with that as well

16:30 given (def foo [:my :vector]) (def bar [:other :vector foo]), is there a way to make the value of bar [:other :vector :my: :vector] instead of [:other :vector [:my: :vector]]?

16:30 amro: in what case would (print (str (type x))) output nothing?

16:30 Scorchin: interesting, if I load up a plain repl and type: (clojure.string/split-lines "test \n string") it throws the following error: ClassNotFoundException clojure.string java.net.URLClassLoader$1.run (URLClassLoader.java:202)

16:30 Anyone what's going on there?

16:31 technomancy: Scorchin: you haven't loaded the clojure.string namespace

16:32 bweaver: augustl: `(vec (flatten bar))`?

16:32 Scorchin: technomancy: thank you

16:33 augustl: bweaver: cool, thanks

16:33 nick_s: Is let free?

16:34 bweaver: augustl: You could also use `concat` depending on whether you needed the intermediate nested vector for anything.

16:34 nick_s: After it's compiled that is. Does a let binding have a performance cost associated with it?

16:34 amalloy: if what you want is [:other :vector :my :vector], then your "given" (def foo [:my :vector]) (def bar [:other :vector foo]) means you started wrong

16:36 mcrittenden-afk: noir's built in server isn't meant to be used in production, right? and if not, then what are people using?

16:37 oh just realized it uses jetty which I assume would be fine in production. never mind.

16:37 Xenocorp_: apparently at my work we're using two toasters strapped together with an ethernet cord

16:40 augustl: pastie can't highlight lisps it seems, any suggestions? :)

16:40 amalloy: ~paste

16:40 clojurebot: paste is gist

16:40 amalloy: ugh, really?

16:40 clojurebot: forget paste |is| gist

16:40 clojurebot: I forgot that paste is gist

16:40 amalloy: clojurebot: paste is https://gist.github.com

16:40 clojurebot: c'est bon!

16:41 technomancy: paste is delicious

16:41 augustl: thanks

16:41 zilti: amalloy: pastie.org can highlight Clojure: http://pastie.org/l

16:41 augustl: since I don't know much about clojure, it seems to me that these calls would be identical https://gist.github.com/1552241

16:41 is there an easy explanation for a noob? :)

16:42 just seems to me that (vec (flatten head-extra)) evaulates to a vector, i.e. exactly the same as head-extra

16:42 amalloy: zilti: i have no opinion about pastie, but he asked for a good pastebin, and that's gist

16:42 technomancy: flatten?

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

16:42 amalloy: ~botsnack

16:42 clojurebot: Thanks! Can I have chocolate next time

16:42 bweaver: augustl: You might want to try appending head-extra instead of inserting it into the vector literal.

16:42 zilti: amalloy: I prefer gist, too

16:43 amalloy: bweaver: nah, that shouldn't matter

16:43 augustl: bweaver: it's nice to keep the literal structure when doing HTML..

16:43 * technomancy used to use paste.lisp.org back in the day

16:44 augustl: anyhow, is "flatten" a special form of some sorts that makes stuff happen under the hood?

16:44 amalloy: no, flatten is a great evil sent by the devil

16:44 bweaver: augustl: no, it's just a function

16:44 amalloy: included only to confuse people into using it when they shouldn't

16:44 augustl: still don't quite grok the difference between the two calls, since vec evaulates to a vector (I guess)

16:45 amalloy: augustl: the difference is, what if head-extra is [:foo [:bar [:baz]]]

16:45 flatten turns it into [:foo :bar :baz]

16:45 augustl: the only thing I can think of is that "flatten" sets some state under the hood that causes clojure to evaulate the vector differently

16:45 ah we wouldn't want that..

16:46 bweaver: augustl: for what it's worth, you might try using quasiquoted lists instead of vectors for representing markup

16:46 augustl: `(:head (:title "...") ~@head-extra)

16:46 amalloy: bweaver: i have to wonder what position you're giving advice from. hiccup uses vectors

16:46 augustl: wonder if hiccup supports that

16:46 ah, right

16:46 bweaver: amalloy: oh, didn't know that

16:47 amalloy: I'm new to Clojure too and just find quasiquotes convenient. If there's a framework already, then that's definitely more convenient :)(

16:47 amalloy: This is what I was thinking of: http://okmij.org/ftp/Scheme/SXML.html

16:47 augustl: the value of head-extra in my case is ["Test test"], so I still don't understand how flatten helps me in this case :)

16:47 I do understand it will turn nested lists into flat lists

16:47 bweaver: augustl: Sorry augustl, ignore me :)

16:47 augustl: not how it "concatinates" vectors into other vectors, inline, sort of

16:47 bweaver: augustl: I was assuming something different than what you're trying to do.

16:48 amalloy: it doesn't help you, flatten never helps, i wish i could remove it from clojure.core

16:48 augustl: it does actually help me in this situation, though

16:48 perhaps my head-extra vector doesn't have the value I think it does..

16:48 amalloy: no, it obviously doesn't, because (vec (flatten ["foo"])) ie still ["foo"]

16:49 if your goal is to end up with the contents of head-extra dumped into the head, you want ##(doc into)

16:49 lazybot: ⇒ "([to from]); Returns a new coll consisting of to-coll with all of the items of from-coll conjoined."

16:49 amalloy: (into [:head [:title ...] ...] head-extra)

16:49 or if you prefer, `[:head [:title ...] ... ~@head-extra]

16:50 augustl: updated https://gist.github.com/1552241, build-head-3 works and I understand it, so yay :)

16:50 amalloy: hmm that's interesting, I wonder why build-head and build-head-2 behaves differently then

16:50 that's good to hear, at least, that means I did actually understand what flatten did ;)

16:50 skelternet: I've been building tables with hiccup.

16:51 augustl: amalloy: ah I'll look up the ~@foo syntax

16:51 skelternet: I noticed some of the tags seem to only respect one parameter the way I had been using them.

16:52 technomancy: warms my heart seeing all these folks learning Clojure for 2012 =)

16:52 cgray: is there any way to get a clear picture of how much memory is actually being used by a clojure process? top just shows how much the jvm has allocated, which i guess is usually more than is used

16:53 skelternet: for instance, I had a [:tr (for … (println something) [:td column] … and the td's weren't getting returned

16:53 augustl: odd, "Attempting to call unbound fn: #'clojure.core/unquote-splicing ", guess I need to import something

16:53 skelternet: Don't know if that helps, agustl,

16:53 I'm still trying to wrap my head around it.

16:53 augustl: skelternet: hmm, you probably need to map instead of for looping?

16:53 amalloy: augustl: you didn't include `

16:53 augustl: not sure what a for loop that prints is doing inside a vector that's supposed to represent HTML :)

16:54 skelternet: was just there while debugging…but it seemed to make things worse while it was there :|

16:54 when I removed it, life was better

16:54 augustl: amalloy: include what? :)

16:55 cgray: augustl: the backtick symbol

16:55 augustl: oh

16:55 amalloy: &(let [x 1] `(:foo ~x))

16:55 lazybot: ⇒ (:foo 1)

17:04 clj_newb: I need to gain 6000 experience points to advance from clj_newb to clj_novice. What are good clojure codebases to read?

17:04 cgray: clj_newb: core.clj is a pretty good place to do some learning

17:05 clj_newb: sorry, I mean clojure.core

17:05 amalloy: downvote. core is interesting once you already know a lot

17:05 but it contains a ton of stuff that is a Bad Idea in other code because it's bootstrapping

17:05 cgray: good point

17:05 maybe the second half of core or so

17:05 pandeiro: amalloy: anything you'd recommend?

17:06 clj_newb: "bootstrapping" <-- as in the code is not idiomatic, because clojure idioms requires things in clojure.core ?

17:06 amalloy: right

17:06 clj_newb: actually, that sounds awesome; I love understanding how things work

17:07 amalloy: *shrug* what you should read depends on what you want to learn

17:07 clj_newb: the great thing about software, as opposed to hardware is that I don't have to put it back together

17:08 amalloy: this is an honest question. Why are you so well respexcted in this channel? Did you write some library in clojure.core or clojure.contrib?

17:09 amalloy: haha no, it's because i spend a lot of time in here. i have more fun helping out than writing a magnum opus

17:09 but a lot of www.4clojure.com is mine, if you're looking for an excuse to idolize me

17:10 clj_newb: I merely found it interesting how that whenever you disagree with someone, they just assume you're right. :-)

17:10 what does 4clojure have to do with cheap realestate?

17:10 amalloy: foreclosure

17:10 it's a pun, you see. not my pun, thank god

17:11 cgray: clj_newb: the damn thing is, he is right so much of the time... plus it's just a pretty respectful community in general

17:13 augustl: clj_newb: currently making a simple web page with Noir. Learning a lot from that.

17:13 I got about 200 experience points after a couple of hours!

17:14 clj_newb: augustl: lol

17:15 amalloy: I have an exercise suggestion for 4clojure.com: "Input: a 3SAT formula. Output: in polynomial time, iether true or false, stating whether the formula is staifisable."

17:15 amalloy: i don't know what 3SAT is. but solve 50 4clojure problems, then you can submit that as a problem yourself

17:18 haha, were you trolling me? you: "output in polynomial time..." wikipedia: "3-SAT is NP-complete..."

17:22 clj_newb: amalloy: look up millenium prize -- a solution is worth 1 million dollars. Additionally, it's probably also worth a turing award. :-)

17:22 amalloy: sure, i know. as a kid i figured i would win that prize by solving minesweeper

17:22 * clj_newb googles paper on minesweeper being NP complete

17:23 clj_newb: damn, it is NP complete

17:23 amalloy: how old are you? the Clay prize isn't that old, and you mention "as a child ..."

17:24 amalloy: yeah, "kid"

17:24 i must have been like 17 at the time. 26 now

17:46 solussd: is there something clojure more generic than (Long/parseLong "1367") ?

17:47 i.e. something that'll work on any number

17:47 amalloy: &(doc read-string)

17:47 lazybot: ⇒ "([s]); Reads one object from the string s"

17:47 solussd: ,(read-string "387429837492387492734923794729347923749")

17:47 clojurebot: 387429837492387492734923794729347923749N

17:49 wingie: is clojure fine to script with?

17:49 AWizzArd: solussd: I don’t know about the efficiency, but there is also a .parse method in http://docs.oracle.com/javase/7/docs/api/java/text/DecimalFormat.html available.

17:49 wingie: compared to groovy

17:50 solussd: ,(.parse "23984294832.23423")

17:50 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching field found: parse for class java.lang.String>

17:51 solussd: oh, duh.

17:51 AWizzArd: Yes, I think the String class doesn't provide such a .parse method.

17:53 This DecimalFormat class also provides parsing for some more exotic formats. Though as long read-string works fine I would surely prefer that one.

17:55 http://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html

17:56 TimMc: solussd: Just be sure to (binding [*read-eval* false] ...) around that for security.

17:56 wingie: If you don't mind the several-second startup time of the JVM, sure, it's fine to script with.

17:56 solussd: yeah, I think that's overkill for me. :)

17:57 TimMc: solussd: Well, as long as you aren't reading user-generated strings, OK.

17:57 solussd: oh, you're referring to 'read-string'

17:57 TimMc: Yeah, sorry.

17:58 wingie: Compared to any other JVM language I know of, yes, Clojure is the best for scripting -- LISPs are great for extracting patterns.

17:59 solussd: TimMc, what could be fed to read-string that would result in evaluation?

17:59 TimMc: &(read-string "#=(+ 1 2)") ; solussd

17:59 lazybot: java.lang.RuntimeException: EvalReader not allowed when *read-eval* is false.

17:59 TimMc: Semi-undocumented syntax.

18:00 solussd: yikes

18:00 TimMc: I've opened a ticket to document that in read and read-string -- it's an "unsupported feature", but the lack of documentation is outright dangerous.

18:00 solussd: what does #= mean exactly?

18:01 TimMc: solussd: It means to use the results of evaluating the next form.

18:02 solussd: Put (read-string "[(+ 1 2) #=(+ 1 2)]") into a REPL.

18:03 clojurebot is stupid, I can demonstrate here:

18:04 ,(binding [*read-eval* true] (read-string "[1 2 #=(- 7 4) 4]"))

18:04 clojurebot: [1 2 3 4]

18:04 TimMc: The main use is serializing data structures that don't have literal support.

18:05 solussd: TimMc: whoa. So I could force evaluation of macro arguments when I pass them

18:05 TimMc: Not following that.

18:06 Seriously, don't use #= in your code -- it's probably going away.

18:06 chipdude: so #=() is a lift macro

18:07 solussd: (defmacro printform [form] `'~form)

18:07 TimMc: It's reader syntax.

18:07 wingie: TimMc: is there any way to eliminate the startup time for java? (im new to java)

18:07 chipdude: [1 #=(prn 2) (x)]

18:07 2

18:07 java.lang.Exception: Unable to resolve symbol: x in this context (NO_SOURCE_FILE:2)

18:08 solussd: then I could (printform #=(+ 2 1)) to force it to pass 3

18:09 chipdude: TimMc: what will replace it

18:14 TimMc: chipdude: Nothing official, I'm just guessing.

18:15 I *think* it was mainly used for records, which now have their own (also undocumented!) literal syntax.

18:18 technomancy: Did you take a look at the no-AOT uberjar example I wrote?

18:24 amalloy: TimMc: i don't think #= is actually going away anytime soon, but it's definitely something to avoid anyway

18:24 TimMc: amalloy: Do you know what else it is used for?

18:24 amalloy: &(print-dup (sorted-set))

18:24 lazybot: clojure.lang.ArityException: Wrong number of args (1) passed to: core$fn--4023$fn

18:25 amalloy: &(binding [*print-dup* true] (pr-str (sorted-set)))

18:25 lazybot: java.lang.SecurityException: You tripped the alarm! pop-thread-bindings is bad!

18:25 TimMc: Ah, right.

18:25 clojurebot won't mind

18:25 amalloy: damn it Raynes, can you just let the thread-binding stuff back into the list? he is crippled without binding

18:25 ,(binding [*print-dup* true] (pr-str (sorted-set)))

18:26 clojurebot: "#=(clojure.lang.PersistentTreeSet/create [])"

18:27 TimMc: amalloy: pop-thread-bindings is only found in the macro expansion -- does clojail really need to inspect the expansion results?

18:27 (Or rather, why.)

18:28 amalloy: &(macroexpand '(clojure.lang.Compiler/eval foo))

18:28 lazybot: java.lang.SecurityException: You tripped the alarm! class clojure.lang.Compiler is bad!

18:29 augustl: someone told me earlier what I had to do to enable ~@ (unquote-splicing), but I didn't grok what it was.. Anyone knows?

18:29 getting "Attempting to call unbound fn: #'clojure.core/unquote-splicing"

18:29 amalloy: ugh, whatever. the point is there are a lot of "special cases" where stuff doesn't look like a problem until it's expanded

18:29 skelternet: I might have it in a buffer, do you need it or need to grok it?

18:30 TimMc: amalloy: I see, lots of sugary stuff.

18:31 doto, etc.

18:31 amalloy: right. but you make an interesting point, i think

18:31 augustl: skelternet: need to grok it :)

18:31 amalloy: i (or Raynes?) just macroexpanded because it seemed like you could hide dangerous things inside a macro

18:32 augustl: need to import `, not sure how to do that

18:32 chipdude: TimMc: the record syntax is as found here? http://dev.clojure.org/display/design/defrecord+improvements

18:32 amalloy: there's nothing to import

18:33 augustl: oh, I'm probably using it wrong then

18:33 amalloy: TimMc: actually i think memfn was the macro that makes it necessary to expand

18:33 TimMc: Ah, right.

18:34 So you'd have to look at all the things that mess with names and calling. Ugh.

18:34 &`[1 2 3 ~@(list 4 5 6) 7 8] ; augustl

18:34 lazybot: ⇒ [1 2 3 4 5 6 7 8]

18:35 technomancy: TimMc: yeah, makes it sense

18:36 maybe package it up as a plugin?

18:36 TimMc: I'm trying to think how exactly.

18:37 There's also the question of how to indicate that this is the desired behavior.

18:37 technomancy: if you had it read the main ns out of jar metadata, you could probably just make it a plain old dependency

18:37 wouldn't need to be a plugin

18:38 TimMc: I was thinking a resource like uberjit.properties

18:39 But no, that's silly -- there might be multiple.

18:40 jmdev: Hi guys

18:40 technomancy: jar metadata lives in project.clj right next to :main; it makes sense to keep them together

18:41 augustl: I

18:41 err

18:41 I'd appreciate if you could tell me how horrible my build-main-menu from https://gist.github.com/1552654 is, and how it could be better :)

18:42 amalloy: (defn ... (def)) is evil

18:42 augustl: I should inline it?

18:42 raek: augustl: def is only for global constants

18:42 amalloy: no, you should never use def inside a defn

18:42 you want let

18:43 augustl: ah

18:43 a "minor" oversight..

18:43 skelternet: would the inner def survive outside of the scope?

18:43 tag-attrs in this case?

18:43 raek: skelternet: it will mutate a global variable

18:43 augustl: I'm curious if my use of concat of vectors makes sense. Not used to functional programming and static collections

18:44 and if having a build-main-menu-iter makes sense. Inspired by SICP which I just started reading ;)

18:44 yoklov: haha i thought your code looked like scheme code

18:44 but wasn't going to say anything because mine does too lol

18:44 augustl: recur is the only "trick" I learned so far ;)

18:45 TimMc: skelternet: The inner def would not become defined until that function had been called.

18:46 amalloy: the manual recursion looks a lot like a map or a mapcat or something

18:46 skelternet: I thought mutations to it were stacked and thread-specific. I must be thinking of bind

18:46 amalloy: but it's hard to tell because you wrote it as manual recursion and now it takes all this effort to read :P

18:46 augustl: guess I could use conj instead of concat-ing vectors

18:46 amalloy: hehe, the idea is that I need to pass active-menu to the calls to build-main-menu-item

18:46 seems that map only passes the item in the collection and doesn't support arbitrary params

18:47 raek: skelternet: yes, when using 'binding' and 'set!'

18:47 arohner: using clj-http, is there any way to set a lower timeout for a request? i.e. "throw if this request takes more than N seconds to finish"?

18:47 augustl: hmm seems conj isn't what I need

18:48 skelternet: def will just mutate it…whenever def gets eval'd? that would be much more difficult to reason about

18:48 raek: but 'def' is for those cases when you unconditionally want to change a global in all threads (unthreadsafely) -- nameley when fixing existing code

18:48 amalloy: (defn build-main-menu [active-menu] (mapcat #(build-main-menu-item % active-menu) main-menu-links))?

18:48 raek: skelternet: yes

18:48 it should normally only be used on the top level

18:48 skelternet: same for defn?

18:48 raek: yes

18:48 augustl: amalloy: ah, mapcat looks nice

18:49 raek: think of 'def' as define global / repair broken global

18:49 augustl: and #() is shorthand for a lambda/anon function right?

18:49 yoklov: yes

18:50 raek: skelternet: (defn foo ...) is just a shorthand for (def foo (fn ...))

18:50 yoklov: you can also use fn which is the same as lambda.

18:50 raek: it's a macro

18:50 augustl: hah, awesome

18:51 skelternet: (dreaming of swapping out implementations of a protocol mid-execution)

18:51 augustl: now it's just https://gist.github.com/1552654

18:51 time to open The Joy of Clojure and grok what the % does :)

18:51 yoklov: it's the parameter for the #() function shorthand.

18:52 TimMc: %`#(+ %1 %3)

18:52 &`#(+ %1 %3)

18:52 lazybot: ⇒ (fn* [p1__14814__14817__auto__ p2__14816__14818__auto__ p3__14815__14819__auto__] (clojure.core/+ p1__14814__14817__auto__ p3__14815__14819__auto__))

18:52 augustl: updated it to use just map (still https://gist.github.com/1552654)

18:52 skelternet: it's almost built-in obfuscation

18:53 amalloy: yeah, the mapcat was (i think) replicating what you were doing but didn't make sense to me

18:53 raek: ,(* (+ (+) (+) (+)) (+ (+) (+)) (+ (+) (+)))

18:53 clojurebot: 0

18:54 raek: right

18:54 ,(* (+ (*) (*) (*)) (+ (*) (*)) (+ (*) (*)))

18:54 clojurebot: 12

18:54 raek: don't forget to obfuscate your number constants!

18:54 chipdude: raek: it's at times like these I wish the mathematicians would go back to paper and leave us to our ones and zeroes

18:55 augustl: what's the % called?

18:55 hard to google..

18:55 amalloy: percent

18:55 TimMc: haha

18:55 augustl: I mean the use of % in clojure, silly

18:55 or in that particular situation, even

18:55 skelternet: oh…anon function?

18:56 augustl: isn't #() the anon function part?

18:56 yoklov: argument?

18:56 TimMc: augustl: The whole thing is referred to as a "function literal". I think that's as close as you're going to get.

18:56 yoklov: http://clojure.org/reader under "anonymous function literal"

18:56 TimMc: augustl: Right, and % is just captured by the macro.

18:56 augustl: so the % in #(build-main-menu-item % active-menu) is part of the #() syntax, which is the function literal syntax?

18:56 ah

18:57 thanks, folks

18:57 amalloy: weird to use the word "literal" in that context

18:57 TimMc: (It might not be a macro technically, but it basically acts as one.)

18:57 augustl: so % is about macros

18:57 TimMc: Nope.

18:57 yoklov: it's a reader macro, not a normal macro

18:57 amalloy: nothing about macros except in a very uninteresting sense

18:58 raek: ,(read-string "#(foo % bar)")

18:58 clojurebot: (fn* [p1__81#] (foo p1__81# bar))

18:58 amalloy: raek: easier to just quote it

18:59 raek: amalloy: true.

18:59 amalloy: ,'#(foo % bar)

18:59 clojurebot: (fn* [p1__106#] (foo p1__106# bar))

18:59 TimMc: amalloy: Can you think of any normal macros in Clojure that capture symbols?

18:59 try/catch is a special form...

18:59 raek: TimMc: I think 'proxy' does it with the 'this' parameter

18:59 augustl: hmmmmmm

18:59 ah right of course

18:59 amalloy: yeah, good call raek

18:59 raek: I don't think it's considered good style, though

18:59 augustl: it just creates an anonymous function that calls the original function and passes active-menu to it

19:00 TimMc: &(let [% 5] 5)

19:00 lazybot: ⇒ 5

19:00 augustl: so it's the same as (fn [index] (build-main-menu-item index active-menu))

19:00 right?

19:00 TimMc: bah

19:00 &(let [% 5] %)

19:00 lazybot: ⇒ 5

19:00 amalloy: yes

19:00 yoklov: augustl: right

19:01 augustl: and % is the way you reference args in #()

19:01 TimMc: augustl: %1, %2, %3... -- yes

19:01 % is %1

19:01 augustl: yay :)

19:01 thanks again folks

19:01 yoklov: oh huh, you can use `this' inside proxy?

19:01 raek: the highest number used determines how many arguments the function takes

19:02 augustl: raek: that's useful, thanks

19:02 TimMc: And there's %& for rest args.

19:03 A function with %1, %5, and %& in it will effectively have the formal params [p1 p2 p3 p4 p5 & pmore].

19:04 augustl: and this is not related to the #() macro? I'm guessing you can't do (fn [] (stuff %1 %5)) though

19:04 TimMc: It's only #().

19:04 augustl: I see

19:04 TimMc: augustl: Try using syntax-quote (`) on function literals; see how they expand.

19:05 augustl: will do :)

19:05 TimMc: They'll be ugly because of double gensym'ing.

19:05 augustl: haven't learned a new language for quite some time now. It's pretty mind blowingly awesome.

19:06 it being clojure probably helps too

19:08 raek: TimMc: augustl: ordinary quote (') works fine for this purpose as well

19:09 as amalloy showed before

19:09 TimMc: raek: Ooh, right -- and only a single level of gensym.

19:10 amalloy: &`#(%)

19:10 lazybot: ⇒ (fn* [p1__14849__14850__auto__] (p1__14849__14850__auto__))

19:10 augustl: aww, arrow keys doesn't work in the repl

19:10 amalloy: heh, i never realized that would have multiple gensyms. funny, TimMc

19:11 TimMc: augustl: Are you using leiningen? Install rlwrap, lein will pick it up.

19:15 solussd: in 1.3, where do I get zip-filter? I see clojure.data.zip, but it is "the future home of zip-filter"… :/

19:20 TimMc: solussd: I think it's correct.

19:21 solussd: TimMc, k. so I can't add it as a dependency in my leiningen project.clj?

19:22 TimMc: No, I mean I think it's the new location.

19:24 augustl: TimMc: I'm using leiningen yes, thanks for the tip

19:25 TimMc: that's better :)

19:25 TimMc: I can't be arsed to file a ticket to get them to fix the README.

19:28 technomancy: quick poll: what's the path to tools.jar vs (System/getProperty "java.home") for the JDK you use?

19:29 quizme: how do you write to a file from a ByteBuffer?

19:30 TimMc: technomancy: Can't find it, OpenJDK Runtime Environment (IcedTea6 1.9.10) (6b20-1.9.10-0ubuntu1~10.10.2)

19:30 OpenJDK Client VM (build 19.0-b09, mixed mode, sharing)

19:30 technomancy: TimMc: whoa; a client JVM? are you running a 64-bit OS?

19:30 yoklov: someone mentioned that #^type was deprecated in favor of ^type. is there any difference between those, or is it being deprecated because ^type looks nicer?

19:31 TimMc: technomancy: Linux kibble 2.6.35-30-generic #61-Ubuntu SMP Tue Oct 11 15:29:15 UTC 2011 i686 GNU/Linux

19:31 quizme: I tried this: (let [fout (-> dest java.io.FileOutputStream. .getChannel)] (do (.write fout buf) (.close fout)) but it's not writing. (actually it's a HeapByteBuffer

19:31 TimMc: doesn't look like it!

19:31 technomancy: TimMc: bummer; I was hoping you had found a way to run a client JVM on a 64-bit system without compiling your own. =\

19:31 didn't realize people still used 32-bit Oses

19:32 TimMc: technomancy: That laptop is from 2005.

19:32 technomancy: well there ya go

19:34 TimMc: technomancy: I don't like specifying the uberjit loader namespace as :main -- it confuses the reader, and more importantly, the REPL.

19:34 technomancy: hm; in that case you'd need a plugin

19:35 TimMc: And as for my Ubuntu Natty machine, OpenJDK 1.6.0_22 (x64, Server) does not have an obvious tools.jar either.

19:36 technomancy: find /usr/lib/jvm -name tools.jar gives nada?

19:36 TimMc: No, that's wrong -- it's down a level!

19:37 cgray: technomancy: /usr/lib/jvm/java-6-openjdk-i386/lib/tools.jar and "/usr/lib/jvm/java-6-openjdk-i386/jre"

19:37 technomancy: cool; thanks

19:37 cgray: what OS?

19:38 cgray: technomancy: debian gnu/linux

19:38 technomancy: cool.

19:38 how bout any macosecksists?

19:38 TimMc: technomancy: ../lib/tools.jar on my Server VM, nothing in my Client VM (except /usr/lib/jvm/java-1.5.0-gcj-4.4/lib/tools.jar)

19:38 technomancy: yeah... I don't think gcj really counts

19:39 TimMc: heh

19:49 technomancy: switching swank-clojure's default branch back to master; woo

20:01 TimMc: amalloy: Your clojopts project -- any plans to make a 1.3 release?

20:03 amalloy: TimMc: it's been like a year since i touched it; you're probably better off using tools.cli, though i'd love to hear why you like clojopts better

20:03 TimMc: amalloy: Well, it's the only thing I saw when I searched for "clojure getopt". :-P

20:04 amalloy: well, to be fair that's what i do that's better than cli. he rolls his own option parser which imo kinda sucks

20:04 i used the java port of gnu getopt

20:06 TimMc: amalloy: I was looking at making clojopts 1.3 compatible. The reliance on contrib is contrib.seqs/separate (which is easy to replicate) and macro-do from your macro-utils.

20:07 I can't tell what macro-do macro-does.

20:07 amalloy: TimMc: depend on useful instead of amalloy-utils

20:07 templating: (macro-do [name val] `(def ~name ~val) foo 1, bar 2) => (do (def foo 1) (def bar 2))

20:08 TimMc: if you wind up preferring clojopts but find it's missing a feature or two then a fork would be lovely. ISTR it was hard (even for me) to figure out the syntax for using clojopts, so hopefully i documented it

20:08 TimMc: You did.

20:41 amalloy: Using useful would pin it to 1.3 -- what are your thoughts on maintaining backwards compat?

20:41 amalloy: TimMc: useful doesn't depend on anything in 1.3

20:41 TimMc: OK, sweet.

20:41 Right, that's a soft dependency in project.clj.

21:00 amalloy: Sweet, that was simple enough: https://github.com/timmc/clojopts/commit/5d243ffc03600e04765d49df46b36145aa8b2dee

21:03 amalloy: awesome, tests

21:08 TimMc: amalloy: Should I make the juxt change and do a pull request, or what?

21:09 amalloy: yeah, send off a pull request and i'll be happy to release to clojars

21:14 TimMc: amalloy: done

21:18 itamar: what do most people use for networking with clojure? aleph?

21:18 amalloy: TimMc: 0.3.2 on clojars

21:19 TimMc: yay

21:21 amalloy: also, "a juxty thing because heck yes". i'm concerned you may be conning me into marrying you

21:21 TimMc: haha

21:35 technomancy: itamar: "networking" is a bit too vague to be useful

21:37 rien: Raynes: it's been a few weeks, no reply whatsoever (re nixeagle's live emacs buffer)

21:40 devn: to anyone out there reading: start a clojure meetup group in your area if one does not exist. there is a coupon for clojure meetup group organizers provided by meetup.com. I started this group roughly 1 year ago and the people I've found have been incredible

21:41 skelternet: I wonder if there is one in Austin. I know there was a fp group at one point

21:41 devn: we have haskellites, scalaphiles, clojurians, schemers, lispers, and more -- a great group of people to meet and talk to.

21:41 amalloy: a coupon? does meetup cost money?

21:42 itamar: technomancy: custom TCP server, say

21:42 devn: amalloy: it does -- i dont even remember the specifics of what is and isnt included. all i remember is they offered a discount to clojure organizers. i will give them money even if that only means a free stick of gum or something

21:43 just for the support for the clojure community

21:43 speaking of which -- i keep looking at clojure open source projects. how do i pay for them? :)

21:44 "needs moar donation buttonz"

21:45 TimMc: bitcoin ^_^

21:53 The tricky bit is dividing the loot.

21:53 * devn shrugs

21:53 * alexbaranosky gets all of it ??? 8-(

21:53 devn: I'll give it to the EFF as a donation from the clojure community or something. i dont care who gets it, just want to share my appreciation with dollar bills yall.

22:38 TimMc: amalloy: clojopts doesn't handle --nil=foo very well. :-)

22:38 amalloy: interesting

22:39 i mean, it doesn't really matter of course, but i wonder why

22:40 TimMc: amalloy: Easy, you're using a macro to pick up symbols.

22:40 Just like that conversation the other day.

22:40 amalloy: oh, you mean if you specify nil in the clojure spec-thingy

22:41 i see

22:41 TimMc: yep

22:41 amalloy: i was trying to find where nil would upset the parsing code, not the spec code

22:42 TimMc: a more interesting point that this implies is that you can't parse options like -1, the way head/tail do

22:42 TimMc: Ah.

22:42 amalloy: but i don't think getopt can either; head must roll its own

22:43 TimMc: Can't it?

22:43 I have clojopts open, I'll try modifying it.

22:43 amalloy: TimMc: to be clear, i'm talking about 1 as an option "name" (key), not value

22:44 TimMc: yep

22:44 ermnik: how might one add a class to an element in hiccup? Like ckeditor to the text-area element?

22:44 amalloy: [:foo.editor]

22:46 ermnik: from the docs: (text-area name value)

22:46 where would [:foo.editor] go?

22:47 Or would i be using a more generic element function in hiccup?

22:47 TimMc: amalloy: You and your use of ` outside of macros...

22:47 amalloy: i think you should read the docstring, or possibly the source, for text-area

22:48 TimMc: looking back over `man getopt`, i still don't see a thing like "call this function if you see an unrecognized argname"

22:48 TimMc: which one are you thinking of? desugar-spec or something?

22:48 TimMc: yeah

22:49 amalloy: well, that's really in a macro anyway

22:49 TimMc: I mean, it reads nicely, but ` still says to me "Oh shit, here comes an s^w^w a macro!"

22:49 amalloy: hahaha

22:50 it's just a helper function; not really the same thing as using `(~@x 0) as a shorthand for (concat x [0])

22:50 TimMc: Oh, it's called from a macro, I see.

22:50 adiabatic: what would "an s" be? sexpr?

22:50 ermnik: amalloy: I took your advice... so text-area just returns a vector, second element of which is a map of attributes. should I assoc a :class in there?

22:50 amalloy: $google apostrophe oh shit here comes an s

22:50 lazybot: [Oh shit, here comes an 's'. - Reddit] http://www.reddit.com/comments/65hz7/the_apostrophe_key_does_not_mean_holy_shit_here

22:51 TimMc: adiabatic: http://www.reddit.com/comments/65hz7/the_apostrophe_key_does_not_mean_holy_shit_here

22:51 bah, slowternets

22:51 adiabatic: ah, thanks

22:51 TimMc: Bing had no idea what I was talking about.

22:52 amalloy: i'm glad lazybot got it right

22:52 TimMc: I think my trial of that particular search engine is over.

22:52 amalloy: ermnik: i would just take the very simple code text-area contains and replicate it yourself, since it doesn't seem to have a feature for adding anything but an id

22:56 TimMc: amalloy: -1 works fine. desugar calls str on the names, but nil goes to ""

22:56 amalloy: TimMc: but does getopt actually parse it?

22:56 TimMc: amalloy: Yeah, ["-1" "foo"] => {:1 "foo"}

22:57 amalloy: that's pretty amazing

22:57 TimMc: --1 didn't work, of course -- then I fixed my code.

22:59 I think I'll bundle that in with some doc fixes.

23:09 technomancy: devn: what does meetup get you over a static site?

23:21 alexbaranosky: devn: I'd also like to know what meetup gets you

23:27 rien: technomancy: findability

23:28 alexbaranosky: so I'm looking into how to add mocking of java methods to Midje -- anyone have any opinions on a good way to approach it?

23:30 I envisioned it looking something like: `(fact (doubler ..x..) => "AA" (provided (.toString Object ..x..) => "A") )`

23:31 but mostly I'm lost :)

Logging service provided by n01se.net