#clojure log - Dec 28 2010

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

0:00 amalloy: &(apply concat ((juxt take (comp rest drop)) 2 [1 2 3 4]))

0:00 sexpbot: ⟹ (1 2 4)

0:01 Gigaroby: look a bit complicated just to remove a element

0:01 lol

0:01 amalloy: Gigaroby: or you could do it more explicitly, like ##(let [x [1 2 3 4]] (concat (take 2 x) (drop 3 x)))

0:01 sexpbot: ⟹ (1 2 4)

0:01 Gigaroby: got it

0:01 Leonidas: I have a list of regexp that I want to chain on a string (using re-sub), what can I use? -> and reduce don't work for me in this case...

0:01 Gigaroby: thanks

0:02 Leonidas: (re-sub second "" (re-sub first "" input-string)) etc.

0:02 amalloy: hippiehunter: -> is a form-restructuring macro like doto. for example: ##(-> {:a {:b 2}} :a :b)

0:02 sexpbot: ⟹ 2

0:03 hippiehunter: does it have a non symbol name?

0:03 amalloy: ,(macroexpand '(-> {:a {:b 2}} :a :b))

0:03 clojurebot: (:b (clojure.core/-> {:a {:b 2}} :a))

0:03 hippiehunter: -> doesnt google well

0:03 amalloy: hippiehunter: i don't think so. maybe one in common lisp? i'll find you the clojure ref

0:03 Leonidas: hippiehunter: "theaded first", there is a nice intorduction in full disclojure.

0:03 "thread first" I mean, sorry.

0:04 amalloy: http://blog.fogus.me/2009/09/04/understanding-the-clojure-macro/

0:04 hippiehunter: perfect, thank you

0:05 amalloy: Leonidas: why doesn't reduce work? (reduce (fn [s [match replace]] (re-sub match replace s)) input-string [[first ""] [second ""]])

0:07 Leonidas: amalloy: the reduce docs says that when coll contains only one element it will return coll without applying f to it

0:08 amalloy: Leonidas: unless you supply it with an initial value, which i do with input-string

0:08 &(reduce + 1 [4])

0:08 sexpbot: ⟹ 5

0:09 Leonidas: ah

0:09 amalloy: the docs do say that, but they're rather poorly written in that regard

0:11 you're meant to read it as "(If val is not supplied...If coll has only 1 item)...If val is supplied..."

0:13 Leonidas: amalloy: you're right, it works just fine, I added it in my code and it passes the tests :)

0:14 rata_: Gigaroby: you could use split-at also... (let [[a b] (split-at 2 [1 2 3 4])] (concat a (rest b)))

0:14 Leonidas: thanks!

0:15 amalloy: Leonidas: great! hippiehunter, is -> starting to make sense?

0:15 Gigaroby: rata_, thanks, I alredy used the other one is shorter

0:15 rata_, (fn [idx lst] (concat (take idx lst) (drop (inc idx) lst)))

0:16 rata_: good

0:16 Gigaroby: rata_, is just strange that someonle else didn't alredy implement it

0:16 rata_, I tought was common enaugh

0:17 amalloy: Gigaroby: it's pretty rare that you need to do it, with clojure's functional/lazy idioms. what do you need it for, out of curiosity?

0:17 Gigaroby: amalloy, well is a bit of a long explanation

0:17 amalloy, I have a list

0:18 rata_: Gigaroby: I haven't need it... as amalloy said is not common at all

0:18 Gigaroby: amalloy, containing a variable number of maps such as {:board [ ... ] :current 0}

0:19 amalloy, I have to extract a value from one of those boards and see if there is a board with the same number in the same position

0:19 amalloy, therefore I need to delete the board itself to check the others

0:20 amalloy: Gigaroby: but you don't need to delete it by index. you could, eg, (remove #{the-map-to-remove} all-the-maps)

0:20 Gigaroby: amalloy, ah

0:20 amalloy, didn't think about it lol

0:21 amalloy, waith tho because 2 of them may contain the same board and number

0:23 amalloy: you might have two exactly-identical maps, and you want to remove only one of them?

0:24 Gigaroby: amalloy, well in worse case I can have all the maps identical

0:24 amalloy, probably they will not point to the same reference but they will be the same at =

0:26 amalloy: Gigaroby: removing by index is probably not *that* sinful then, i guess, though you could do without it if you wanted to

0:27 tomoj: how many boards?

0:27 Gigaroby: tomoj, variable number

0:27 tomoj, suppose not over 20

0:27 tomoj: ok

0:27 Gigaroby: tomoj, and not less then 5 or 6

0:28 tomoj: I was thinking that'd be slow, but with those numbers it won't matter I bet

0:28 Gigaroby: tomoj, no the bottle neck is not there for sure

0:28 amalloy: tomoj: remove/filter won't be any faster, will they?

0:28 rata_: Gigaroby: what happens when there's a board with the same number in the same position?

0:29 Gigaroby: all right I'll explain the whole problem than

0:29 I'm trying to do a strange kind of 8 queens problem

0:30 by taking 8 single problems and trying to make them fit one in the other

0:30 tomoj: amalloy: what would be faster would be not keeping this in a list, I think..

0:30 amalloy: tomoj: for sure

0:30 Gigaroby: all the fuss is about checking that a queen on a single board will not collide with one in another board

0:31 so nothing happend when 2 maps are equals simply the check returns false

0:32 rata_: Gigaroby: the question is, what do you do when a queen collide with one in another board? do you delete one of those boards?

0:33 Gigaroby: rata_, no simply the check returns false

0:33 rata_: ok

0:33 Gigaroby: rata_, I delete one board into the check

0:33 rata_, to make sure that some will not take the board itself as argument

0:35 rata_, I'll show you the source as short as I finish that function

0:35 rata_: ok

0:42 Gigaroby: rata_, you were right I thought about it and I did a mess for nothing

0:43 was just a matter of check if the count was greater then 1

0:43 rata_: =)

0:43 Gigaroby: rata_, afk for couple of hours or so

0:43 rata_: glad I've been helpful

0:45 hippiehunter: amalloy: yes that made -> much more clear

1:08 amalloy: hippiehunter: it occurs to me, you could make this "prettier" with (defmacro set-member! [inst field val] `(set! (. ~inst ~field) ~val)))

1:25 rata_: why, if (map reverse lst) returns (([1 2] [3 4])), when I do (into {} (map reverse lst)) it returns {1 2, 3 4} instead of {[1 2] [3 4]}?

1:25 but when I do (into {} (map (comp vec reverse) lst) it works

1:59 amalloy: &(into {} [[1 2]])

1:59 sexpbot: ⟹ {1 2}

2:00 amalloy: &(into {} ['(1 2)])

2:00 sexpbot: java.lang.ClassCastException: java.lang.Integer cannot be cast to java.util.Map$Entry

2:00 amalloy: rata_: vectors can be coerced into map entries, but lazyseqs can't

2:01 rata_: oh ok... didn't know that

2:01 thanks =)

2:01 strange anyway

2:01 amalloy: &(supers (class (first {:a 1})))

2:01 sexpbot: ⟹ #{clojure.lang.Sequential clojure.lang.IPersistentCollection clojure.lang.APersistentVector clojure.lang.ILookup java.lang.Object clojure.lang.IFn java.lang.Runnable java.io.Serializable clojure.lang.AMapEntry java.util.List java.lang.Iterable clojure.lang.IPersisten... http://gist.github.com/756986

2:01 amalloy: &(class (first {:a 1}))

2:01 sexpbot: ⟹ clojure.lang.MapEntry

2:15 rata_: good night

2:18 joshua__: I just realized something really cool.

2:19 It felt natural for me for the first time to choose Clojure instead of Python for my last little script.

2:19 yeay

2:37 amalloy: inspired by hippiehunter's recent question: is there some way to combine the -> family of macros to get a macro M, such that (M a (b c d e...)) yields (b c a d e...); that is, splices into the third position instead of second or last? i realize this is not useful, nor difficult to do by a plain defmacro, but it seems to me there must be some way to do it with ->

2:43 notsonerdysunny: can members of a record be type hinted? will this enhance performance or improve storage efficiency?

2:55 amalloy: notsonerdysunny: if it's possible (i'm not sure), it won't improve storage efficiency, and won't enhance performance any more than you could by type-hinting the members when you access them

2:58 notsonerdysunny: (doc defrecord) says the fields can have type hints

3:00 zvrba: hmm. i was intrigued that clojuer's vector implementation has log_32(n) access time

3:00 how are they implemented?

3:00 amalloy: i settled down with emacs+slime :-)

3:00 getting leiningen to work under windows wasn't too painful either

3:00 amalloy: $google higher order blog implement ipersistentvector

3:00 sexpbot: First out of 11 results is: Ruminations of a Programmer: Random thoughts on Clojure Protocols

3:00 http://debasishg.blogspot.com/2010/08/random-thoughts-on-clojure-protocols.html

3:01 amalloy: bah

3:01 zvrba: http://blog.higher-order.net/2009/02/01/understanding-clojures-persistentvector-implementation/

3:01 this one? :)

3:01 amalloy: that's the one!

3:01 zvrba: interestingly, that WAS the first result in my google search

3:03 amalloy: zvrba: google corrected you to persistentvector; sexpbot's using the api, which doesn't do that

3:05 zvrba: clojure's persistent data structures are amazing things, and i'm glad i don't have to deal with them. but if you're interested in working on an effort to implement another useful persistent data structure, check out https://github.com/Chouser/finger-tree/commits/master

3:08 zvrba: uh, no. :)

3:09 * joshua__ loves scraping the web. Finds joy in running a script (that takes hours to finish (don't want to dos someone (nested parentheses))) which accomplishes a task that would takes hours to do by hand. Yeay, programming.

3:09 notsonerdysunny: thanks amalloy

3:10 zvrba: amalloy: anyway, starting to read on finger trees now

3:10 i got a bit intrigued :-)

3:10 notsonerdysunny: amalloy: you don't think it would improve storage efficiency.. ?

3:10 double would require more storage than a int ..right ..

3:11 zvrba: amalloy: but why did he choose int? using long would make access time log_64(n) ?

3:11 amalloy: notsonerdysunny: an Object reference takes up exactly as much space as a LinkedList reference

3:12 notsonerdysunny: you might save a little space if you wanted to store primitives, but you'll suffer performance penalties for the boxing and unboxing

3:13 zvrba: it's a trade-off. with a larger branching factor, there's less room for pointer-sharing between "related" vectors

3:13 zvrba: uh, that finger_tree.clj is way above my clojure-fu atm. :-)

3:13 amalloy: zvrba: yeah, mine too. chouser is something else

3:14 notsonerdysunny: amalloy: I am storing primitives only

3:14 they are all doubles.

3:14 amalloy: notsonerdysunny: so...why not just use (make-array Double/TYPE 10)?

3:15 notsonerdysunny: yea true but .. I like being able to access with the automatic getters ..

3:15 for example I could have (defrecord point [x y]) and I can access it via (:x somepoint)

3:16 amalloy: notsonerdysunny: so type-hint your defrecord, then. you'll save four bytes for each double, i guess

3:26 notsonerdysunny: amalloy: is there some way to say that this will contain an array of 3-doubles? i.e. type hint that it will contain an array of 3 doubles..

3:28 amalloy: notsonerdysunny: afaict protocols only allow type-hinting of primitives, and double[] is an Object

3:29 notsonerdysunny: er, records, not protocls

3:29 if you wanted to type-hint a double[] outside of a record, the tag would be ^"[D"

3:29 notsonerdysunny: actually I was able to type hint it with another record type...

3:30 amalloy: where do you get these type-hint strings.. do you have a reference?

3:30 amalloy: &(class (make-array Double/Type 0))

3:30 sexpbot: java.lang.Exception: Unable to find static field: Type in class java.lang.Double

3:30 amalloy: &(class (make-array Double/TYPE 0))

3:30 sexpbot: ⟹ [D

3:31 amalloy: notsonerdysunny: ^"Foo" hints "the java class Foo", and the class string for double[] is [D

3:31 notsonerdysunny: but all this is madness. you don't gain anything unless you're type-hinting primitives directly; if you hint it as some other defrecord, it just stores it as an Object anyway, because the references are the same size

3:33 same goes for arrays of primitives

3:33 notsonerdysunny: oh .. ic

3:35 amalloy: notsonerdysunny: https://gist.github.com/757058

3:38 notsonerdysunny: amalloy ah ic .. thanks for the gist .. I need sitback and see how I have to do what I am doing.. :)

3:39 I guess the type-hinting with other records/classes will also be taken into account in the future releases of clojure ...

3:42 amalloy: notsonerdysunny: maybe. it's probably a good feature, but i suspect the core team has a lot of higher-priority stuff to do, and there may be reasons not obvious to either of us that it's a bad feature anyway

3:48 notsonerdysunny: I defined a an array of some-user-defined record .. and tried to assign a different record .. so it is trying to check if the type of array and that of assigned objects match .. ? can I disable this.. ? just out of curiosity

3:48 *forgot to say that the repl didn't allow this .. *

3:50 amalloy: notsonerdysunny: yes; no. java's type system is strict

3:54 _ato: notsonerdysunny: specify the type as "Object" when you create the array and you can put anything in it. Like: (into-array Object [1 2 3 4])

3:54 notsonerdysunny: _ato .. Yeah I tried that .. thanks

3:57 suppose I have an array of size 10x10 .. is it faster to zero out all the elements of the array or just create another array?

3:59 amalloy: notsonerdysunny: try it and see

4:05 notsonerdysunny: amalloy: using the aset macros from http://clj-me.cgrand.net/2009/10/15/multidim-arrays/ both are about the same speed ..

4:05 I guess it is just easier to create a new array then ...

4:08 a naive implementation would be about a 20 times slower when I reset all the values to zero ..

5:48 ngw: is there something similar to http://www.liquidmarkup.org/ for clojure ?

5:49 what I need is a simple lib to use a DSL (something simple, basic looping and mostly functions that return strings, very limited) inside HTML templates

5:50 considering how good clojure is at building DSLs ...

5:50 lenw: ngw : like velocity ?

5:53 ngw: actually liquid is much more limited, and that is very good :p

5:53 velocity seems more similar to erb/PHP

5:55 fleet is the best I found until now

8:29 * Lajla will use his boundless masculinity to ejaculate over the greater part of this channel.

8:42 * ejackson feels consoled that he is certainly in the set of lesser members of this channel.

8:42 Raynes: I'm happy that that little outburst happened early on a Tuesday morning.

8:43 * cemerick wouldn't mourn usage of the banstick in various venues.

8:44 Raynes: cemerick: Nobody has ever used the banstick here. Unfortunately, not nearly enough people have a banstick.

8:45 cemerick: Raynes: I think it's been used once, a long time ago.

8:45 late 2008, maybe?

8:45 Raynes: Before my time.

8:45 cemerick: But yes, I agree. There should be an op in here at all times IMO.

8:45 Raynes: Wait until Clojure is *really* popular.

8:46 There will be no choice in the matter.

8:46 ejackson: sigh, indeed.

8:46 Raynes: Too bad chouser isn't omnipresent.

8:46 ejackson: so I learnt this am that the java client for Redis is called jedis.

8:46 I didn't notice the pun until I googled it

8:47 Raynes: I wouldn't have noticed the pun.

8:47 ejackson: also before you time ? :P

8:47 Raynes: I think I pronounce Redis incorrectly.

8:47 No, I get 'jedi', but I don't enunciate the 'i' in Redis.

8:48 It wouldn't have popped out at me.

8:48 ejackson: it didn't me either

8:50 it stresses me out how easy these new dbs are

8:50 to get clojure working with jedis was < 5 mins of work

8:50 something terrible must be hiding under the rug here

9:08 LauJensen: cemerick: Hows responsible for moderating #clojure?

9:09 cemerick: LauJensen: only Rich and chouser have op IIRC

9:09 LauJensen: k

9:13 bendlas: Can somebody tell me what's up with that snippet: http://pastebin.com/AgNVKFhW

9:14 and what happens when you do (= (Vec2. 5 6) (Vec2. 5 6))

9:59 Why is instance? _broken_ in deftype method bodies?

10:13 Please guys, take a look at http://pastebin.com/cTdUCKfp

10:19 cemerick: bendlas: it's a known issue, related to a stub class being generated prior to the "real" deftype class being generated (the former being required for hinting).

10:19 bendlas: I don't see an issue for it in jira yet; feel free to submit one with your testcase.

10:20 bendlas: ok, thanks

10:21 isn't issue tracking done at assembla?

10:21 cemerick: bendlas: no: http://www.assembla.com/wiki/show/clojure

10:24 bendlas: oh, it's fixed in current 1.3 snapshot

10:37 drewolson: anyone have experience with aleph? on large requests the body is a channel and i'm having trouble turning this channel into a string.

11:02 Appl6: Hello, I'm just getting started with Clojure. I'd like to use the REPL to import a public Java class file (part of the default package) in the current directory (Instruction.class). I tried several things but only (import '(Instruction)) didn't produce an error (it returned nil), but:

11:02 user=> (Instruction. nil 100)

11:02 java.lang.IllegalArgumentException: Unable to resolve classname: Instruction (NO_SOURCE_FILE:18)

11:05 mrBliss: Appl6: make sure it's on the class path, the proper syntax is: (import '(packagename Class))

11:06 Appl6: I advise you to look into leiningen or cake (pick one)

11:07 Appl6: mrBliss: It is not in a package; it's in the default package. What would I use then for "packagename"?

11:11 mrBliss: Appl6: I'm not sure, but I think it's not possible

11:12 Appl6: mrBliss: OK, thank you.

11:19 cemerick: mrBliss: you can also do (import 'Foo), which will work for classes in the default package.

11:19 mrBliss: cemerick: too bad App16 already left :-)

11:20 krl: is there any way to swap atoms from within calls to map?

11:32 LauJensen: krl: yes, but it sounds unidiomatic. If you want sideeffects, try doseq

11:47 pdk: ,(let [triangle (for [i (range 5)] (range i))] (for [row (count triangle)] (get triangle row)))

11:47 clojurebot: java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Integer

11:48 pdk: ,(let [triangle (for [i (range 5)] (range i))] (for [row (range (count triangle))] (get triangle row)))

11:48 clojurebot: (nil nil nil nil nil)

11:48 pdk: is this a known bug with get

11:49 ,(let [triangle (for [i (range 5)] (range i))] (for [row (range (count triangle))] (nth triangle row)))

11:49 clojurebot: (() (0) (0 1) (0 1 2) (0 1 2 3))

11:49 pdk: compare

11:50 danlarkin: ,(type (for [i (range 5)] (range i)))

11:50 clojurebot: clojure.lang.LazySeq

11:50 danlarkin: can't get on a LazySeq

11:50 pdk: yea that seemed to explain part of it

11:51 hm do you just call seq on a lazy sequence to force evaluation

11:51 danlarkin: if you want to use get you need to turn it into an associative data type

11:51 like a vector

11:53 pdk: so easiest way would just be to vec it

11:53 vector rather

11:54 danlarkin: it seems like a pretty odd example, does your real use case match what your example does?

11:54 pdk: what i'm trying to do is write a function that takes in a 2d matrix say as a vector

11:55 and if it's jagged or has more rows than columns/vice versa it returns a version padded with empty space until it has a square

11:55 so say giving it [[1 2 3]] would return something like [[1 2 3] [nil nil nil] [nil nil nil]]

11:56 worked on the other usage cases i gave it so i'm starting to figure i can just replace get with nth and add a not-found so it doesn't crash

11:57 success

11:57 calls for a group hug

11:58 ok

11:58 maybe not success when it has more columns than rows

12:08 Guest10433: I am invoking my program from the command line like so: "java -cp myjar.jar clojure.main -i @/some/package/myfile.clj" but I can't figure out how to pass command line variables. Does anyone know how to do this?

12:10 tonyl: Guest10433: just pass them after your clj file

12:10 Guest10433: tonyl: when i do that i get an error in "main" that it can't find the file

12:11 tonyl: what file?

12:11 Guest10433: tonyl: for example, if i put "somearg" at the end, i get filenotfoundexception in main for file "somearg"

12:12 tonyl: it seems that is something in the code of main that is not working right

12:12 can't tell much without a snippet

12:12 Guest10433: ok sure, let me post it up and i'll brb

12:17 tonyl: http://pastebin.com/YgS1N97N

12:18 if I leave the "Jackson" off, it runs but doesn't print any name. if I put "Jackson" on the line, I get FileNotFoundException in main for file Jackson

12:19 this is on Windows so the 0th arg isn't the program name but the first argument

12:21 tonyl: yeah, i tried it and mine only prints Hello, *command-line-args* is nil for some reason

12:22 let me see

12:22 bendlas: ,(if (Boolean. "false") "It's true" "It's false")

12:22 clojurebot: "It's true"

12:22 bendlas: somebody know if that is worked on?

12:22 tonyl: only false and nil are boolean false in clojure

12:23 bendlas: no, look

12:23 Guest10433: tonyl: are you saying that you don't get the FileNotFound if you DO put some additional arg on there?

12:23 tonyl: Guest10433, i don't get any errors

12:23 bendlas: ,(if (Boolean/FALSE) "It's true" "It's false")

12:23 clojurebot: "It's false"

12:24 bendlas: Boolean/FALSE is also boxed

12:24 Guest10433: tonyl: that's odd. i'm using 1.2 here. you?

12:24 rhickey: ,(identical? (Boolean. false) Boolean/FALSE)

12:24 clojurebot: false

12:24 tonyl: I am using 1.2 too

12:24 gju_: can i somehow create a record without having to initialize every single field in that record?

12:25 rhickey: ,(identical? (Boolean. "false") Boolean/FALSE)

12:25 clojurebot: false

12:25 Guest10433: tonyl: on windows? i don't understand how we get different behavior

12:25 tonyl: not on windows

12:26 Guest10433: try putting (println *command-line-args*) before (hi (nth *command-line-args* 0)) see what do you get

12:27 rhickey: ,(identical? false Boolean/FALSE)

12:27 clojurebot: true

12:28 bendlas: rhickey: so you're arguing that exactly one instance of Boolean (namely Boolean/FALSE) should be false in clojure?

12:28 rhickey: bendlas: I'm not arguing, that's how it is

12:29 bendlas: indeed

12:29 Guest10433: tonyl: hmmm if i pass one arg, *command-line-args* prints as nil, if i pass 2 args, i see the second one

12:29 tonyl: i think this is broken on windows

12:29 bendlas: what about using ,(.equals Boolean/FALSE (Boolean. false)) instead?

12:30 rhickey: bendlas: where?

12:30 tonyl: Guest10433: u are better off then me, I passed 0 or 10 args and it is still is nil

12:31 bendlas: rhickey: wherever conditional forms are currently using (identical? Boolean/FALSE x)

12:31 rhickey: bendlas: no way, for perf reasons

12:32 tonyl: Guest10433: try running it without the -i just clojure.main file.clj

12:33 Guest10433: tonyl: doh! why didn't i try that? that is working. it's ok for you too?

12:33 bendlas: rhickey: same thing for an implicit (boolean x), I suppose?

12:34 ,(if (boolean (Boolean. "false")) "It's true" "It's false")

12:34 clojurebot: "It's false"

12:34 tonyl: no, but that might be because i use a bash script to call up that command, there might be something wrong in my script

12:35 Guest10433: when i read the doc at clojure.org/repl_and_main i thought i needed the -i when loading a file

12:35 tonyl: yes, but anything after -i is treated as a file to load

12:35 even the args

12:36 Guest10433: tonyl: ok, got it. but if i do specify a file, it doesn't leave me at a repl, which is what i want in this case. anyway thanks!

12:36 with no -i i mean

12:36 tonyl: yeah i understand the nead

12:37 *need

12:37 you might want to try out cake, lein, labrepl, or cljr or those scripts/programs tested to work better and simpler

12:38 I know i am thinking about using them now

12:39 Guest10433: tonyl: better and simpler than what? basically i just built an uberjar and now i want to distribute it to run on some system where i can only count on java being present. all i need to know is the invocation syntax to kick it off via a script

12:40 tonyl: everything works perfectly without the "-i" in there ;) i'll just write a simple wrapper script for the user so they don't have to type in that java command line

12:41 tonyl: yeah, that is my mentality "if it works, fine. tune it later when you have time"

12:42 Guest10433: tonyl: hmm not sure i'm following since i don't see anything further to tune. are you suggesting a better way to run standalone clojure programs?

12:43 tonyl: I am just saying there are other ways with those tools and from what i heard simpler too, but nothing from my experience

12:43 bendlas: rhickey: is there really no way/plan to fix this? I mean it's really one of my basic assumptions for a PL, that (if x ...) means the same as (if (boolean x) ...)

12:44 Guest10433: ok, sure. thanks for your input. it got me out of that rut (not thinking about removing -i)

12:46 rhickey: bendlas: it's not broken. What is broken is that Java creates distinct Boolean objects when they have perfectly fine canonical ones. It is not going to change

12:47 Raynes: rhickey: Long time no see. Hope you had a merry Christmas. :>

12:47 bendlas: rhickey: ack @ java brokenness

12:47 rhickey: Raynes: thanks, you too

12:54 bendlas: if the construction is up to you, use valueOf:

12:54 (identical? (Boolean/valueOf "false") Boolean/FALSE)

12:54 ,(identical? (Boolean/valueOf "false") Boolean/FALSE)

12:54 clojurebot: true

12:55 rhickey: bendlas: if not, chastise the producer for not using valueOf

12:55 those Boolean ctors are evil

12:56 bendlas: rhickey: will do, thanks for explaining

12:59 rhickey: yes, Boolean ctors should be private

13:12 zvrba: how can i define a local function in clojure? like labels in CL?

13:12 let + fn ?

13:14 yes, it works.

13:15 mrBliss: zvrba: letfn if you need to refer to a local function (= labels)

13:15 bendlas: ,(letfn [(x [a] (inc a))] (x 5))

13:15 clojurebot: 6

13:17 amalloy: personally i use let+fn so that i don't have to remember the syntax for letfn - there's no obvious gain from using letfn unless you need mutual recursion

13:31 Raynes: ivey: -> #sexpbot if you're around

14:27 gju_: when i define a record and want to fill it with data... what's the best way to do it?

14:28 without always re-defining something.

14:30 tonyl: gfu_ a fn that has a default map of the values maybe?

15:45 jcromartie: I'm totally stumped as to how to handle nil/null in clojure.contrib.sql

15:45 I mean reading queries is easy

15:45 but matching or updating when a column is null

15:47 in fact, I've found that text type columns and nil values totally throw c.c.sql for a loop

15:47 fv: hi

15:48 I've got a simple issue, but neither google nor searching archive helped

15:48 (ns clojurefirst

15:48 (defn print-string [x]

15:48 (1)

15:48 )

15:48 )

15:48 Caused by: java.lang.IllegalArgumentException: Parameter declaration quote should be a vector

15:49 amalloy: fv: (ns blah) (defn foo [x] 1)

15:49 fv: example runs perfectly in REPL, and I just have no idea why would it be something wrong with it

15:49 thank you

15:50 works

15:50 jcromartie: tjat

15:50 that's not how you use ns

16:20 sarcher|work: Just got a copy of Programming Clojure. Any advice for a Java guy getting started with Clojure?

16:20 I took Lisp in college and at some point it all made sense, but I haven't looked at a lisp since then.

16:21 auser: <~ from an erlang guy, I'd say don't think about objects, think in terms of functions

16:21 ex-java guy too

16:21 but from a long time ago

16:21 heh

16:21 sarcher|work: yeah the whole idea of functional programming makes sense to me.

16:22 auser: oh I'd also work with clojure like it's an entirely new language

16:22 the java interop took me a little while to understand (I'm still learning about it, in fact)

16:22 sarcher|work: I just don't have any experience building stuff using that paradigm

16:22 auser: write something simple then

16:23 qbg: Doing some Project Euler problems may be useful.

16:23 auser: good idea qbg

16:23 amalloy: sarcher|work: if you have a handle on the "idea" of functional programming, lazy sequences are an important thing to get the hang of

16:24 auser: oh yeah, that's really true amalloy

16:24 sarcher|work: yeah I'm not familiar with that.

16:24 qbg: Code reviews on irc could be useful also.

16:24 amalloy: and yeah, project euler is a good thing to try. you can also look at Rosetta Code; it's a wiki so some of the code is pretty shoddy or poorly-documented, but it offers a great side-by-side comparison of clojure to other languages

16:25 sarcher|work: cool, it sounds like I just need to start building something and then see where it leads me :)

16:34 amalloy: sarcher|work: you can also look at some open-source clojure programs on github

16:39 sarcher|work: thanks amalloy

16:51 Leonidas: I have something like (def u {"Leonidas" 3}) (def d {"Leonidas" 2}) and run (merge-with (fn [u d] {:upvotes u :downvotes d}) u d) This only works when both u and d have a Leonidas-key. Is there a way to transform it, even when one of u or d is empty?

16:53 tonyl: Leonidas: instead of merging can't you just create the new map (def newmap {:up u :down d})

16:56 mabes: I have some namespaces that need to be AOT, so I have configured my project.clj (lein) to compile them.. however, I keep running into state class files when testing. Is there a way to have the compile task always run before "lein test"?

16:56 er.. state -> stale class files

16:56 Leonidas: tonyl: yeah but I need to transform both u and d dicts and so far I don't even know how

16:57 amalloy: Leonidas: (into {} (for [user (set [(keys u) (keys d)])] {:u (u user), :d (d user)})) looks like a good start to me?

16:59 Leonidas: (fmap (fn [k v] [k {:downvotes v}]) d) does not work that well :/

17:00 amalloy: (into {} (for [user (set (mapcat keys [u d]))] {user {:u (u user) :d (d user)}}))

17:00 Leonidas: amalloy: returns {:u nil :d nil}

17:00 amalloy: Leonidas: yes, i was sorta thinking out loud. the second one will actually work

17:01 Leonidas: amalloy: yep, thank you. Will need a bit of time to tinker with it to understand.

17:02 amalloy: Leonidas: take the keys from both maps, and iterate over the distinct keys. for each key, look up that key in each map and create an entry in the new map with appropriate :u and :d entries

17:07 Leonidas: amalloy: thanks, I think I get it now. I modified it slightly to set 0 instead of nil for unknown keys and it works perfectly

17:07 amalloy: sure

17:17 sarcher|work: what's the best way to add up a list of numbers in clojure?

17:17 Derander: sarcher|work: probably (reduce + list)

17:17 amalloy: sarcher|work: or #(apply + [1 2 3])

17:17 qbg: Or (apply + coll)

17:18 sarcher|work: I was trying apply + coll

17:18 and having trouble

17:18 amalloy: sorry, no # (apply + [1 2 3])

17:18 Derander: yeah, apply is probably faster

17:18 sarcher|work: wow the lack of parens was what was getting me

17:18 amalloy: lol, it's getting less readable by the second. what goes wrong when you try apply?

17:18 qbg: + will use reduce anyways...

17:18 sarcher|work: i thought you had to put + in parens

17:18 with a % or something

17:19 Derander: sarcher|work: (apply #(+) [1 2 3]) ?

17:19 no

17:19 sarcher|work: i guess since you are passing it as an argument that makes sense that it doesn't need parenthesis though.

17:19 Derander: #() is the anonymous function syntax

17:21 sarcher|work: what do y'all think about this - http://pastebin.com/xNNf3j1g

17:21 qbg: Prefer names such as my-add and divides?

17:22 sarcher|work: Add all the natural numbers below one thousand that are multiples of 3 or 5.

17:22 yeah sorry for the names

17:22 qbg: isDivisibleBy is too specific

17:22 Leonidas: can i destructure a map somehow?

17:23 qbg: ,(let [{:keys [a b c]} {:a 1 :b 2 :c 3}] [a b c])

17:23 Leonidas: (for [[k {:upvotes u}] v] k) where v is a map

17:23 clojurebot: [1 2 3]

17:23 amalloy: Leonidas: ##(let [{a :a} {:b 1 :a 1}] a)

17:23 sexpbot: ⟹ 1

17:23 qbg: sarcher|work: The or should be in filter's fn

17:24 sarcher|work: thanks qbg

17:24 amalloy: qbg, sarcher|work: i'd do it differently: (defn divides-any? [x divisors] ...)

17:25 Leonidas: amalloy: ah, I get it. I got the syntax wrong but the general approach was good already :)

17:25 amalloy: sarcher|work: so i think qbg and i, combined, are saying divides? should take either one factor or N, but not specifically two

17:25 qbg: amalloy: or (defn divides-any? [x & divisors] ...)

17:26 sarcher|work: yeah that makes sense

17:26 amalloy: qbg: yes, but i didn't want to get into & yet

17:27 qbg: The (+ * %) in the apply part looks wrong

17:28 You just want +

17:31 Berengal: Is it possible to force destructuring to match exactly?

17:33 qbg: Berengal: as in thrown an exception if the lengths don't match?

17:33 amalloy: Berengal: it's not clear what you mean. perhaps an example of what you wish worked?

17:33 Berengal: qbg: Yes

17:33 qbg: Don't think so

17:33 Berengal: amalloy: I'd ultimately like something like Haskell's case

17:34 With multiple paths depending on the shape of the value

17:34 qbg: There are pattern matching libraries for Clojure

17:34 Berengal: Ah, neat

17:37 sarcher|work: what are the prefered naming conventions for functions in clojure?

17:37 divides-any

17:37 gfrlog: that sounds like a predicate

17:37 which end in question marks

17:37 sarcher|work: dash separated stuff?

17:38 gfrlog: yes

17:38 sarcher|work: usually lowercase?

17:38 gfrlog: yes

17:38 sarcher|work: so does the ? have any syntactic meaining or is it just a convention?

17:38 gfrlog: convention

17:38 sarcher|work: ah cool good to know

17:38 gfrlog: used when a function always returns a boolean

17:39 joshua__: Hmm. Having trouble finding someone that allows the selling of small files without a monthly charge.

17:41 gfrlog: Does there exist a clojure templating language that functions like ERB? I'm assuming clojure.template is kind of a different thing

17:43 ivey: gfrlog: https://github.com/mmcgrana/clj-html

17:44 gfrlog: well I want to use it for latex

17:44 so I assume it would have to be simple insertion templating like ERB

17:52 I can probably write my own in 3 lines with gsub

18:12 qbg: Nearly complete defn implementation using https://github.com/qbg/syntax-rules: https://gist.github.com/757885

18:14 The error messages it produces aren't that bad also

18:15 Needs more/better syntax sugar

21:06 gfrlog: this templating idea is tricky

21:06 due to the behavior of eval

21:50 AWizzArd: Currently concrete implementations of protocol FNs in defrecords/types can not be closures. The docs also mention this. I am curious if this is technically not possible, because some JVM internas, or if it was intentional.

21:51 Example: (defprotocol Foo [bar [this]]) and then: (let [x 10] (defrecord Baz [a] Foo (bar [this] (println x))))

21:51 ==> x can not be resolved in that context.

21:53 cemerick: AWizzArd: IIUC, that would require Baz to be an inner class, where x would be held in the outer class.

21:53 (as a static field, presumably)

21:54 AWizzArd: And Baz should not be an inner class I guess.

21:55 And could the closed over fields not be added as private vars to the Baz class?

21:55 cemerick: It'd be particularly unfriendly if deftypes were to be alternately inner or "regular" classes, depending upon the presence of a lexical scope.

21:55 gfrlog: ,(s2/replace "s" #"s" (fn [_] "\\node"))

21:55 clojurebot: java.lang.Exception: No such namespace: s2

21:55 cemerick: What if you've got multiple defrecords in that let scope?

21:56 gfrlog: (clojure.contrib.str-utils2/replace "s" #"s" (fn [_] "\\node"))

21:56 ,(clojure.contrib.str-utils2/replace "s" #"s" (fn [_] "\\node"))

21:56 clojurebot: java.lang.ClassNotFoundException: clojure.contrib.str-utils2

21:56 gfrlog: gosh dangit

21:56 AWizzArd: Hmm okay, in that case the objects would be separate.

21:57 amalloy: gfrlog: (constantly "\\node") is a simpler way to write that (fn)

21:57 AWizzArd: I just got used to proxy closures and liked that style :)

21:57 gfrlog: amalloy: I'm trying to demonstrate what appears to be a bug in s2/replace

21:57 AWizzArd: It was not obvious to me why this should not work too for defrecords.

21:57 cemerick: AWizzArd: you're roughly looking to have static fields in your records, which almost certainly isn't going to happen. :-)

21:57 gfrlog: in my repl it evals to "node"

21:58 cemerick: AWizzArd: you can always extend Baz to Foo with a fn *shrug*

21:58 amalloy: gfrlog: str-utils2 is way old, isn't it?

21:58 gfrlog: it is?

21:58 is there str-utils3 now?

21:59 ooh clojure.string

21:59 I haven't gotten into that habit yet

21:59 ,clojure.string/replace

21:59 clojurebot: java.lang.ClassNotFoundException: clojure.string

21:59 amalloy: &(require '[clojure.string :as s])

21:59 sexpbot: ⟹ nil

22:00 gfrlog: can you have it eval my expr?

22:00 amalloy: (s/join " " ["a" "b"])

22:00 AWizzArd: cemerick: so the idea is to do the extend outside of the defrecord and have those bodies be closures?

22:00 amalloy: &(s/join " " ["a" "b"])

22:00 sexpbot: ⟹ "a b"

22:00 gfrlog: my repl has clojure.string with the same bug

22:00 amalloy: &(doc s/replace)

22:00 sexpbot: ⟹ "([s match replacement]); Replaces all instance of match with replacement in s. match/replacement can be: string / string char / char pattern / (string or function of match). See also replace-first."

22:00 AWizzArd: cemerick: or is the idea to call closed over defns from within the bodies?

22:00 cemerick: AWizzArd: extend takes regular ol' functions, which are definitely closures.

22:01 AWizzArd: I didn’t know that, interesting. Does this come with a performance hit?

22:01 gfrlog: &(s/replace "s" #"s" (fn [_] "\\x"))

22:01 sexpbot: ⟹ "x"

22:01 amalloy: &"\\x"

22:01 sexpbot: ⟹ "\\x"

22:01 gfrlog: is there any reason to expect the string to be escaped twice?

22:01 &(s/replace "s" #"s" (fn [_] "\\\\x"))

22:01 sexpbot: ⟹ "\\x"

22:01 amalloy: gfrlog: oh, i see

22:02 gfrlog: I say it's either a bug or at least terribly counterintuitive

22:02 amalloy: the replacement is probably allowed to have backreferences like \1

22:02 gfrlog: oh I bet it is

22:02 cemerick: AWizzArd: compared to any other protocol dispatch, no

22:02 gfrlog: that's not necessary though since the fn takes the match :(

22:02 oh well

22:02 amalloy: yeah

22:03 gfrlog: if I had ever filled out a contributer thing I'd go amend the documentation

22:03 cuz that just took me an hour to figure out

22:04 cemerick: gfrlog: you still can :-)

22:04 gfrlog: &(s/replace "s" "s" "\\x")

22:04 sexpbot: ⟹ "\\x"

22:04 gfrlog: cemerick: I can fill out the form you mean?

22:04 cemerick: right

22:05 gfrlog: you're telling me that code doesn't get written just by griping in an IRC channel?

22:05 AWizzArd: I thought that inner implementations and extend / extend-type / extend-protocol are all the same.

22:05 cemerick: AWizzArd: from the standpoint of a protocol fn invocation, they are

22:06 The former are methods bolted into the generated class though; the latter are not.

22:06 AWizzArd: I see.

22:07 cemerick: thanks for your explanations :)

22:08 cemerick: AWizzArd: np, hope they help :-)

22:08 AWizzArd: yess

22:31 auser: hola all

22:33 has anyone implemented a proxy server in clojure?

22:53 AWizzArd: auser: can you be more specific?

22:56 auser: ah fair enough AWizzArd... I mean... I'd like to accept socket requests on a port and route requests according to the request details to other internal ports

22:56 AWizzArd: auser: similar to ssh -D ?

22:57 What I did was using Jetty to proxy a binary B. So, clients can send jobs to B through my rest interface.

22:57 auser: I've done it in erlang, ruby and c, just haven't done it in clojure yet

22:57 I was thinking using jetty

22:57 http://www.jboss.org/netty/documentation.html (Proxy Server)

22:57 yeah, exactly

22:58 AWizzArd: It’s a good choice to start with. Or netty, yes.

22:58 auser: is your code open-source, by chance?

22:58 yeah

22:58 AWizzArd: I didn’t do Netty yet, because this targets other use cases, but in principle it’s the same.

22:58 auser: what's the difference?

22:59 AWizzArd: No, this code is closed-source (for the company i work for).

22:59 auser: ah fair enough

22:59 AWizzArd: Netty is good when you have a massive amount of ultra short running requests.

22:59 Jetty is for everything else.

22:59 So: echo server ==> Netty

22:59 auser: so netty is more concurrent, it sounds like?

23:00 AWizzArd: Netty is non-blocking.

23:00 auser: ahh

23:01 AWizzArd: Also Jetty has very nice support.

23:01 auser: maybe something like this: http://efreedom.com/Question/1-1735776/Server-Programming-Clojure ?

23:01 AWizzArd: You can suspend running threads

23:01 auser: cool

23:02 AWizzArd: auser: basically what I did was: setting up a resource, for example: POST: https://example.com/process and my handler sends the job to a Clojure agent which operates the Binary.

23:03 Done with promise injection and an agent, though an ArrayBlockingQueue is an even better fit :)

23:04 auser: interesting, I am using LinkedBlockingQueue

23:04 AWizzArd: yes, also fine of course

23:04 auser: rather, I'm not familiar with ArrayBlockingQueue

23:04 yep yep

23:05 AWizzArd: My point was more about using a Queue from the j.concurrent package, so, the LBQ is fine.

23:05 auser: ah yeah

23:07 AWizzArd: auser: about the link that you posted — depending on what you want to do you should look into Jetty.

23:07 auser: yeah, that's a good thought. I'll look more heavily into Jetty

23:08 AWizzArd: Netty uses only a small number of threads. If one request is long running then all clients in the work-queue of that thread will have to wait, while Jetty would serve them cause its thread pool will grow.

23:09 Only if you plan to do 10k echo requests it would be overkill to make use of 10k threads, so this is were Netty would perform better.

23:09 auser: yeah, that's a good point, actually

23:09 no, most would not be echo requests

23:10 AWizzArd: auser: also in Jetty you can suspend threads. So for example, if a job is coming in and you need to do IO such as writing into a DB for, say, 25 msecs, then you can suspend the Jetty worker thread for those 25 msecs.

23:11 During this time it sits in the pool and is able to serve other requests. And when the DB has finished the thread can be resumed and answer the client.

23:11 auser: cool, that's a good idea

23:11 AWizzArd: So, that allows for nice concurrency.

23:11 auser: yeah, definitely!

23:11 hey, be right back

23:12 AWizzArd: auser|brb: you would like to read this: http://wiki.eclipse.org/Jetty/Feature/Continuations (6 minutes reading time required)

23:18 auser|brb: hey thanks AWizzArd

23:47 auser: it's possible to call (gen-class :name MyException :extends [Exception]) still, right?

23:47 when I do that, I get: Unable to resolve classname

23:52 or I could use error-kit

Logging service provided by n01se.net