#clojure log - Nov 21 2010

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

0:17 danlarkin: java crypto is enough to drive a person nuts

1:32 livingston: creating protocols and attaching them to classes / records is far easier than creating a ton of defmulti's but is there a way to put a default on a protocol function like I can for a defmulti, for something that doesn't have the specified behavior to return the default?

1:33 technomancy: livingston: you can extend Object.

1:33 livingston: yeah i was thinking about that, but then I won't get all the native types? or will it autobox an int into an Integer to get the behavior?

1:34 technomancy: I think calls from Clojure would get autoboxed; I don't know about calls from Java

1:35 ISTR some discussion about the Conj re: reservations about extending Object, but I don't remember the details

1:36 livingston: I think i'm ok with that... and the dispatch on protocols always picks the more specific type, if there are several applicable, I'm sure, right?

1:36 oops I mean ok with clj code and java maybe maybe-not

1:37 hmm maybe I should just keep this particular function as a defmulti instead of fighting with the protocol, since I pretty much want in to work for about anything

1:38 technomancy: personally I find the semantics of defmulti to be much more straightforward

1:38 defrecord attempts to straddle AOT and JIT worlds in ways that are still unpredictable to me.

1:40 livingston: yes me too, but when you have a handful of functions that naturally fall in a group, then protocols seems pretty useful (I came from lisp, there was nothing like protocol it was all dispatch so I think that way)

1:40 technomancy: for my purposes namespaces have served just fine as a way of grouping defmultis

1:41 livingston: the docs seem to imply if you can use protocols/records it's more efficient, but that's not exactly clear to me when there's still dispatch I would assume?

1:41 technomancy: but I could see the appear of the way protocols do it

1:41 it's very rare for that level of optimization to be justified.

1:41 unless you're writing clojure-in-clojure

1:41 talios: 'lo technomancy

1:41 technomancy: talios: hi

1:43 livingston: technomancy: i don't have a problem grouping them or whatever, that's fine. some of what I'm working on will end up in pretty tight loops, if there's a bit to eek out of that, I'll take it now - why not, doesn't seem that much harder with protocols. but I hear you on defmulti just making sense

1:43 talios: turns out spilling lemonade thru a macbooks keyboard isn't healthy for said macbook :(

1:43 technomancy: talios: time to get a thinkpad--built-in drainage in the keyboard =)

1:44 livingston: talios: bummer. yeah and they don't have drains, because I'm sure Steve Jobs thinks things like drains and vents are ugly

1:44 talios: livingston: yeh - hopefully the insurance will come thru and pay for a replacement ( which I could then upgrade to something more decent as well ).

1:44 draintrays would be a wonderful thing. I see the new HPs have them too.

1:45 livingston: I like my mac book. some things like that just make sense. like the mac power connector. there should just be basic things always included.

1:46 technomancy: they are nice, but I also like the fact that I can buy three thinkpad power supplies for the price of one apple power supply =P

1:46 talios: thankfully I have 98% of everything backed up, and thankfully co-podcaster richard loaned me his old macbook pro. so at least I can continue to do stuff

1:47 technomancy: surely liquids can't damage the drive?

1:47 livingston: it's not the power supply it's your laptop that goes flying when someone trips over the cord

1:47 talios: I should be able to get the data off it. will find out when I get the machine back from the store where I was getting a repair/insurance quote

1:48 livingston: yeah I would think last resort you could pull the drive. even if it had a drain there'd be some disassembly involved anyway to clean something like lemonade.

1:48 technomancy: livingston: I guess that would be a bummer if your laptop wasn't indestructible =)

1:49 livingston: technomancy: I've seen it happen more times than it should at conferences, sucks every time

1:49 technomancy: I have a 6-ft standing desk; I've pulled my laptop off it twice (from the ethernet cord, ironically) without a scratch.

1:50 talios: impressive

1:50 livingston: lucky. hopefully your drive readheads parked themselves in time - you won't see the scratches there ;)

1:56 technomancy: talios: I was up really late last week and couldn't help being struck by how quiet things are on freenode in your timezone.

1:58 talios: mmm, most of the people I know on IRC pride themselves with their idle times anyway :)

1:58 undernet seems to get more NZ users ( or used to at least ).

1:59 livingston: talios: that's funny. I can't run idle we have it blocked at work, and this web client will crap out sooner or later.

1:59 talios: I find it depends on the channel. Trying to get anyone from the codehaus servers to respond during my "awake" is impossible

2:00 livingston: ssh+irssi ;-)

2:00 technomancy: even better: ssh+free EC2 micro instance

2:01 talios: altho now you've made me think about the time I realise it's past dinner time - no wonder i'm hungry :)

2:01 livingston: I was just going to say I don't have anywhere to ssh to, but that's an interesting option

2:02 technomancy: free for a year

2:02 check out http://github.com/dysinger/nanosat

2:02 livingston: a better client would be better, but running idle offers no major advantage, I mean it's all archived on the net

2:02 technomancy: you can even get the machine provisioned using clojure

2:02 ERC works great on EC2

2:03 livingston: technomancy: what's ERC?

2:04 trybeingarun: Emacs Relay Chat

2:05 livingston: oh right, yeah I started off looking into using that, and then found out about the silly firewall - "only "hackers" and bots use IRC, can't possibly be useful" -- I said, "I know, I'm a hacker - you've hired one, now help me out."

2:06 technomancy: well if they allow SSH then it's game over

2:06 no point in blocking anything

2:07 hiredman: ssh even has a built in socks proxy

2:07 technomancy: heck; you can run an SSH server on the HTTPS port and get around anything

2:08 talios: tcp/ip over dns works as well :-) slow as all hell, but works.

2:08 http://analogbit.com/tcp-over-dns_howto

2:08 livingston: yeah, their avg. user doesn't know that here though. I don't know how smart their firewall is though, it may look for odd traffic like that.

2:08 hiredman: it sure is slow

2:08 technomancy: or ICMP

2:10 livingston: if it's something that's needed you can file paperwork and get it eventually - you should have seen what was involved for a skype exemption -- meanwhile I can just use webchat

2:10 technomancy: grumble... still no paredit 22 in elpa.

2:10 I really need to get my own package server working.

2:10 talios: bbl - going to find some dinner. I'm thinking Thai.

2:11 hiredman: technomancy: I built the latest emacs and the paredit from the starter kit stopped working (looked like a conflict with a paredit that came with emacs)

2:11 technomancy: paredit comes with emacs now... !

2:11 wat

2:12 hiredman: maybe, I did look that into it, I uninstalled the elpa paredit, stopped getting warnings, and still have paredit

2:12 I did not look

2:12 or something

2:12 technomancy: I'm not seeing it; must have been an older manual install

2:13 the one in elpa is so old it doesn't really work with {} =(

2:13 hiredman: right

2:13 and whatever I have now does

2:14 technomancy: the latest one has a new feature where you can configure it to sorta even work in JS without inserting those annoying spaces

2:16 hiredman: weird, I cannot find a predit file in the emacs src, or in my .emacs.d, but I have predit

2:18 technomancy: M-x locate-lib

2:20 hiredman: ugh, it is in my .emacs.d, but I was running find $PWD, and $PWD was a symlink, so fail

2:36 livingston: i hate having to either forward declare things or write code that seems upside-down.

2:43 records will behave just like maps when it comes to accessors and keys, right?

2:44 hiredman: records don't extend IFn if I recall

2:45 livingston: hiredman: ok so you just have to make sure to do (:keyword record) instead of the other way around, right?

4:10 fbru02: Hi anyone around ?

4:11 kumarshantanu: hi, can somebody tell me if this is the right way to pass type hints? -- (fn [^java.util.Map m k] (.contains m k))

4:12 I am getting warning though

4:20 livingston: you can try putting the hint in the (.contains call

4:21 (.contains ^hint m k)

4:24 kumarshantanu: livingston: still not working :(

4:24 (fn [^java.util.Map m ^String k]

4:24 (.contains ^java.util.Map m ^String k))

4:37 notsonerdysunny: can somebody help me understand clojure.zip/seq-zip with an example?

4:40 _ato: kumarshantanu: java.util.Map has no .contains method

4:40 http://download.oracle.com/javase/6/docs/api/java/util/Map.html

4:44 kumarshantanu: _ato: you are right! (wondering why .contains works nevertheless)

4:45 _ato: I changed it to .containsKey and it no more gives a warning

4:46 _ato: must be whatever concrete class is being passed in does have a .contains and Clojure is finding it via reflection at runtime

4:47 kumarshantanu: _ato: right

5:02 fbru02: hey can somebody try this and see if this is also failing for you?

5:03 https://github.com/alexott/clojure-libs/blob/9a6bbe7b7cd1c299d05863d8c82ef2468cf0e706/mahout/project.clj

5:26 Vinzent: fbru02: yes

5:27 fbru02: Vinzent: cool , I thought i was the only one that got that failing , thanks

5:32 Vinzent: np

6:44 LauJensen: I justed released a new jar on clojars in which ClojureQL now supports joins on multiple tables

6:44 s/justed/just/

6:44 sexpbot: <LauJensen> I just released a new jar on clojars in which ClojureQL now supports joins on multiple tables

6:46 _ulises: morning all

6:55 fbru02: LauJensen: Cool

7:04 i have a mvn question, i'm using lein, and i have a project that needs some other project. This second project has a pom with dependencies etc. Do i have to specify all the deps for the second project in my first project or is there a way of mvn/lein knowing how to resolve those?

7:06 _ato: maven/lein will do transitive dependency resolution. So if project A depends on B and B depends on C, then A will pull in C as well without you having to specify it explicitlyfff

8:01 raek: hrm, why do I get "Can only recur from tail position" when I do (when-let [y (f x)] (recur ...) (...))?

8:02 ah, nevermind...

8:02 *if-let*

8:37 joeyd81: Hi, there has to be a better way to do AOT compilation than what I do : echo "(compile 'explore.perm)" | clj_compiler

8:38 raek: what is clj_compiler?

8:39 I would use one of the build tools (Leiningen or Cake)

8:39 with Leiningen, it would be "lein compile", I think

8:40 joeyd81: exec java -server -d64 -cp ${JAR}/clojure-contrib.jar:${JAR}/clojure.jar:${JAR}/

8:40 jline-0.9.94.jar:/opt/clojure jline.ConsoleRunner cloj

8:40 ure.main $*

8:41 I am calling this stuff from within a Makefile

8:45 kumarshantanu: can anybody tell me if it's possible to type hint object arrays (non-primitive arrays)?

8:49 edbond: how to println in -main?

8:55 raek: edbond: (defn -main [] (println "hello")) ?

8:58 edbond: raek, ha this doesn't print anything

8:59 raek: it will only print when -main is called. in what situation do you want it to be called?

8:59 edbond: raek, oops I use printf not println

9:00 raek: -main is usually for when you AOT compile your project into a jar

9:00 joeyd81: how do you test for 2 things being identical vs. equal in clojure?

9:01 raek: joeyd81: identical? is for object identity

9:01 joeyd81: in Ocaml you have physical equality (==) vs. structural equality (=)

9:01 raek: joeyd81: = means value-based equality for immutable types and identity-based equality for mutable types

9:02 (this is the semantics for types introduced by clojure. for java types, = means java .equals and identical? means java ==)

9:02 joeyd81: I definite identical thus - the 2 things have the same address in memory and are equal, vs. equal - different addresses in memory

9:03 raek: joeyd81: then clojure.core/identical? fits your definition of identical

9:03 joeyd81: ok, cool is there sugar for it?

9:04 raek: oh, sorry. I misinterpreted you statement. identical? is only same address in memory

9:05 but how could they not be equal if they are the same object?

9:05 ,(= [1 2 3] [1 2 3])

9:05 clojurebot: true

9:05 raek: ,(= [1 2 3] '(1 2 3))

9:05 clojurebot: true

9:05 raek: ,(= (atom [1 2 3]) (atom [1 2 3]))

9:05 clojurebot: false

9:06 raek: ,(identical? [1 2 3] [1 2 3])

9:06 clojurebot: false

9:06 raek: you could see = as sugar for identical? if you are comparing reference types

9:07 joeyd81: so when I store an object into a collection the address of it is stored, not the object itself, seems to me

9:07 raek: yes

9:07 on the JVM, only primitives are stored themselves

9:07 joeyd81: good, thanks a lot raek

9:07 raek: objects and arrays are reference types

9:09 two sequential collections are = if they are = element-wise and of the same size

9:09 ,(let [a (atom 1)] (= [0 a 0] [0 a 0]))

9:09 clojurebot: true

9:10 raek: 0 = 0, because they are the same value, a = a because they are the same object

9:10 joeyd81: then what is == used for

9:11 in clojure?

9:13 it seems to me that == is used solely for numerical comparisons in clojure

9:13 edbond: joeyd81, read http://clojuredocs.org/clojure_core/clojure.core/==

9:14 raek: ,(= 1 1.0M)

9:14 clojurebot: false

9:14 raek: ,(== 1 1.0M)

9:14 clojurebot: false

9:15 raek: I have never used ==

9:15 joeyd81: ok, enough dumb questions for today, thanks everyone

9:15 jarpiain: ,(== 1.0M 1.00M)

9:15 clojurebot: false

9:17 raek: ~source ==

9:27 joeyd81: actually 1 more question and no more - how can I unify the repl definitions of -main and the AOT compiled version of same? Here is what I mean, in the repl the definition is (defn -main [args] .....) and it gets called (-main *command-line-args*) VERSUS compiled code the definition is (defn - main [& args] ......) . As you see args are passed in differently, hence I can't have the same -main code

9:28 raek: what code calls (-main *command-line-args*)?

9:28 'cause that should indeed be (apply -main *command-line-args*)

9:28 joeyd81: The repl calls it

9:28 raek: leiningen?

9:28 clojurebot: http://github.com/technomancy/leiningen

9:28 joeyd81: no, I don't use leinigen just yet

9:28 raek: hrm

9:29 how do you launch clojure?

9:29 joeyd81: java -server -d64 -cp ${JAR}/clojure-contrib.jar:${JAR}/clojure.jar:${JAR}/jline-0.9.94.jar:/opt/clojure jline.ConsoleRunner clojure.main $*

9:29 raek: so clojure.main calls the -main function?

9:30 joeyd81: yes I think

9:30 raek: that's odd

9:30 how does it now in which namespace it should look for the -main var...=

9:31 joeyd81: I don't know but it looks like the answer is to call (apply -main *command-line-args*), I will give this a try

9:31 raek: what is in the $* variable?

9:31 joeyd81: represents the args to the -main

9:32 raek: yes, but what args do you pass it?

9:32 joeyd81: the argv[] array from the C world

9:34 raek: joeyd81: is there any (-main *command-line-args*) call in your code?

9:34 jarpiain: ,(doc clojure.main/main)

9:34 clojurebot: "([& args]); Usage: java -cp clojure.jar clojure.main [init-opt*] [main-opt] [arg*] With no options or args, runs an interactive Read-Eval-Print Loop init options: -i, --init path Load a file or reso...

9:35 joeyd81: I paste that code into the repl after the -main definition: (-main *command-line-args*)

9:35 raek: ah.

9:36 joeyd81: but you said it should be (apply -main *command-line-args*) if -main takes [args] instead of [& args]

9:36 raek: you should probably do something like ... clojure.main -e "(use 'the-namespace) (apply -main *command-line-args*)" ...

9:36 if you have a call to -main in the source file, that will be run at *compile time* when you AOT compile your source

9:37 joeyd81: ok, let me give it a try, this chat room is awesome

9:37 raek: :)

9:38 there is a lein-run plugin for this (will be a part of leiningen itself in the next release, I think), if you happen to start using leiningen later on

9:43 fbru02: _ato: thanks for your answer I just came back to the computer

10:11 cljbie: hi everyone.

10:12 anyone here also using python?

10:12 python has dir() method which lets me see what methods and attributes an object has, does clojure have anything like that?

10:15 yacin: cljbie: maybe show in clojure.contrib-repl-utils?

10:16 cljbie: yacin: i only have clojure and don't know what that is

10:17 yacin: how did you install clojure?

10:17 but i'm sure show is what you want

10:17 ,(show "str")

10:17 clojurebot: java.lang.Exception: Unable to resolve symbol: show in this context

10:18 yacin: ,(use 'clojure.contrib-repl-utils)

10:18 clojurebot: java.io.FileNotFoundException: Could not locate clojure/contrib_repl_utils__init.class or clojure/contrib_repl_utils.clj on classpath:

10:18 yacin: hmm

10:19 ,(use 'clojure.contrib.repl-utils)

10:19 clojurebot: java.io.FileNotFoundException: Could not locate clojure/contrib/repl_utils__init.class or clojure/contrib/repl_utils.clj on classpath:

10:19 cljbie: there is "inspect"

10:19 i found that hmm

10:21 yacin: ,(use 'clojure.contrib.shell)

10:21 clojurebot: java.io.FileNotFoundException: Could not locate clojure/contrib/shell__init.class or clojure/contrib/shell.clj on classpath:

10:21 yacin: hmm, guess you can't import contrib

10:21 anyway, repl-utils' show is what you want

10:21 user=> (show "str")

10:21 === public final java.lang.String ===

10:21 [ 0] static CASE_INSENSITIVE_ORDER : Comparator

10:21 [ 1] static copyValueOf : String (char[])

10:21 [ 2] static copyValueOf : String (char[],int,int)

10:21 [ 3] static format : String (Locale,String,Object[])

10:21 ...

10:23 raek: $(use '[clojure.contrib.repl-utils :only (show)])

10:23 &(use '[clojure.contrib.repl-utils :only (show)])

10:23 sexpbot: java.io.FileNotFoundException: Could not locate clojure/contrib/repl_utils__init.class or clojure/contrib/repl_utils.clj on classpath:

10:23 raek: well, the bot's are limited... :)

10:25 SergeyD: Hi! Is there a better way to translate [[3 4 5]] into [3 4 5] than "(apply map identity [[3 4 5]])" ?

10:25 yacin: ,(flatten [[3 4 5]])

10:25 clojurebot: (3 4 5)

10:25 cljbie: thanks yacin

10:25 yacin: np

10:25 SergeyD: oh, thanks :)

10:25 yacin: np :)

10:26 or i guess you could just use first

10:26 SergeyD: ,(first [[345]])

10:26 clojurebot: [345]

10:41 cljbie: yacin: i have a list. how can i loop through all of the elements and sum them all up?

10:43 trybeingarun: (defn sum-list [lst]

10:43 yacin: ,(reduce + [1 2 3 4 5 6])

10:43 clojurebot: 21

10:43 trybeingarun: (reduce + l))

10:45 yacin: there's no reason to make a separate function

10:45 reduce is clear enough, imho

10:46 trybeingarun: yep. my bad :)

10:59 cljbie: alright :)

10:59 i've written my first clojure function

10:59 kumarshantanu: is a type hint in a macro passed to ~@body ?

11:01 cljbie: yacin: http://paste.pocoo.org/show/294246/

11:01 :)

11:02 a question here. if i wanted to store "(+ 1 (count others))" part in a variable, how should i have done it and how could i use it in the calculation?

11:03 raek: (let [c (inc (count others))] ...calculations...)

11:05 another slight variation would be to let the function take a sequence rathern than multiple arguments

11:05 trybeingarun: There is a version of reduce function which takes 3 args, [fn val coll] which is also useful

11:05 raek: (defn avg [coll] (/ (reduce + coll) (count coll)))

11:07 cljbie: also, you usually indent like this: http://pastebin.com/dzTYsevH

11:07 trybeingarun: make sure that you handle the case of empty collection, where (count coll) is 0

11:08 raek: two spaces for def* forms and closing parens not on separate lines

11:09 bhenry: raek: (defn avg [& args] (/ (reduce + args) (count args))) would look nicer when calling imo

11:09 silveen: I'm trying to get ClojureQL running, but I'm getting SQLExceptions, "no suitable driver found". Any know anything about this if there's anything I've missed?

11:09 bhenry: i'm just coming in, so maybe i missed an important part of the discussion

11:09 raek: depends on whether you make the call manually or get a sequence of values from somewhere else

11:10 cljbie: thanks raek

11:10 trybeingarun: Or trust your ide for indentation :)

11:11 raek: yes, you shouln't have to indent your code manually...

11:11 i emacs: select the code and press tab

11:11 cljbie: i have not setup my vim for clojure yet

11:11 trybeingarun: Me 2 emacs!

11:11 how is vim's clojure support?

11:11 bhenry: M-q for the win.

11:11 silveen: trybeingarun: it's terrible

11:12 cljbie: there is vim-clojure which i have not tried yet

11:12 silveen: I got slimv running last night. But it causes the entire window to flash like a disco lamp.

11:12 trybeingarun: I find emacs' clojure support very good

11:12 I, however am facing a huge pain point

11:12 silveen: vim-clojure requires that dreadfull Nailgun server running

11:12 trybeingarun: (read-line) is not working in emacs

11:13 Anybody managed to fix that (read-line) problem in emacs?

11:15 raek: Dude, do you have any suggestions for (read-line) issue?

11:15 kumarshantanu: asking again...is a type hint in a macro passed to ~@body ?

11:16 trybeingarun: At least in my setup (read-line) is not taking any user input

11:16 raek: yes, I never got that to work. but then, I haven't needed it yet

11:16 trybeingarun: can you please share how you got that to work?

11:17 I am sorry. Din't read ur reply properly. OOPS!!

11:19 raek: maybe you could do something like (binding [*in* System/in] (read-line)) and type it in the swank terminal

11:19 it's too bad that the swank protocol is mostly undocumented...

11:20 * raek is looking forward to the happy time in the future when everyone is using nRepl

11:20 trybeingarun: let me see if it works...

11:21 what is the advantage of nRepl?

11:21 raek: hrm... how does one get the root binding of a var when it has a thread-local binding...

11:21 it is a replacement for swank

11:22 trybeingarun: hm

11:22 raek: one of its goals is that it should be usable from any IDE

11:22 and built for clojure

11:22 trybeingarun: then that should be awesome!!

11:22 raek: (future (def in *in*)) ;; ouch!

11:23 (binding [*in* in] (read-line))

11:23 hrm... that didn't work

11:24 trybeingarun: I am getting an error saying "in" is not defined

11:24 System/in is also not working for me

11:25 raek: bbl

11:25 trybeingarun: (future) What is that call? Never heard of that...

11:28 bhenry: ,(doc future)

11:28 clojurebot: "([& body]); Takes a body of expressions and yields a future object that will invoke the body in another thread, and will cache the result and return it on all subsequent calls to deref/@. If the com...

11:28 bhenry: &(doc future)

11:28 sexpbot: ⟹ "Macro ([& body]); Takes a body of expressions and yields a future object that will invoke the body in another thread, and will cache the result and return it on all subsequent calls to deref/@. If the computation has not yet finished, calls to deref/@ will block."

11:31 trybeingarun: Thanks

11:44 hiredman: http://byteworm.com/2010/11/21/the-fastest-vm-bytecode-interpreter/ cute

12:25 mrroman: hi, i'm here first time.

12:26 i've got problem with using clojure.string

12:26 tonyl: welcome

12:26 mrroman: i've got clojure 1.2 and i tried to start example of clojure.string/split from clojuredocs

12:27 and i've got error message java.lang.ClassNotFoundException: clojure.string (NO_SOURCE_FILE:0)

12:28 tonyl: did you (use 'clojure.string) before calling it

12:28 since it is in another namespace

12:29 mrroman: yes, but i used full path to function, clojure.string/split

12:29 tonyl: or better use require since some functions' names would collide

12:29 mrroman: ok

12:29 hiredman: mrroman: clojure namespaces have to be explicitly loaded

12:30 mrroman: ou

12:30 ok, thanks for help

12:30 tonyl: hiredman: I never understood why is that, do you know?

12:32 hiredman: tonyl: I imagine the ultimate answer is it makes distinguishing between vars and classes easier for the compiler

12:32 mrroman: BTW, great number of members, 256

12:33 mengu_: what is the difference between (use 'clojure.inspector) and (:use 'clojure.inspector)?

12:33 kumarshantanu: is it possible to type hint non-primitive arrays?

12:33 hiredman: (:use 'clojure.inspector) is incorrect in all cases

12:33 (use 'clojure.inspector) may or may not be

12:34 kumarshantanu: yes but it is rarely useful

12:34 kotarak: kumarshantanu: ^"[Lyou.custom.Class;" the-array

12:34 kumarshantanu: kotarak: I am trying the same technique, but it still warns me for reflection

12:35 kotarak: mengu_: use is a standalone function, :use is only used in the ns clause, :use is without '

12:35 kumarshantanu: hiredman: I am calling a Java method that accepts arrays

12:35 hiredman: kumarshantanu: ah

12:35 mengu_: kotarak: thats why :use did not work when i tried it then

12:35 kotarak: kumarshantanu: might depend on other arguments?

12:36 kumarshantanu: kotarak: certainly not -- but curiously (1) that technique works for ^"[Ljava.util.Map;" but not for ^"[Ljava.lang.Object;" and (2) I am doing this inside a macro

12:38 kotarak: kumarshantanu: because you hint (unquote x). the list. Not x itself. You have to do ~(with-meta x {:tag 'String}) ....

12:39 kumarshantanu: shameless self-promotion (although a little out-dated by now): http://bit.ly/a51mbM

12:41 * kumarshantanu looks at Kotarak's link

12:41 kumarshantanu: kotarak: what is {:tag 'String} for?

12:42 kotarak: kumarshantanu: This is was ^String does.

12:42 kumarshantanu: ah

12:42 kotarak: kumarshantanu: ^String is short for ^{:tag String}

12:43 kumarshantanu: Uh. I even had your problem as an example at the end. :)

12:44 kumarshantanu: so, for ^"[Ljava.lang.Object;" it should be {:tag '"[Ljava.lang.String;"} ?

12:44 kotarak: it's working !!

12:44 kotarak: yup

12:44 \o/

12:45 Actually without '

12:45 '"bla" and "bla" are the same

12:46 kumarshantanu: kotarak: thanks! I was struggling for the past two hours and finished watching a movie meanwhile due to frustration :)

12:46 kotarak: kumarshantanu: hehe :) That's a good approach. I do the same from time to time. :)

13:17 rdeshpande: howdy

13:23 mengu_: hi rdeshpande

14:33 LauJensen: Im looking for a simple solid introduction to log4j logging on Tomcat - Got link?

14:37 nickik: does anybody know when the clojure conj videos will be available?

14:41 raek: nickik: here. have a strange loop talk by chouser while you wait. :-) http://www.infoq.com/presentations/Clojure-Expression-Problem

14:42 nickik: i allready watched that.

16:52 joeyd81: I still can't get my simple permutations program to work, http://pastebin.com/UrRfi124

17:00 tufflax: joeyd81 btw normally people don't have spaces between '(' and the operator, as on you line 4, and not newlines after ( and [ as in your line 12 and 13. And they normally just stack up ) behind each other, not using newlines for each like you have on lines 24-26. And I don't think it's a good idea to use defn within another function, use let or letfn instead.

17:01 I'll try to see what's wrong with your program but your style confuses me :P

17:01 joeyd81: ok, thanks for the feedback, I will rework it soon, I am just a newbie and the syntax betrays that

17:03 tufflax: using defn within a function doesn't work as you think, probably. I think it "creates" the function in the namespace just as if you had written it outside the function, but only when you run the function that contains the inner defn. So it's a side effect of running the outer function.

17:04 joeyd81: ok, so you're saying that I should replace it with letfn? Earlier I put it inside the let binding but the compiler complained that 'permute' is undefined

17:05 _ato: put all your functions at the top-level and use (declare permute) before (defn gen-perms ...) so that gen-perms knows permute exists

17:05 tufflax: Yes... It should work fine. Paste the code again if you change it and then get errors

17:06 joeyd81: ok, I will change it soon as you suggested but the stylistic issue aside, it would still yield the wrong answer

17:08 ossareh: joeyd81: also, I think your recursion is done incorrectly. If the JVM had TCO then you can recurse as you are on line 23, however since it doesn't then in theory you could overflow the stack - this is what loop / recur is for, and given that you could in fact have your permute fn in the let before it.

17:09 I guess, said a little more concisely, the assertion in the comment on line 10 is incorrect; your recursion is implemented in correctly.

17:10 joeyd81: ok, give me 5 minutes to move it in a letfn declaration and repost

17:11 tufflax: joeyd81 or do what _ato said, move the functions out completely

17:12 ossareh: tufflax: assuming there is a benefit to having a global var for that fn, then yes that is a good idea too.

17:12 joeyd81: but I like inner functions that refer to the closure in which they are defined

17:12 tufflax: joeyd81 also, why do you have a function called main? It should be easy to test the individual functions in a REPL

17:13 joeyd81: I have used the repl repeatedly to test the smaller functions

17:14 tufflax: ok good

17:18 Raynes: _ato: It speaks!

17:18 _ato: Haven't seen you in a while. :<

17:18 joeyd81: ok, I made the changes that you guys suggested and I still get the wrong answer, http://pastebin.com/qbztx8LE

17:20 _ato: Raynes: hi

17:21 joeyd81: hmm, the first thing I notice is that gen-subsets' base case is inconsistent:

17:21 (gen-subsets #{1 2}) ;; => ((1 (2)) (2 (1)))

17:21 (gen-subsets #{1}) ;; => (1 ())

17:21 shouldn't (gen-subsets #{1}) be ((1 ())) ?

17:23 joeyd81: ok, I am thinking about it, not ignoring you

17:26 added (list ....) to the base case (1 el in set) and still got the same result

17:33 _ato: joeyd81: http://pastebin.com/ph73mKC0

17:35 joeyd81: great, your program works! How could you print each permutation on a separate line (i.e. vertically instead of horizontally)

17:37 _ato: joeyd81: just call println on each permutation?

17:37 eg: (dorun (map println (permute (range 1 4))))

17:38 joeyd81: ok, you're great, I am going away now to study your code, thanks and see you guys later

17:52 tufflax: I'm using vimclojure with the nailgun server to get a repl. And then I try to eval "(ns pe)" by sending with <leader>et and it gives me the following error: java.io.FileNotFoundException: Could not locate pe__init.class or pe.clj on classpath... Writing it in the REPL works though. Does anyone know what's wrong?

17:54 kotarak: tufflax: you have to have the appropriate files set up on your classpath

17:55 tufflax: vc reads the namespace to provide things like omnicompletion and such.

17:55 tufflax: But what's the difference between writing in into the repl by hand and sending it with <leader>et

17:55 ok

17:55 hm

17:56 kotarak: tufflax: exactly that: writing in the repl does nothing but the command. Sending \et loads the namespace. Because vc can't know what you send, it has to set up everything so that all required functions are in place.

17:57 tufflax: ok, thank you

18:10 jimduey: joeyd81: I'm stepping into the middle of your conversation, but do you know about clojure.contrib.combinatorics?

18:10 (use 'clojure.contrib.combinatorics)

18:11 (println (interpose \newline (permutations (range 1 4))))

18:11 joeyd81: no, thanks for the link. I was just in the process of learning clojure by way of writing simple programs, that's all

18:11 jimduey: excellent. good way to start.

18:17 CaseyS: hello all

18:51 rata_: hi

19:07 ossareh: I wonder why so many people use macro's where a fn would suffice.

19:07 Is there some fundamental misunderstanding about macros?

19:08 * ossareh just caught himself doing it.

19:09 zakwilson: I think the misunderstandings are usually related to what can be accomplished with an ordinary function.

19:09 joeyd81: hey guys, does clojure support eta reduction, example of something I want to reduce is this: (my-map [f colls]

19:09 (if (> (count colls) 8) (pmap f colls) (map f colls)))

19:09 Raynes: zakwilson: Indeed. You can be *really* creative with functions to accomplish things that you might assume are only possible with macros.

19:10 chouser: Demonstrated this on the hotel shuttle at the Conj that I happened to be on when he and a group were off to the car rental place. He pointed out how 'or' and 'and' could be implemented using normal functions.

19:10 <3 chouser

19:11 zakwilson: I think the Right Thing is to do whatever is easiest to understand. Usually, that's a normal function, not a macro, but if lots of trickery is required for the function to work, go with the macro.

19:12 _ato: Raynes: they're implemented as macros so that they can short circuit. eg (or (foo) (bar)) doesn't need to execute (bar) if (foo) returns true. You can't do that with a function (unless you changed 'or' to take functions instead of values)

19:13 Raynes: _ato: I know. That's what I just said.

19:13 Well, I didn't explain myself, but that's what I was talking about.

19:13 _ato: ah, I see

19:13 rata_: is there anything like Python's "template %s" % ("strings") ?

19:13 Raynes: He was talking about how and and or could be written as functions that take functions.

19:14 _ato: ,(format "I %s food" "food")

19:14 clojurebot: "I food food"

19:14 _ato: Raynes: ^

19:15 Raynes: _ato: I'm not rata_

19:15 rata_: hahahaha thanks =)

19:15 zakwilson: A lot of things we do with macros require macros because macros let you evaluate some or all arguments lazily. Haskell can do them without macros because it's lazy by default. It is also possible to do similar things with ugly syntax in any language that lets you pass something resembling a thunk.

19:15 _ato: damn.. channel is getting too crowded (ra<tab>) ;-)

19:16 joeyd81: Hey guys, what is a better way to write this function, so that repetition is reduced (defn my-map [f colls] (if (> (count colls) 8) (pmap f colls) (map f colls)))

19:17 zakwilson: That's pretty succinct as it is. What would you like to not repeat?

19:18 joeyd81: the args f coll

19:18 ossareh: agreed, only thing I see is potentially providing the map function - but then you start to introduce ambiguity

19:20 _ato: (defn my-map [f colls] ((if (> (count colls) 8) pmap map) f colls))

19:20 I prefer the original though

19:21 joeyd81: yes, you nailed it _ato, that's what I was looking for

19:21 zakwilson: You could write a macro somewhat resembling ->, which I'll call -:/ for purposes of this discussion that would allow you to write (defn my-map (-:/ [f colls] (count colls) pmap map)), but that would be pathological.

19:23 joeyd81: :), macros are too advanced for me, I'll study them in the context of a DSL implementation in clojure of a non-lisp language, if there is one such implementation pls feel free to provide a link

19:25 dnolen: ,(let [x 5 y 4] `(+ ~x ~y))

19:25 clojurebot: (clojure.core/+ 5 4)

19:26 joeyd81: example: the DSL is the syntax in which you write Makefiles, input is a makefile, output is the interpretation of the actions in it

19:26 dnolen: joeyd81: think of macros as "HTML templating" for code. DSLs are not the only usecase.

19:28 zakwilson: joeyd81: a macro would let you write a shorter version of the function you gave as an example, but it would be a mistake to write one for that situation because it would make the overall system more complicated and longer. If you had to write 10 functions that looked almost identical, macros might make short work of it.

19:29 joeyd81: yes, I understand that application of macros but to be really impressed I want to see them used to implement a DSL for a simple non-lisp language, I just don't know of any such implementations though I'm sure they exist

19:32 zakwilson: If you're going to make a non-lisp language, you really need a parser, not macros.

19:35 joeyd81: I thought you could write something like this http://www.venge.net/graydon/talks/mkc/html/index.html in lisp/clojure easier than in any other language

19:35 with macros alone

19:38 zakwilson: Well, you probably *could* write a DSL that has to be wrapped in (eval-my-dsl ...) without writing a parser, but it's probably not a good way to go about it.

19:40 The most common use of macros is to delay evaluation of an argument so you can write control structures like if and when. Other common uses include making a Lisp-like DSL that outputs a non-Lisp language and making a template for often-repeated code that can't be optimized away by other means.

19:41 joeyd81: camlp4 macros are not any more powerful than lisp/clojure macros, it seems, the reason I mention it is because I want to explore the depths of what is possible with lisp/clojure macros

19:42 zakwilson: I have minimal experience with ML, but I suspect an ML macro system is more limited than Lisp macros.

19:42 Furthermore, Clojure macros are more limited than Common Lisp macros.

19:42 joeyd81: Yes, that's my point too. So if that guy in the link can write a DSL with camlp4 macros, the same should be possible with clojure

19:43 I just want to see a common lisp or clojure example of something like that

19:44 zakwilson: I just picked a random slide and he was talking about writing a recursive-descent parser, which suggests that he DID use a parser.

19:46 joeyd81: he is not, camlp4 is the macro facility employed by the ocaml system, he is using a lexer but no parser

19:53 zakwilson: http://www.venge.net/graydon/talks/mkc/html/mgp00021.html <-- here, he says he's using a recursive-descent parser. He uses pa_extend to write the parser, and while pa_extend comes with camlp4, it's not inherently part of a macro system; it's a parser library.

19:56 joeyd81: Just like in clojure macros have a narrower scope of application that you pointed out above, so does camlp4 primarily defined syntax extensions to the core language and is rarely if ever used for anything else. The guy who wrote the slides points out that it could be used for more than just staying within the confines of ocaml.... So I am not yet convinced that clojure macros may not be used to go outside the confines of the core langua

19:58 but I am not an expert on these matters, I just wish that an example would be provided in lisp or clojure of how you could do that, if it's possible

20:09 zakwilson: joeyd81: Clojure macros can't replace the entire syntax of the language directly. It looks like camlp4 can, but what it's doing is essentially the same as (eval-my-dsl (read some-file))

20:17 joeyd81: @zakwilson, so are you implying then that it's possible to write macros in clojure that implement a DSL, where neither the input is clojure nor the output is clojure? In the slides the input is a makefile, the output is an executable a.out program

20:20 zakwilson: joeyd81: it's possible, but the only reason to base the design of such a system around macros is to demonstrate that you can. The Right Thing is to write a parser and a code generator. Both will probably make use of macros to some degree.

20:22 joeyd81: I tend to agree that it's not the Right Thing to do but if there is such an example in Lisp or Clojure I'd love to study it because it pushes the limits of what is possible to achieve with macros

20:26 jweiss_: is there doc somewhere on how to get gen-class to add annotations? i saw some old mailing list posts, but I'm not sure if that was the proposed solution or the real deal

20:27 perhaps it works just like this? https://gist.github.com/377213

20:28 zakwilson: joeyd81: See an implementation of the Common Lisp loop macro for an idea of how to evaluate non-lisp inside a macro body. After that, it's just a matter of calling your macro on a list of the results of calling read on your non-lisp file until you hit EOF, though there are some limitations.

20:31 joeyd81: thanks zak, will definitely study it

20:33 zakwilson: joeyd81: another thing that's important to understand is that camlp4 seems to be a preprocessor, which is a bit different from Lisp macros. You could certainly write a Clojure program (with or without macros) that reads a file containing code written in a DSL, compiles that code to Clojure and uses that Clojure to spit out another language (though your OCaml example really only does the latter because the OCaml compiler can output C natively)

20:36 joeyd81: ok

21:17 livingston: I have a multi method, lets call it foo for select user defined / 3rd party classes foo needs to do something but for all clojure native types foo can be the identity function. I can make that the default behavior but then I lose the fail-fast checking on when foo isn't implemented for a 3rd party type -- thoughts?

21:23 do all the clojure native types implement any particular protocol/interface that I could dispatch on?

21:24 tonyl: var maybe

21:25 IVar

21:26 livingston: i would assume that's only for vars? I'm more looking for the clojure-only equivalent of Object.

21:27 jarpiain: livingston: http://tinyurl.com/clojure-classes

21:27 jweiss_: i cannot figure out how to get annotations onto the class i'm generating with gen-class. the classes always end up without them. is this supported?

21:29 livingston: jarpiain: wow there's a lot of detail in there thanks.

21:30 iObj may be what I want... although I still have to stare at that for a long time to be sure that java classes don't implement that too.

22:08 ossareh: other than java interop is there much benefit to a record over a structmap ?

22:08 livingston: ossareh: compiled in type information

22:09 dnolen: ossareh: java interop is not the main benefit of records

22:09 livingston: ossareh: see the discussion here: http://clojure.org/datatypes

22:10 * ossareh is reading

22:10 dnolen: ossareh: consider structmap a legacy feature, you should just records here on out.

22:10 s/just/just use

22:12 ossareh: dnolen: thanks, so it turns out it is a performance thing too it seems?

22:12 livingston: is there a way from the repl to see what interfaces/protocols an object instance is implementing?

22:12 ossareh: "one need not leave Clojure to get the highest-performing data structures possible on the platform."

22:12 joshua__: What is the best way to deal with forms when using appengine/compojure/enlive?

22:12 dnolen: ossareh: yes that's another benefit

22:12 rata_: livingston: (supers (class thing))

22:13 livingston: that's not showing me any protocols there should be at least two in this guys list

22:14 rata_: livingston: well, I don't know what are you looking at, but (supers (class [])) shows every interface vectors implement

22:15 dnolen: ,(supers (class []))

22:15 clojurebot: #{java.util.List clojure.lang.Seqable clojure.lang.Reversible clojure.lang.IEditableCollection clojure.lang.Sequential java.io.Serializable clojure.lang.Associative clojure.lang.IPersistentStack cloj...

22:16 livingston: I have an instance of a Record, (show _) reports the correct type, (supers (class _)) doesn't give me the protocols I have attached to it, and I have extended two onto it at least

22:19 _ato: I don't think there's an efficient way to do it, since :impls is stored with the protocol, not the other way around

22:20 livingston: so it's the protocols that know who implement themselves but no way to get from an object to a list of protocols (kinda makes sense since protocols don't monkey patch)

22:21 _ato: yeah, if you look at the source for extends? for example: https://github.com/clojure/clojure/blob/master/src/clj/clojure/core_deftype.clj#L444

22:21 hiredman: protocols don't create an is-a relationship

22:22 livingston: makes sense I suppose, I was just layering up a few of them on a thing, and I just want to make sure I was getting what I thought I was getting, and was hoping for some debugability even if ineffecient - oh well

22:27 interesting as a further oddity, if package foo has protocol P and record R it's foo/P and foo.R which is another differentiator between protocols behaving like classes/interfaces...

22:27 hiredman: package?

22:27 clojurebot: amespaces are (more or less, Chouser) java packages. they look like foo.bar; and corresponde to a directory foo/ containg a file bar.clj in your classpath. the namespace declaration in bar.clj would like like (ns foo.bar). Do not try to use single segment namespaces. a single segment namespace is a namespace without a period in it

22:27 hiredman: surely you mean namespaces

22:28 livingston: hiredman: yes

22:28 hiredman: well then why didn't you use the word "package"?

22:30 did

22:31 livingston: so if the protocol implementation isn't with the record, why is this more efficient, there's still dispatch right? or can the compiler find it ahead of time with type hints?

22:31 or is the efficiency of protocols/records only in that the records can have accessors etc. compiled in?

22:33 hiredman: I still think in common-lisp, the word is package over there -- force of habit

22:34 _ato: livingston: there's some discussion about it here: http://groups.google.com/group/clojure-dev/browse_thread/thread/59d2f3a1703cc09

22:35 livingston: _ato: thanks for the pointer, I'll look that over

22:37 _ato: kind of cryptic, but basically, yes you're right that you get maximum performance from a inline definition (like a class implementing the protocol's interface, which presumably deftype does). But the protocol also caches the last used implentation, which should help the common case for extending after definition

22:41 livingston: interesting. so if I put the protocol implementation on with a defrecord I'll get better performance than if I do it with an extend?

22:54 _ato: looks like it

22:56 livingston: I would not have expected find to do what find does, I was expecting more of a common-lisp find, although clj find happens to do exactly what I need

22:57 multiple return values would be really useful right about now too..

23:03 what's the preferred idiom for mapping a function that could produce nil and removing the nils? (remove nil? (map fcn data))

23:05 _ato: ,(doc keep)

23:05 clojurebot: "([f coll]); Returns a lazy sequence of the non-nil results of (f item). Note, this means false return values will be included. f must be free of side-effects."

23:05 _ato: livingston: ^

23:06 livingston: that's an extremely non-intuitive name, but ok.

23:06 _ato: thanks

23:06 _ato: heh, I agree about the name

23:07 livingston: keep sounds like it should be the opposite of remove and shouldn't inherently accumulate/map too

23:08 tomoj: keep? since when?

23:08 ,(:added ^keep)

23:08 clojurebot: Unmatched delimiter: )

23:08 livingston: tomoj: apparently 1.2

23:08 tomoj: shucks

23:08 ,(:added (meta keep)) ;?

23:08 clojurebot: "1.2"

23:09 tomoj: cool

23:09 livingston: my version of slime doesn't even recognize it as a reserve word (I probably need to update)

23:09 tomoj: eh

23:10 I've come to accept that random colors will show up inexplicably

23:10 livingston: there have been a lot of weird names added with stuff like that, I was following the discussion and gave up (the intent was to be intuitive but many are not: find, keep, etc.)

23:10 tomoj: find too/

23:10 ?

23:10 ,(doc find)

23:10 clojurebot: "([map key]); Returns the map entry for key, or nil if key not present."

23:10 tomoj: oh

23:11 livingston: yeah that's the function I wanted, but I went looking for a "find" expecting to have to wrap it myself around a map

23:11 tomoj: naming is hard :(

23:14 livingston: yeah, there's some stuff that's really confusing to me (lisp people?) in there, but it is what it is

23:15 _ato: 'keep' needs a succinct name or you may as well just do (remove nil? (map ...)). I can't think of anything intuitive that's succinct

23:15 livingston: _ato "mapcon" ;)

23:16 er mapcan I meant

23:18 I wonder if the compiler is smart enough / produces equally efficient code for keep and (remove nil? (map ... ?

23:18 _ato: hehe, intuitive for a common lisper maybe, but not for me

23:19 nah I don't think the compiler's clever enough to avoid the intermediate lazyseq objects

23:19 livingston: I'm not actually lobbying for that but it's not bad, it's basically "map" + "concatenate"

23:19 _ato: ,(doc mapcat)

23:19 clojurebot: "([f & colls]); Returns the result of applying concat to the result of applying map to f and colls. Thus function f should return a collection."

23:19 livingston: and it has parity with mapcar (map through the car (first) elements of a list) which is clojure's map

23:21 yes mapcat is cl:mapcan - the 'n' was also used as a flag for being destructive in lisp, I don't know why.

23:27 I wished the compiler would warn at least on non-local non-special variable being present in a function - dumb me just lost 30 min because I cut and paste some code that used a different variable name

23:51 Derander: livingston: does seem like that should be possible to statically check

23:52 livingston: It's possible I've corrupted my repl enough too that it hallucinated a bound symbol there too, but yeah

Logging service provided by n01se.net